diff --git a/.gitignore b/.gitignore
index 5f0fead..6e053a5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -63,7 +63,7 @@
 /build/android/bin
 /build/Debug
 /build/Debug_x64
-/build/goma/client
+/build/goma
 /build/gomacc.lock
 /build/ipch/
 /build/Release
diff --git a/BUILD.gn b/BUILD.gn
index 0fa2013..0bb77f1 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -179,7 +179,6 @@
       "//mojo/common:mojo_common_unittests",
       "//mojo/edk/system:mojo_system_unittests",
       "//mojo/edk/test:mojo_public_bindings_unittests",
-      "//mojo/edk/test:mojo_public_environment_unittests",
       "//mojo/edk/test:mojo_public_system_unittests",
       "//mojo/edk/test:mojo_public_utility_unittests",
       "//mojo/shell/public/cpp",
diff --git a/DEPS b/DEPS
index 1a536c6f..4c0ee4d5 100644
--- a/DEPS
+++ b/DEPS
@@ -39,11 +39,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '706d21ffd03a0a446f7b997c801356abb891eaeb',
+  'skia_revision': 'bd590aa658a80d1646656289d802046a80f7c987',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': '609ae417e503d25c01b7284e1d1eab3ddd853b75',
+  'v8_revision': '18b482899e4a312477a4abe3591e58279e47aed9',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
@@ -185,7 +185,7 @@
     Var('chromium_git') + '/external/selenium/py.git' + '@' + '5fd78261a75fe08d27ca4835fb6c5ce4b42275bd',
 
   'src/third_party/libvpx/source/libvpx':
-   Var('chromium_git') + '/webm/libvpx.git' + '@' +  '89cc68252846478fa7f2d570d96ff93776cefac6',
+   Var('chromium_git') + '/webm/libvpx.git' + '@' +  '9aa083d164e0d39086aa0c83f0d1a0d0f0d1ba61',
 
   'src/third_party/ffmpeg':
    Var('chromium_git') + '/chromium/third_party/ffmpeg.git' + '@' + '60fc535386f97c6a0078738ba13ba3c4ef94ae01',
@@ -270,7 +270,7 @@
 
   'src/third_party/catapult':
     Var('chromium_git') + '/external/github.com/catapult-project/catapult.git' + '@' +
-    '271451854ad0fc877ee2ee2c380a0e30d00cb144',
+    '61904434b5f480f4d1509111b8e513d6dcb034ca',
 
   'src/third_party/openh264/src':
     Var('chromium_git') + '/external/github.com/cisco/openh264' + '@' + 'b37cda248234162033e3e11b0335f3131cdfe488',
@@ -815,21 +815,6 @@
     ],
   },
   {
-    'name': 'blimp_fonts',
-    'pattern': '\\.sha1',
-    'action': [ 'download_from_google_storage',
-                '--no_resume',
-                '--platform=linux*',
-                '--directory',
-                '--recursive',
-                '--quiet',
-                '--no_auth',
-                '--num_threads=16',
-                '--bucket', 'chromium-fonts',
-                'src/third_party/blimp_fonts',
-    ],
-  },
-  {
     # Pull sanitizer-instrumented third-party libraries if requested via
     # GYP_DEFINES.
     'name': 'instrumented_libraries',
diff --git a/base/metrics/histogram.cc b/base/metrics/histogram.cc
index 7feacdb..ea4f816 100644
--- a/base/metrics/histogram.cc
+++ b/base/metrics/histogram.cc
@@ -154,22 +154,10 @@
   ImportPersistentHistograms();
 
   HistogramBase* histogram = StatisticsRecorder::FindHistogram(name_);
-
-  // crbug.com/588946 debugging. See comment at end of function.
-  const BucketRanges* created_ranges =
-      reinterpret_cast<const BucketRanges*>(0xDEADBEEF);
-  const BucketRanges* registered_ranges =
-      reinterpret_cast<const BucketRanges*>(0xDEADBEEF);
-  HistogramBase* tentative_histogram =
-      reinterpret_cast<HistogramBase*>(0xDEADBEEF);
-  PersistentMemoryAllocator* allocator =
-      reinterpret_cast<PersistentMemoryAllocator*>(0xDEADBEEF);
-  PersistentMemoryAllocator::Reference histogram_ref = 0xDEADBEEF;
-
   if (!histogram) {
     // To avoid racy destruction at shutdown, the following will be leaked.
-    created_ranges = CreateRanges();
-    registered_ranges =
+    const BucketRanges* created_ranges = CreateRanges();
+    const BucketRanges* registered_ranges =
         StatisticsRecorder::RegisterOrDeleteDuplicateRanges(created_ranges);
 
     // In most cases, the bucket-count, minimum, and maximum values are known
@@ -182,17 +170,15 @@
       minimum_ = registered_ranges->range(1);
       maximum_ = registered_ranges->range(bucket_count_ - 1);
     }
-    CHECK_LT(0, minimum_);
-    CHECK_LT(0, maximum_);
 
     // Try to create the histogram using a "persistent" allocator. As of
     // 2015-01-14, the availability of such is controlled by a base::Feature
     // that is off by default. If the allocator doesn't exist or if
     // allocating from it fails, code below will allocate the histogram from
     // the process heap.
-    histogram_ref = 0;
-    tentative_histogram = nullptr;
-    allocator =
+    PersistentMemoryAllocator::Reference histogram_ref = 0;
+    HistogramBase* tentative_histogram = nullptr;
+    PersistentMemoryAllocator* allocator =
         GetPersistentHistogramMemoryAllocator();
     if (allocator) {
       flags_ |= HistogramBase::kIsPersistent;
@@ -205,12 +191,6 @@
           registered_ranges,
           flags_,
           &histogram_ref);
-      CHECK_LT(0, minimum_);
-      CHECK_LT(0, maximum_);
-      CHECK_EQ(minimum_,
-               static_cast<Histogram*>(tentative_histogram)->declared_min_);
-      CHECK_EQ(maximum_,
-               static_cast<Histogram*>(tentative_histogram)->declared_max_);
     }
 
     // Handle the case where no persistent allocator is present or the
@@ -220,12 +200,6 @@
       DCHECK(!allocator);  // Shouldn't have failed.
       flags_ &= ~HistogramBase::kIsPersistent;
       tentative_histogram = HeapAlloc(registered_ranges);
-      CHECK_LT(0, minimum_);
-      CHECK_LT(0, maximum_);
-      CHECK_EQ(minimum_,
-               static_cast<Histogram*>(tentative_histogram)->declared_min_);
-      CHECK_EQ(maximum_,
-               static_cast<Histogram*>(tentative_histogram)->declared_max_);
     }
 
     FillHistogram(tentative_histogram);
@@ -240,15 +214,6 @@
   }
 
   DCHECK_EQ(histogram_type_, histogram->GetHistogramType());
-  bool bad_args = false;
-  HistogramBase* existing_histogram = histogram;
-  HistogramType existing_type = histogram->GetHistogramType();
-  const char* existing_name = histogram->histogram_name().c_str();
-  Sample existing_minimum = static_cast<Histogram*>(histogram)->declared_min_;
-  Sample existing_maximum = static_cast<Histogram*>(histogram)->declared_max_;
-  uint32_t existing_bucket_count =
-    static_cast<Histogram*>(histogram)->bucket_count();
-
   if (bucket_count_ != 0 &&
       !histogram->HasConstructionArguments(minimum_, maximum_, bucket_count_)) {
     // The construction arguments do not match the existing histogram.  This can
@@ -258,45 +223,8 @@
     // on dereference, but extension/Pepper APIs will guard against NULL and not
     // crash.
     DLOG(ERROR) << "Histogram " << name_ << " has bad construction arguments";
-    bad_args = true;
-    histogram = nullptr;
+    return nullptr;
   }
-
-#if !DCHECK_IS_ON()  // Don't affect tests, only release builds.
-  // For the moment, crash here so that collected crash reports have access
-  // to the construction values in order to figure out why this is failing.
-  // TODO(bcwhite): Remove this once crbug.com/588946 is resolved. Also remove
-  // from beta-branch because we don't want crashes due to misbehaving
-  // extensions (see comment above).
-  if (!histogram) {
-    HistogramType histogram_type = histogram_type_;
-    HistogramBase::Sample minimum = minimum_;
-    HistogramBase::Sample maximum = maximum_;
-    uint32_t bucket_count = bucket_count_;
-    int32_t flags = flags_;
-    CHECK(histogram) << name_ << ": bad-args=" << bad_args;
-    base::debug::Alias(&histogram_type);
-    base::debug::Alias(&minimum);
-    base::debug::Alias(&maximum);
-    base::debug::Alias(&bucket_count);
-    base::debug::Alias(&flags);
-    base::debug::Alias(&created_ranges);
-    base::debug::Alias(&registered_ranges);
-    base::debug::Alias(&histogram_ref);
-    base::debug::Alias(&tentative_histogram);
-    base::debug::Alias(&allocator);
-    base::debug::Alias(&tentative_histogram);
-  }
-#endif
-
-  // Down here so vars are always "used".
-  base::debug::Alias(&bad_args);
-  base::debug::Alias(&existing_histogram);
-  base::debug::Alias(&existing_type);
-  base::debug::Alias(&existing_name);
-  base::debug::Alias(&existing_minimum);
-  base::debug::Alias(&existing_maximum);
-  base::debug::Alias(&existing_bucket_count);
   return histogram;
 }
 
@@ -558,12 +486,8 @@
     bucket_ranges_(ranges),
     declared_min_(minimum),
     declared_max_(maximum) {
-  CHECK_LT(0, minimum);
-  CHECK_LT(0, maximum);
   if (ranges)
     samples_.reset(new SampleVector(HashMetricName(name), ranges));
-  CHECK_EQ(minimum, declared_min_);
-  CHECK_EQ(maximum, declared_max_);
 }
 
 Histogram::Histogram(const std::string& name,
@@ -579,16 +503,12 @@
     bucket_ranges_(ranges),
     declared_min_(minimum),
     declared_max_(maximum) {
-  CHECK_LT(0, minimum);
-  CHECK_LT(0, maximum);
   if (ranges) {
     samples_.reset(new SampleVector(HashMetricName(name),
                                     counts, counts_size, meta, ranges));
     logged_samples_.reset(new SampleVector(samples_->id(), logged_counts,
                                            counts_size, logged_meta, ranges));
   }
-  CHECK_EQ(minimum, declared_min_);
-  CHECK_EQ(maximum, declared_max_);
 }
 
 Histogram::~Histogram() {
diff --git a/base/metrics/histogram_persistence.cc b/base/metrics/histogram_persistence.cc
index 8b946475..f18d175 100644
--- a/base/metrics/histogram_persistence.cc
+++ b/base/metrics/histogram_persistence.cc
@@ -288,8 +288,6 @@
   HistogramBase::AtomicCount* logged_data =
       counts_data + histogram_data.bucket_count;
 
-  CHECK_LT(0, histogram_data.minimum);
-  CHECK_LT(0, histogram_data.maximum);
   std::string name(histogram_data_ptr->name);
   HistogramBase* histogram = nullptr;
   switch (histogram_data.histogram_type) {
diff --git a/base/metrics/histogram_unittest.cc b/base/metrics/histogram_unittest.cc
index e6aefd3..beb6a71 100644
--- a/base/metrics/histogram_unittest.cc
+++ b/base/metrics/histogram_unittest.cc
@@ -668,7 +668,7 @@
   EXPECT_FALSE(iter.SkipBytes(1));
 }
 
-TEST_P(HistogramTest, DISABLED_BadConstruction) {
+TEST_P(HistogramTest, BadConstruction) {
   HistogramBase* histogram = Histogram::FactoryGet(
       "BadConstruction", 0, 100, 8, HistogramBase::kNoFlags);
   EXPECT_TRUE(histogram->HasConstructionArguments(1, 100, 8));
diff --git a/base/metrics/statistics_recorder.cc b/base/metrics/statistics_recorder.cc
index 90d64bb..d0fa2ad 100644
--- a/base/metrics/statistics_recorder.cc
+++ b/base/metrics/statistics_recorder.cc
@@ -5,7 +5,6 @@
 #include "base/metrics/statistics_recorder.h"
 
 #include "base/at_exit.h"
-#include "base/debug/alias.h"
 #include "base/debug/leak_annotations.h"
 #include "base/json/string_escape.h"
 #include "base/logging.h"
@@ -124,17 +123,13 @@
         histogram_to_return = histogram;
       } else {
         // We already have one histogram with this name.
-        CHECK_EQ(histogram->histogram_name(),
-                 it->second->histogram_name()) << "hash collision";
+        DCHECK_EQ(histogram->histogram_name(),
+                  it->second->histogram_name()) << "hash collision";
         histogram_to_return = it->second;
         histogram_to_delete = histogram;
       }
-      base::debug::Alias(&it);
-      base::debug::Alias(&name);
-      base::debug::Alias(&name_hash);
     }
   }
-  base::debug::Alias(&histogram);
   delete histogram_to_delete;
   return histogram_to_return;
 }
@@ -284,22 +279,10 @@
   if (histograms_ == NULL)
     return NULL;
 
-  const uint64_t lookup_hash = HashMetricName(name);
-  HistogramMap::iterator it = histograms_->find(lookup_hash);
+  HistogramMap::iterator it = histograms_->find(HashMetricName(name));
   if (histograms_->end() == it)
     return NULL;
-
-  const uint64_t existing_hash = it->first;
-  const char* existing_name = it->second->histogram_name().c_str();
-  HistogramMap* histograms = histograms_;
-  CHECK_EQ(name, it->second->histogram_name()) << "hash collision";
-  base::debug::Alias(&lookup_hash);
-  base::debug::Alias(&existing_hash);
-  base::debug::Alias(&name);
-  base::debug::Alias(&existing_name);
-  base::debug::Alias(&it);
-  base::debug::Alias(&histograms);
-
+  DCHECK_EQ(name, it->second->histogram_name()) << "hash collision";
   return it->second;
 }
 
diff --git a/blimp/README.md b/blimp/README.md
index 3ed48f9..adff5d3 100644
--- a/blimp/README.md
+++ b/blimp/README.md
@@ -14,10 +14,7 @@
 
 For running blimp, read more at [running](docs/running.md).
 
-## Updating Fonts
-
-For updating the fonts that blimp supports, read more at [fonts](docs/fonts.md).
-
 ## New to Markdown?
 
 For learning more about Markdown, read more at [markdown](docs/markdown.md).
+
diff --git a/blimp/docs/container.md b/blimp/docs/container.md
index 7a1902a..31adc80 100644
--- a/blimp/docs/container.md
+++ b/blimp/docs/container.md
@@ -43,7 +43,7 @@
 
 ```bash
 ./blimp/tools/generate-engine-manifest.py \
-    --build-dir out-chromeos/Debug \
+    --build-dir out-linux/Debug \
     --target //blimp/engine:blimp_engine \
     --output blimp/engine/engine-manifest.txt
 ```
@@ -56,7 +56,7 @@
 Using the tarfile you can create a Docker image:
 
 ```bash
-docker build -t blimp_engine - < ./out-chromeos/Debug/blimp_engine_bundle.tar.gz
+docker build -t blimp_engine - < ./out-linux/Debug/blimp_engine_bundle.tar
 ```
 
 ## Running the Engine in a Docker Container
@@ -74,8 +74,7 @@
     public certificate. Permissions should be set to 644.
 *   `$CONFIG_DIR/client_token`: A file with a non-empty string used as the
     client token (the shared secret between the client and the engine).
-    Permissions should also be set to 644. See [running](running.md) for how
-    to get the default token from the source code.
+    Persmissions should also be set to 644.
 
 This setup step is only required once and can be reused for all the rest of the
 runs of the engine.
@@ -95,3 +94,4 @@
 ```
 See the [blimp engine `Dockerfile`](../engine/Dockerfile) to find out what flags
 are passed by default.
+
diff --git a/blimp/docs/fonts.md b/blimp/docs/fonts.md
deleted file mode 100644
index 44b744f..0000000
--- a/blimp/docs/fonts.md
+++ /dev/null
@@ -1,39 +0,0 @@
-# Updating Blimp Fonts
-
-1.  Clone the git-repositories listed in
-    `//third_party/blimp_fonts/README.chromium`, and roll forward to the commit
-    you want.
-1.  Copy the necessary files to `//third_party/blimp_fonts`.
-1.  Verify that the `LICENSE` file is still up to date and lists all relevant
-    licenses and which fonts use which license.
-1.  Update the `//third_party/blimp_fonts:fonts` target to include all the
-    current fonts and their license files.
-1.  Update the engine dependencies using
-    `//blimp/tools/generate-engine-manifest.py`. This step is documented in
-    `//blimp/docs/container.md`.
-1.  Run the `upload_to_google_storage.py` (from depot_tools) script to upload
-    the files. To do this, execute:
-
-    ```bash
-    find ./third_party/blimp_fonts \
-        -regex '^.*.\(ttf\|otf\)$' -type f -print0 | \
-        upload_to_google_storage.py --use_null_terminator -b chromium-fonts -
-    ```
-
-    If the set of fonts includes more than `.ttf` or `.otf` files, you must
-    update the regular expression to include such fonts.
-1.  Verify that `//third_party/blimp_fonts/.gitignore` lists the correct files
-    to ignore.
-1.  Add all the `.sha1` files to the chromium src repository, by executing the
-    following command:
-
-    ```bash
-    git add ./third_party/blimp_fonts/*.sha1
-    ```
-
-1.  Commit and upload the change for review:
-
-    ```bash
-    git commit
-    git cl upload
-    ```
diff --git a/blimp/docs/running.md b/blimp/docs/running.md
index bb92199f..8accd3e 100644
--- a/blimp/docs/running.md
+++ b/blimp/docs/running.md
@@ -100,8 +100,6 @@
   compositor.
 * `--disable-cached-picture-raster`: Ensures that rasterized content is not
   destroyed before serialization.
-* `--android-fonts-path=$PATH`: Path to where the fonts are located.
-  Typically this would be `out-linux/Debug/gen/third_party/blimp_fonts`.
 
 #### Typical invocation
 When the client connects to a manually specified engine instead of using the
@@ -124,7 +122,6 @@
   --disable-cached-picture-raster \
   --blimp-client-token-path=/tmp/blimpengine-token \
   --user-data-dir=/tmp/blimpengine \
-  --android-fonts-path=out-linux/Debug/gen/third_party/blimp_fonts \
   --enable-logging=stderr \
   --vmodule="blimp*=1"
 ```
diff --git a/blimp/engine/BUILD.gn b/blimp/engine/BUILD.gn
index a19eb10..5bd4c21 100644
--- a/blimp/engine/BUILD.gn
+++ b/blimp/engine/BUILD.gn
@@ -223,7 +223,6 @@
       ":blimp_engine_app",
       ":pak",
       "//sandbox/linux:chrome_sandbox",
-      "//third_party/blimp_fonts",
     ]
 
     # List dependencies as both deps and data_deps to ensure changes trigger a
diff --git a/blimp/engine/DEPS b/blimp/engine/DEPS
index 5c16370..e4ebc4e 100644
--- a/blimp/engine/DEPS
+++ b/blimp/engine/DEPS
@@ -6,7 +6,6 @@
   "+components/web_cache/renderer",
   "+content/public",
   "+net",
-  "+third_party/blimp_fonts",
   "+third_party/khronos/GLES2/gl2.h",
   "+third_party/WebKit/public/web/WebInputEvent.h",
   "+ui/aura",
diff --git a/blimp/engine/Dockerfile b/blimp/engine/Dockerfile
index 7e3cbbaa..0410cf8 100644
--- a/blimp/engine/Dockerfile
+++ b/blimp/engine/Dockerfile
@@ -13,10 +13,7 @@
 
 RUN useradd -ms /bin/bash blimp_user
 
-# The glob below expands to all files, but does not add directories
-# recursively.
 ADD * /engine/
-ADD gen/third_party/blimp_fonts /engine/fonts
 RUN mv /engine/chrome_sandbox /engine/chrome-sandbox
 RUN chown -R blimp_user /engine
 
@@ -24,3 +21,4 @@
 WORKDIR "/engine"
 
 ENTRYPOINT ["/engine/start_engine.sh"]
+
diff --git a/blimp/engine/engine-manifest.txt b/blimp/engine/engine-manifest.txt
index b24bcc8b..d84b8f9 100644
--- a/blimp/engine/engine-manifest.txt
+++ b/blimp/engine/engine-manifest.txt
@@ -1,7 +1,7 @@
 # Runtime dependencies for the Blimp Engine
 #
 # This file was generated by running:
-# generate-engine-manifest.py --build-dir out-chromeos/Debug --target //blimp/engine:blimp_engine --output blimp/engine/engine-manifest.txt
+# generate-engine-manifest.py --build-dir out/Linux --target //blimp/engine:blimp_engine --output blimp/engine/engine-manifest.txt
 #
 # Note: Any unnecessary dependencies should be added to
 #       manifest-blacklist.txt and this file should be regenerated.
@@ -9,209 +9,4 @@
 icudtl.dat
 natives_blob.bin
 blimp_engine.pak
-./chrome_sandbox
-gen/third_party/blimp_fonts/AndroidClock.ttf
-gen/third_party/blimp_fonts/AndroidClock_Highlight.ttf
-gen/third_party/blimp_fonts/AndroidClock_Solid.ttf
-gen/third_party/blimp_fonts/CarroisGothicSC-Regular.ttf
-gen/third_party/blimp_fonts/Clockopia.ttf
-gen/third_party/blimp_fonts/ComingSoon.ttf
-gen/third_party/blimp_fonts/CutiveMono.ttf
-gen/third_party/blimp_fonts/DancingScript-Bold.ttf
-gen/third_party/blimp_fonts/DancingScript-Regular.ttf
-gen/third_party/blimp_fonts/DroidSansFallback.ttf
-gen/third_party/blimp_fonts/DroidSansFallbackFull.ttf
-gen/third_party/blimp_fonts/DroidSansMono.ttf
-gen/third_party/blimp_fonts/LICENSE
-gen/third_party/blimp_fonts/LICENSE.Apache
-gen/third_party/blimp_fonts/LICENSE.OFL
-gen/third_party/blimp_fonts/MTLc3m.ttf
-gen/third_party/blimp_fonts/MTLmr3m.ttf
-gen/third_party/blimp_fonts/NanumGothic.ttf
-gen/third_party/blimp_fonts/NanumGothicBold.ttf
-gen/third_party/blimp_fonts/NotoColorEmoji.ttf
-gen/third_party/blimp_fonts/NotoKufiArabic-Bold.ttf
-gen/third_party/blimp_fonts/NotoKufiArabic-Regular.ttf
-gen/third_party/blimp_fonts/NotoNaskhArabic-Bold.ttf
-gen/third_party/blimp_fonts/NotoNaskhArabic-Regular.ttf
-gen/third_party/blimp_fonts/NotoNaskhArabicUI-Bold.ttf
-gen/third_party/blimp_fonts/NotoNaskhArabicUI-Regular.ttf
-gen/third_party/blimp_fonts/NotoSans-Bold.ttf
-gen/third_party/blimp_fonts/NotoSans-BoldItalic.ttf
-gen/third_party/blimp_fonts/NotoSans-Italic.ttf
-gen/third_party/blimp_fonts/NotoSans-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansArmenian-Bold.ttf
-gen/third_party/blimp_fonts/NotoSansArmenian-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansAvestan-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansBalinese-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansBamum-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansBatak-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansBengali-Bold.ttf
-gen/third_party/blimp_fonts/NotoSansBengali-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansBengaliUI-Bold.ttf
-gen/third_party/blimp_fonts/NotoSansBengaliUI-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansBrahmi-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansBuginese-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansBuhid-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansCanadianAboriginal-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansCarian-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansCham-Bold.ttf
-gen/third_party/blimp_fonts/NotoSansCham-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansCherokee-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansCoptic-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansCuneiform-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansCypriot-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansDeseret-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansDevanagari-Bold.ttf
-gen/third_party/blimp_fonts/NotoSansDevanagari-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansDevanagariUI-Bold.ttf
-gen/third_party/blimp_fonts/NotoSansDevanagariUI-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansEgyptianHieroglyphs-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansEthiopic-Bold.ttf
-gen/third_party/blimp_fonts/NotoSansEthiopic-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansGeorgian-Bold.ttf
-gen/third_party/blimp_fonts/NotoSansGeorgian-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansGlagolitic-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansGothic-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansGujarati-Bold.ttf
-gen/third_party/blimp_fonts/NotoSansGujarati-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansGujaratiUI-Bold.ttf
-gen/third_party/blimp_fonts/NotoSansGujaratiUI-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansGurmukhi-Bold.ttf
-gen/third_party/blimp_fonts/NotoSansGurmukhi-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansGurmukhiUI-Bold.ttf
-gen/third_party/blimp_fonts/NotoSansGurmukhiUI-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansHanunoo-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansHebrew-Bold.ttf
-gen/third_party/blimp_fonts/NotoSansHebrew-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansImperialAramaic-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansInscriptionalPahlavi-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansInscriptionalParthian-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansJP-Regular-Subsetted.otf
-gen/third_party/blimp_fonts/NotoSansJP-Regular.otf
-gen/third_party/blimp_fonts/NotoSansJavanese-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansKR-Regular.otf
-gen/third_party/blimp_fonts/NotoSansKaithi-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansKannada-Bold.ttf
-gen/third_party/blimp_fonts/NotoSansKannada-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansKannadaUI-Bold.ttf
-gen/third_party/blimp_fonts/NotoSansKannadaUI-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansKayahLi-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansKharoshthi-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansKhmer-Bold.ttf
-gen/third_party/blimp_fonts/NotoSansKhmer-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansKhmerUI-Bold.ttf
-gen/third_party/blimp_fonts/NotoSansKhmerUI-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansLao-Bold.ttf
-gen/third_party/blimp_fonts/NotoSansLao-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansLaoUI-Bold.ttf
-gen/third_party/blimp_fonts/NotoSansLaoUI-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansLepcha-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansLimbu-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansLinearB-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansLisu-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansLycian-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansLydian-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansMalayalam-Bold.ttf
-gen/third_party/blimp_fonts/NotoSansMalayalam-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansMalayalamUI-Bold.ttf
-gen/third_party/blimp_fonts/NotoSansMalayalamUI-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansMandaic-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansMeeteiMayek-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansMongolian-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansMyanmar-Bold.ttf
-gen/third_party/blimp_fonts/NotoSansMyanmar-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansMyanmarUI-Bold.ttf
-gen/third_party/blimp_fonts/NotoSansMyanmarUI-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansNKo-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansNewTaiLue-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansOgham-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansOlChiki-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansOldItalic-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansOldPersian-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansOldSouthArabian-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansOldTurkic-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansOriya-Bold.ttf
-gen/third_party/blimp_fonts/NotoSansOriya-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansOriyaUI-Bold.ttf
-gen/third_party/blimp_fonts/NotoSansOriyaUI-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansOsmanya-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansPhagsPa-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansPhoenician-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansRejang-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansRunic-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansSC-Regular.otf
-gen/third_party/blimp_fonts/NotoSansSamaritan-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansSaurashtra-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansShavian-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansSinhala-Bold.ttf
-gen/third_party/blimp_fonts/NotoSansSinhala-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansSundanese-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansSylotiNagri-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansSymbols-Regular-Subsetted.ttf
-gen/third_party/blimp_fonts/NotoSansSymbols-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansSyriacEastern-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansSyriacEstrangela-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansSyriacWestern-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansTC-Regular.otf
-gen/third_party/blimp_fonts/NotoSansTagalog-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansTagbanwa-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansTaiLe-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansTaiTham-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansTaiViet-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansTamil-Bold.ttf
-gen/third_party/blimp_fonts/NotoSansTamil-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansTamilUI-Bold.ttf
-gen/third_party/blimp_fonts/NotoSansTamilUI-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansTelugu-Bold.ttf
-gen/third_party/blimp_fonts/NotoSansTelugu-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansTeluguUI-Bold.ttf
-gen/third_party/blimp_fonts/NotoSansTeluguUI-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansThaana-Bold.ttf
-gen/third_party/blimp_fonts/NotoSansThaana-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansThai-Bold.ttf
-gen/third_party/blimp_fonts/NotoSansThai-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansThaiUI-Bold.ttf
-gen/third_party/blimp_fonts/NotoSansThaiUI-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansTibetan-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansTifinagh-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansUI-Bold.ttf
-gen/third_party/blimp_fonts/NotoSansUI-BoldItalic.ttf
-gen/third_party/blimp_fonts/NotoSansUI-Italic.ttf
-gen/third_party/blimp_fonts/NotoSansUI-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansUgaritic-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansVai-Regular.ttf
-gen/third_party/blimp_fonts/NotoSansYi-Regular.ttf
-gen/third_party/blimp_fonts/NotoSerif-Bold.ttf
-gen/third_party/blimp_fonts/NotoSerif-BoldItalic.ttf
-gen/third_party/blimp_fonts/NotoSerif-Italic.ttf
-gen/third_party/blimp_fonts/NotoSerif-Regular.ttf
-gen/third_party/blimp_fonts/NotoSerifArmenian-Bold.ttf
-gen/third_party/blimp_fonts/NotoSerifArmenian-Regular.ttf
-gen/third_party/blimp_fonts/NotoSerifGeorgian-Bold.ttf
-gen/third_party/blimp_fonts/NotoSerifGeorgian-Regular.ttf
-gen/third_party/blimp_fonts/NotoSerifKhmer-Bold.ttf
-gen/third_party/blimp_fonts/NotoSerifKhmer-Regular.ttf
-gen/third_party/blimp_fonts/NotoSerifLao-Bold.ttf
-gen/third_party/blimp_fonts/NotoSerifLao-Regular.ttf
-gen/third_party/blimp_fonts/NotoSerifThai-Bold.ttf
-gen/third_party/blimp_fonts/NotoSerifThai-Regular.ttf
-gen/third_party/blimp_fonts/Roboto-Black.ttf
-gen/third_party/blimp_fonts/Roboto-BlackItalic.ttf
-gen/third_party/blimp_fonts/Roboto-Bold.ttf
-gen/third_party/blimp_fonts/Roboto-BoldItalic.ttf
-gen/third_party/blimp_fonts/Roboto-Italic.ttf
-gen/third_party/blimp_fonts/Roboto-Light.ttf
-gen/third_party/blimp_fonts/Roboto-LightItalic.ttf
-gen/third_party/blimp_fonts/Roboto-Medium.ttf
-gen/third_party/blimp_fonts/Roboto-MediumItalic.ttf
-gen/third_party/blimp_fonts/Roboto-Regular.ttf
-gen/third_party/blimp_fonts/Roboto-Thin.ttf
-gen/third_party/blimp_fonts/Roboto-ThinItalic.ttf
-gen/third_party/blimp_fonts/RobotoCondensed-Bold.ttf
-gen/third_party/blimp_fonts/RobotoCondensed-BoldItalic.ttf
-gen/third_party/blimp_fonts/RobotoCondensed-Italic.ttf
-gen/third_party/blimp_fonts/RobotoCondensed-Light.ttf
-gen/third_party/blimp_fonts/RobotoCondensed-LightItalic.ttf
-gen/third_party/blimp_fonts/RobotoCondensed-Regular.ttf
-gen/third_party/blimp_fonts/fonts.xml
\ No newline at end of file
+./chrome_sandbox
\ No newline at end of file
diff --git a/blimp/engine/start_engine.sh b/blimp/engine/start_engine.sh
index a9cf193..f507c24 100755
--- a/blimp/engine/start_engine.sh
+++ b/blimp/engine/start_engine.sh
@@ -8,12 +8,11 @@
   -p /engine/data/stunnel.pem \
   -P /engine/stunnel.pid \
   -d 25466 -r 25467 -f &
-LD_LIBRARY_PATH=/engine/ /engine/blimp_engine_app \
+/engine/blimp_engine_app \
   --disable-gpu \
   --use-remote-compositing \
   --disable-cached-picture-raster \
   --blimp-client-token-path=/engine/data/client_token \
-  --android-fonts-path=/engine/fonts \
   $@ &
 
 # Stop execution if either stunnel or blimp_engine_app die.
diff --git a/blimp/tools/manifest-blacklist.txt b/blimp/tools/manifest-blacklist.txt
index d21b052a..ce4c1c9b 100644
--- a/blimp/tools/manifest-blacklist.txt
+++ b/blimp/tools/manifest-blacklist.txt
@@ -2,11 +2,13 @@
 # Wildcards (* or ?) are allowed.
 
 *.mojo
-*mojom.js
 ./libfont_service_library.so
 ./libtracing_library.so
 ./libmus_library.so
 ./libosmesa.so
 ./libresource_provider_library.so
 ./mojo_runner
+gen/*
+mus/mus.mojo
 snapshot_blob.bin
+
diff --git a/build/all.gyp b/build/all.gyp
index 169bd5a..68a52f4a 100644
--- a/build/all.gyp
+++ b/build/all.gyp
@@ -54,10 +54,8 @@
             # javascript-related targets cause v8 to be built.
             '../mojo/mojo_base.gyp:mojo_common_lib',
             '../mojo/mojo_base.gyp:mojo_common_unittests',
-            '../mojo/mojo_base.gyp:mojo_environment_chromium',
             '../mojo/mojo_edk.gyp:mojo_system_impl',
             '../mojo/mojo_edk_tests.gyp:mojo_public_bindings_unittests',
-            '../mojo/mojo_edk_tests.gyp:mojo_public_environment_unittests',
             '../mojo/mojo_edk_tests.gyp:mojo_public_system_unittests',
             '../mojo/mojo_edk_tests.gyp:mojo_public_utility_unittests',
             '../mojo/mojo_edk_tests.gyp:mojo_system_unittests',
diff --git a/build/android/incremental_install/installer.py b/build/android/incremental_install/installer.py
index 2f60a9a..25a0295 100755
--- a/build/android/incremental_install/installer.py
+++ b/build/android/incremental_install/installer.py
@@ -86,7 +86,7 @@
 
 def Install(device, apk, split_globs=None, native_libs=None, dex_files=None,
             enable_device_cache=False, use_concurrency=True,
-            show_proguard_warning=False):
+            show_proguard_warning=False, permissions=()):
   """Installs the given incremental apk and all required supporting files.
 
   Args:
@@ -99,6 +99,8 @@
     use_concurrency: Whether to speed things up using multiple threads.
     show_proguard_warning: Whether to print a warning about Proguard not being
         enabled after installing.
+    permissions: A list of the permissions to grant, or None to grant all
+                 non-blacklisted permissions in the manifest.
   """
   main_timer = time_profile.TimeProfile()
   install_timer = time_profile.TimeProfile()
@@ -117,9 +119,9 @@
       for split_glob in split_globs:
         splits.extend((f for f in glob.glob(split_glob)))
       device.InstallSplitApk(apk, splits, reinstall=True,
-                             allow_cached_props=True, permissions=())
+                             allow_cached_props=True, permissions=permissions)
     else:
-      device.Install(apk, reinstall=True, permissions=())
+      device.Install(apk, reinstall=True, permissions=permissions)
     install_timer.Stop(log=False)
 
   # Push .so and .dex files to the device (if they have changed).
diff --git a/build/android/pylib/local/device/local_device_test_run.py b/build/android/pylib/local/device/local_device_test_run.py
index 4660b8e4..bf4bb65 100644
--- a/build/android/pylib/local/device/local_device_test_run.py
+++ b/build/android/pylib/local/device/local_device_test_run.py
@@ -33,7 +33,8 @@
   from incremental_install import installer
   installer.Install(device, apk_helper, split_globs=params['splits'],
                     native_libs=params['native_libs'],
-                    dex_files=params['dex_files'])
+                    dex_files=params['dex_files'],
+                    permissions=None)  # Auto-grant permissions from manifest.
 
 
 def handle_shard_failures(f):
diff --git a/build/android/resource_sizes.py b/build/android/resource_sizes.py
index c42a852..5374326 100755
--- a/build/android/resource_sizes.py
+++ b/build/android/resource_sizes.py
@@ -398,7 +398,7 @@
       PrintPakAnalysis(f, options.min_pak_resource_size, options.build_type)
 
   if chartjson:
-    results_path = os.path.join(options.outpur_dir, 'results-chart.json')
+    results_path = os.path.join(options.output_dir, 'results-chart.json')
     with open(results_path, 'w') as json_file:
       json.dump(chartjson, json_file)
 
diff --git a/build/gn_migration.gypi b/build/gn_migration.gypi
index d9211dee..924e533 100644
--- a/build/gn_migration.gypi
+++ b/build/gn_migration.gypi
@@ -283,7 +283,6 @@
             '../mojo/mojo.gyp:mojo',
             '../mojo/mojo_edk_tests.gyp:mojo_system_unittests',
             '../mojo/mojo_edk_tests.gyp:mojo_public_bindings_unittests',
-            '../mojo/mojo_edk_tests.gyp:mojo_public_environment_unittests',
             '../mojo/mojo_edk_tests.gyp:mojo_public_system_perftests',
             '../mojo/mojo_edk_tests.gyp:mojo_public_system_unittests',
             '../mojo/mojo_edk_tests.gyp:mojo_public_utility_unittests',
@@ -566,7 +565,6 @@
             '../media/media.gyp:media_unittests_run',
             '../media/midi/midi.gyp:midi_unittests_run',
             '../mojo/mojo_edk_tests.gyp:mojo_public_bindings_unittests_run',
-            '../mojo/mojo_edk_tests.gyp:mojo_public_environment_unittests_run',
             '../mojo/mojo_edk_tests.gyp:mojo_public_system_unittests_run',
             '../mojo/mojo_edk_tests.gyp:mojo_public_utility_unittests_run',
             '../net/net.gyp:net_unittests_run',
diff --git a/cc/scheduler/compositor_timing_history.cc b/cc/scheduler/compositor_timing_history.cc
index 3cbd32a..9d5a5844 100644
--- a/cc/scheduler/compositor_timing_history.cc
+++ b/cc/scheduler/compositor_timing_history.cc
@@ -72,9 +72,11 @@
 const double kActivateEstimationPercentile = 90.0;
 const double kDrawEstimationPercentile = 90.0;
 
+// Only log UMA histograms once every N frames to reduce the data volume.
+const int kUmaSamplingFrequency = 10;
 const int kUmaDurationMinMicros = 1;
-const int64_t kUmaDurationMaxMicros = 1 * base::Time::kMicrosecondsPerSecond;
-const size_t kUmaDurationBucketCount = 100;
+const int64_t kUmaDurationMaxMicros = base::Time::kMicrosecondsPerSecond / 5;
+const int kUmaDurationBucketCount = 100;
 
 // Deprecated because they combine Browser and Renderer stats and have low
 // precision.
@@ -357,6 +359,7 @@
     : using_synchronous_renderer_compositor_(
           using_synchronous_renderer_compositor),
       enabled_(false),
+      draw_count_(0),
       did_send_begin_main_frame_(false),
       begin_main_frame_needed_continuously_(false),
       begin_main_frame_committing_continuously_(false),
@@ -588,14 +591,16 @@
   // of our predictions.
   base::TimeDelta begin_main_frame_sent_to_commit_estimate =
       BeginMainFrameToCommitDurationEstimate();
-  uma_reporter_->AddBeginMainFrameToCommitDuration(
-      begin_main_frame_sent_to_commit_duration,
-      begin_main_frame_sent_to_commit_estimate, enabled_);
+  if (ShouldReportUma()) {
+    uma_reporter_->AddBeginMainFrameToCommitDuration(
+        begin_main_frame_sent_to_commit_duration,
+        begin_main_frame_sent_to_commit_estimate, enabled_);
+  }
   rendering_stats_instrumentation_->AddBeginMainFrameToCommitDuration(
       begin_main_frame_sent_to_commit_duration,
       begin_main_frame_sent_to_commit_estimate);
 
-  if (begin_main_frame_start_time_is_valid) {
+  if (ShouldReportUma() && begin_main_frame_start_time_is_valid) {
     if (begin_main_frame_on_critical_path_) {
       uma_reporter_->AddBeginMainFrameQueueDurationCriticalDuration(
           begin_main_frame_queue_duration, enabled_);
@@ -605,8 +610,10 @@
     }
   }
 
-  uma_reporter_->AddBeginMainFrameStartToCommitDuration(
-      begin_main_frame_start_to_commit_duration, enabled_);
+  if (ShouldReportUma()) {
+    uma_reporter_->AddBeginMainFrameStartToCommitDuration(
+        begin_main_frame_start_to_commit_duration, enabled_);
+  }
 
   if (enabled_) {
     begin_main_frame_sent_to_commit_duration_history_.InsertSample(
@@ -625,7 +632,7 @@
   }
 
   if (begin_main_frame_needed_continuously_) {
-    if (!begin_main_frame_end_time_prev_.is_null()) {
+    if (ShouldReportUma() && !begin_main_frame_end_time_prev_.is_null()) {
       base::TimeDelta commit_interval =
           begin_main_frame_end_time_ - begin_main_frame_end_time_prev_;
       if (begin_main_frame_on_critical_path_)
@@ -649,8 +656,10 @@
   DCHECK_NE(base::TimeTicks(), prepare_tiles_start_time_);
 
   base::TimeDelta prepare_tiles_duration = Now() - prepare_tiles_start_time_;
-  uma_reporter_->AddPrepareTilesDuration(
-      prepare_tiles_duration, PrepareTilesDurationEstimate(), enabled_);
+  if (ShouldReportUma()) {
+    uma_reporter_->AddPrepareTilesDuration(
+        prepare_tiles_duration, PrepareTilesDurationEstimate(), enabled_);
+  }
   if (enabled_)
     prepare_tiles_duration_history_.InsertSample(prepare_tiles_duration);
 
@@ -671,8 +680,10 @@
 
   base::TimeDelta commit_to_ready_to_activate_estimate =
       CommitToReadyToActivateDurationEstimate();
-  uma_reporter_->AddCommitToReadyToActivateDuration(
-      time_since_commit, commit_to_ready_to_activate_estimate, enabled_);
+  if (ShouldReportUma()) {
+    uma_reporter_->AddCommitToReadyToActivateDuration(
+        time_since_commit, commit_to_ready_to_activate_estimate, enabled_);
+  }
   rendering_stats_instrumentation_->AddCommitToActivateDuration(
       time_since_commit, commit_to_ready_to_activate_estimate);
 
@@ -693,8 +704,10 @@
   DCHECK_NE(base::TimeTicks(), activate_start_time_);
   base::TimeDelta activate_duration = Now() - activate_start_time_;
 
-  uma_reporter_->AddActivateDuration(activate_duration,
-                                     ActivateDurationEstimate(), enabled_);
+  if (ShouldReportUma()) {
+    uma_reporter_->AddActivateDuration(activate_duration,
+                                       ActivateDurationEstimate(), enabled_);
+  }
   if (enabled_)
     activate_duration_history_.InsertSample(activate_duration);
 
@@ -722,6 +735,7 @@
   DCHECK_NE(base::TimeTicks(), draw_start_time_);
   base::TimeTicks draw_end_time = Now();
   base::TimeDelta draw_duration = draw_end_time - draw_start_time_;
+  draw_count_++;
 
   // Before adding the new data point to the timing history, see what we would
   // have predicted for this frame. This allows us to keep track of the accuracy
@@ -730,14 +744,16 @@
   rendering_stats_instrumentation_->AddDrawDuration(draw_duration,
                                                     draw_estimate);
 
-  uma_reporter_->AddDrawDuration(draw_duration, draw_estimate, enabled_);
+  if (ShouldReportUma()) {
+    uma_reporter_->AddDrawDuration(draw_duration, draw_estimate, enabled_);
+  }
 
   if (enabled_) {
     draw_duration_history_.InsertSample(draw_duration);
   }
 
   SetCompositorDrawingContinuously(true);
-  if (!draw_end_time_prev_.is_null()) {
+  if (ShouldReportUma() && !draw_end_time_prev_.is_null()) {
     base::TimeDelta draw_interval = draw_end_time - draw_end_time_prev_;
     uma_reporter_->AddDrawInterval(draw_interval);
   }
@@ -748,14 +764,18 @@
     base::TimeDelta main_and_impl_delta =
         impl_frame_time - active_tree_main_frame_time_;
     DCHECK_GE(main_and_impl_delta, base::TimeDelta());
-    uma_reporter_->AddMainAndImplFrameTimeDelta(main_and_impl_delta);
+    if (ShouldReportUma()) {
+      uma_reporter_->AddMainAndImplFrameTimeDelta(main_and_impl_delta);
+    }
     active_tree_main_frame_time_ = base::TimeTicks();
 
     if (begin_main_frame_committing_continuously_) {
       if (!new_active_tree_draw_end_time_prev_.is_null()) {
         base::TimeDelta draw_interval =
             draw_end_time - new_active_tree_draw_end_time_prev_;
-        uma_reporter_->AddCommitInterval(draw_interval);
+        if (ShouldReportUma()) {
+          uma_reporter_->AddCommitInterval(draw_interval);
+        }
       }
       new_active_tree_draw_end_time_prev_ = draw_end_time;
     }
@@ -772,8 +792,14 @@
 void CompositorTimingHistory::DidSwapBuffersComplete() {
   DCHECK_NE(base::TimeTicks(), swap_start_time_);
   base::TimeDelta swap_to_ack_duration = Now() - swap_start_time_;
-  uma_reporter_->AddSwapToAckLatency(swap_to_ack_duration);
+  if (ShouldReportUma()) {
+    uma_reporter_->AddSwapToAckLatency(swap_to_ack_duration);
+  }
   swap_start_time_ = base::TimeTicks();
 }
 
+bool CompositorTimingHistory::ShouldReportUma() const {
+  return (draw_count_ % kUmaSamplingFrequency) == 0;
+}
+
 }  // namespace cc
diff --git a/cc/scheduler/compositor_timing_history.h b/cc/scheduler/compositor_timing_history.h
index a7c58dd..fc07c61 100644
--- a/cc/scheduler/compositor_timing_history.h
+++ b/cc/scheduler/compositor_timing_history.h
@@ -83,12 +83,17 @@
   void SetBeginMainFrameCommittingContinuously(bool active);
   void SetCompositorDrawingContinuously(bool active);
 
+  bool ShouldReportUma() const;
+
   static scoped_ptr<UMAReporter> CreateUMAReporter(UMACategory category);
   virtual base::TimeTicks Now() const;
 
   bool using_synchronous_renderer_compositor_;
   bool enabled_;
 
+  // Used to limit the recorded UMA data to once every N frames.
+  int draw_count_;
+
   // Used to calculate frame rates of Main and Impl threads.
   bool did_send_begin_main_frame_;
   bool begin_main_frame_needed_continuously_;
diff --git a/chrome/android/java/res/menu/chrome_context_menu.xml b/chrome/android/java/res/menu/chrome_context_menu.xml
index d2e2f7c..477ac1b 100644
--- a/chrome/android/java/res/menu/chrome_context_menu.xml
+++ b/chrome/android/java/res/menu/chrome_context_menu.xml
@@ -28,6 +28,8 @@
             android:title="@string/contextmenu_save_image"/>
         <item android:id="@+id/contextmenu_open_image"
             android:title="@string/contextmenu_open_image"/>
+        <item android:id="@+id/contextmenu_open_image_in_new_tab"
+            android:title="@string/contextmenu_open_image_in_new_tab"/>
         <!-- Title is set in Java. Suppress lint warning about missing title. -->
         <!--suppress MenuTitle -->
         <item android:id="@+id/contextmenu_search_by_image" />
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java
index 4e6240d..93e88fc 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java
@@ -47,7 +47,7 @@
             R.id.contextmenu_open_in_incognito_tab,
             R.id.contextmenu_save_link_as,
             R.id.contextmenu_load_original_image,
-            R.id.contextmenu_open_image,
+            R.id.contextmenu_open_image_in_new_tab,
             R.id.contextmenu_search_by_image,
     };
 
@@ -77,6 +77,7 @@
         static final int ACTION_SAVE_LINK = 5;
         static final int ACTION_SAVE_IMAGE = 6;
         static final int ACTION_OPEN_IMAGE = 7;
+        static final int ACTION_OPEN_IMAGE_IN_NEW_TAB = 8;
         static final int ACTION_SEARCH_BY_IMAGE = 11;
         static final int ACTION_LOAD_IMAGES = 12;
         static final int ACTION_LOAD_ORIGINAL_IMAGE = 13;
@@ -279,6 +280,9 @@
         } else if (itemId == R.id.contextmenu_open_image) {
             ContextMenuUma.record(params, ContextMenuUma.ACTION_OPEN_IMAGE);
             mDelegate.onOpenImageUrl(params.getSrcUrl(), params.getReferrer());
+        } else if (itemId == R.id.contextmenu_open_image_in_new_tab) {
+            ContextMenuUma.record(params, ContextMenuUma.ACTION_OPEN_IMAGE_IN_NEW_TAB);
+            mDelegate.onOpenImageInNewTab(params.getSrcUrl(), params.getReferrer());
         } else if (itemId == R.id.contextmenu_load_images) {
             ContextMenuUma.record(params, ContextMenuUma.ACTION_LOAD_IMAGES);
             DataReductionProxyUma.dataReductionProxyLoFiUIAction(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuItemDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuItemDelegate.java
index 5f087463..6dc2a465 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuItemDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuItemDelegate.java
@@ -63,6 +63,12 @@
     void onOpenImageUrl(String url, Referrer referrer);
 
     /**
+     * Called when the {@code url} is of an image and should be opened in a new tab.
+     * @param url The image URL to open.
+     */
+    void onOpenImageInNewTab(String url, Referrer referrer);
+
+    /**
      *  Reloads all the Lo-Fi images in a Tab.
      */
     void onReloadLoFiImages();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/ClientManager.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/ClientManager.java
index e65d295..5624ca48 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/ClientManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/ClientManager.java
@@ -52,6 +52,7 @@
         public final String packageName;
         public final ICustomTabsCallback callback;
         public final IBinder.DeathRecipient deathRecipient;
+        public boolean mIgnoreFragments;
         private boolean mShouldHideDomain;
         private ServiceConnection mKeepAliveConnection;
         private String mPredictedUrl;
@@ -258,6 +259,20 @@
         if (params != null) params.mShouldHideDomain = hide;
     }
 
+    /**
+     * @return Whether the fragment should be ignored for prerender matching.
+     */
+    public synchronized boolean getIgnoreFragmentsForSession(IBinder session) {
+        SessionParams params = mSessionParams.get(session);
+        return params == null ? false : params.mIgnoreFragments;
+    }
+
+    /** Sets whether the fragment should be ignored for prerender matching. */
+    public synchronized void setIgnoreFragmentsForSession(IBinder session, boolean value) {
+        SessionParams params = mSessionParams.get(session);
+        params.mIgnoreFragments = value;
+    }
+
     /** Tries to bind to a client to keep it alive, and returns true for success. */
     public synchronized boolean keepAliveForSession(IBinder session, Intent intent) {
         // When an application is bound to a service, its priority is raised to
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
index 9b44f6a..267814a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
@@ -57,6 +57,7 @@
 import org.chromium.chrome.browser.toolbar.ToolbarControlContainer;
 import org.chromium.chrome.browser.util.ColorUtils;
 import org.chromium.chrome.browser.util.IntentUtils;
+import org.chromium.chrome.browser.util.UrlUtilities;
 import org.chromium.chrome.browser.widget.findinpage.FindToolbarManager;
 import org.chromium.components.dom_distiller.core.DomDistillerUrlUtils;
 import org.chromium.content_public.browser.LoadUrlParams;
@@ -96,6 +97,9 @@
     private boolean mHasCreatedTabEarly;
     private CustomTabObserver mTabObserver;
 
+    private String mPrerenderedUrl;
+    private boolean mHasPrerendered;
+
     // Only the normal tab model is observed because there is no icognito tabmodel in Custom Tabs.
     private TabModelObserver mTabModelObserver = new EmptyTabModelObserver() {
         @Override
@@ -357,8 +361,11 @@
                 Tab.INVALID_TAB_ID, false, this, getWindowAndroid(),
                 TabLaunchType.FROM_EXTERNAL_APP, null, null);
         tab.setAppAssociatedWith(customTabsConnection.getClientPackageNameForSession(mSession));
+
+        mPrerenderedUrl = customTabsConnection.getPrerenderedUrl(mSession);
         WebContents webContents =
                 customTabsConnection.takePrerenderedUrl(mSession, url, referrerUrl);
+        mHasPrerendered = webContents != null;
         if (webContents == null) {
             webContents = customTabsConnection.takeSpareWebContents();
             // TODO(lizeb): Remove this once crbug.com/521729 is fixed.
@@ -431,6 +438,15 @@
      */
     private void loadUrlInTab(final Tab tab, final LoadUrlParams params, long timeStamp) {
         Intent intent = getIntent();
+        String url = IntentHandler.getUrlFromIntent(intent);
+        if (mHasPrerendered && UrlUtilities.urlsFragmentsDiffer(mPrerenderedUrl, url)) {
+            mHasPrerendered = false;
+            LoadUrlParams temporaryParams = new LoadUrlParams(mPrerenderedUrl);
+            IntentHandler.addReferrerAndHeaders(temporaryParams, intent, this);
+            tab.loadUrl(temporaryParams);
+            params.setShouldReplaceCurrentEntry(true);
+        }
+
         IntentHandler.addReferrerAndHeaders(params, intent, this);
         if (params.getReferrer() == null) {
             params.setReferrer(CustomTabsConnection.getInstance(getApplication())
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java
index 80efa2a..b996b5cf 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java
@@ -46,6 +46,7 @@
 import org.chromium.chrome.browser.prerender.ExternalPrerenderHandler;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.util.IntentUtils;
+import org.chromium.chrome.browser.util.UrlUtilities;
 import org.chromium.content.browser.ChildProcessLauncher;
 import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.content_public.browser.WebContents;
@@ -466,6 +467,11 @@
      * to call mayLaunchUrl(null) to cancel a current prerender before 2, that
      * is for a mispredict.
      *
+     * Note that this methods accepts URLs that don't exactly match the initially
+     * prerendered URL. More precisely, the #fragment is ignored. In this case,
+     * the client needs to navigate to the correct URL after the WebContents
+     * swap. This can be tested using {@link UrlUtilities#urlsFragmentsDiffer()}.
+     *
      * @param session The Binder object identifying a session.
      * @param url The URL the WebContents is for.
      * @param referrer The referrer to use for |url|.
@@ -480,8 +486,11 @@
         String prerenderedUrl = mPrerender.mUrl;
         String prerenderReferrer = mPrerender.mReferrer;
         if (referrer == null) referrer = "";
-        if (TextUtils.equals(prerenderedUrl, url)
-                && TextUtils.equals(prerenderReferrer, referrer)) {
+        boolean ignoreFragments = mClientManager.getIgnoreFragmentsForSession(session);
+        boolean urlsMatch = TextUtils.equals(prerenderedUrl, url)
+                || (ignoreFragments
+                        && UrlUtilities.urlsMatchIgnoringFragments(prerenderedUrl, url));
+        if (urlsMatch && TextUtils.equals(prerenderReferrer, referrer)) {
             mPrerender = null;
             return webContents;
         } else {
@@ -490,6 +499,14 @@
         return null;
     }
 
+    /** Returns the URL prerendered for a session, or null. */
+    String getPrerenderedUrl(IBinder session) {
+        if (mPrerender == null || session == null || !session.equals(mPrerender.mSession)) {
+            return null;
+        }
+        return mPrerender.mUrl;
+    }
+
     /** See {@link ClientManager#getReferrerForSession(IBinder)} */
     public Referrer getReferrerForSession(IBinder session) {
         return mClientManager.getReferrerForSession(session);
@@ -505,6 +522,16 @@
         return mClientManager.getClientPackageNameForSession(session);
     }
 
+    @VisibleForTesting
+    void setIgnoreUrlFragmentsForSession(IBinder session, boolean value) {
+        mClientManager.setIgnoreFragmentsForSession(session, value);
+    }
+
+    @VisibleForTesting
+    boolean getIgnoreUrlFragmentsForSession(IBinder session) {
+        return mClientManager.getIgnoreFragmentsForSession(session);
+    }
+
     /**
      * Shows a toast about any possible sign in issues encountered during custom tab startup.
      * @param session The session that corresponding custom tab is assigned.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabContextMenuItemDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabContextMenuItemDelegate.java
index 6873f39..06fc49d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabContextMenuItemDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabContextMenuItemDelegate.java
@@ -27,6 +27,9 @@
  * A default {@link ContextMenuItemDelegate} that supports the context menu functionality in Tab.
  */
 public class TabContextMenuItemDelegate implements ContextMenuItemDelegate {
+    public static final String PAGESPEED_PASSTHROUGH_HEADERS =
+            "Chrome-Proxy: pass-through\nCache-Control: no-cache";
+
     private final Clipboard mClipboard;
     private final Tab mTab;
 
@@ -108,6 +111,16 @@
     }
 
     @Override
+    public void onOpenImageInNewTab(String url, Referrer referrer) {
+        boolean useOriginal = isSpdyProxyEnabledForUrl(url);
+        LoadUrlParams loadUrlParams = new LoadUrlParams(url);
+        loadUrlParams.setVerbatimHeaders(useOriginal ? PAGESPEED_PASSTHROUGH_HEADERS : null);
+        loadUrlParams.setReferrer(referrer);
+        mTab.getActivity().getTabModelSelector().openNewTab(loadUrlParams,
+                TabLaunchType.FROM_LONGPRESS_BACKGROUND, mTab, isIncognito());
+    }
+
+    @Override
     public void onOpenInChrome(String linkUrl, String pageUrl) {
         Intent chromeIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(linkUrl));
         chromeIntent.setPackage(mTab.getApplicationContext().getPackageName());
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/util/UrlUtilities.java b/chrome/android/java/src/org/chromium/chrome/browser/util/UrlUtilities.java
index d0be1c3..30be076 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/util/UrlUtilities.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/util/UrlUtilities.java
@@ -217,6 +217,20 @@
         return nativeGetDomainAndRegistry(uri, includePrivateRegistries);
     }
 
+    /** @return whether two URLs match, ignoring the #fragment. */
+    @VisibleForTesting
+    public static boolean urlsMatchIgnoringFragments(String url, String url2) {
+        if (TextUtils.equals(url, url2)) return true;
+        return nativeUrlsMatchIgnoringFragments(url, url2);
+    }
+
+    /** @return whether the #fragmant differs in two URLs. */
+    @VisibleForTesting
+    public static boolean urlsFragmentsDiffer(String url, String url2) {
+        if (TextUtils.equals(url, url2)) return false;
+        return nativeUrlsFragmentsDiffer(url, url2);
+    }
+
     // Patterns used in validateIntentUrl.
     private static final Pattern DNS_HOSTNAME_PATTERN =
             Pattern.compile("^[\\w\\.-]*$");
@@ -385,4 +399,6 @@
     public static native String nativeFormatUrlForSecurityDisplay(String url);
     public static native String nativeFormatUrlForSecurityDisplayOmitScheme(String url);
     private static native String nativeFixupUrl(String url, String desiredTld);
+    private static native boolean nativeUrlsMatchIgnoringFragments(String url, String url2);
+    private static native boolean nativeUrlsFragmentsDiffer(String url, String url2);
 }
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd
index c5ec0b1..161bc8b 100644
--- a/chrome/android/java/strings/android_chrome_strings.grd
+++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -1310,6 +1310,9 @@
       <message name="IDS_CONTEXTMENU_OPEN_IMAGE" desc="Context sensitive menu item for opening/viewing the selected image. [CHAR-LIMIT=30]">
         Open image
       </message>
+      <message name="IDS_CONTEXTMENU_OPEN_IMAGE_IN_NEW_TAB" desc="Context sensitive menu item for opening/viewing the selected image in a new tab. [CHAR-LIMIT=30]">
+        Open image in new tab
+      </message>
       <message name="IDS_CONTEXTMENU_LOAD_IMAGES" desc="Context sensitive menu item for Data Saver low fidelity placeholder images that reloads the page with the original images. [CHAR-LIMIT=30]">
         Load images
       </message>
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/GeolocationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/GeolocationTest.java
index 1bbc8115..ede3387 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/GeolocationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/GeolocationTest.java
@@ -8,6 +8,7 @@
 import android.test.suitebuilder.annotation.MediumTest;
 import android.test.suitebuilder.annotation.Smoke;
 
+import org.chromium.base.test.util.DisableIf;
 import org.chromium.base.test.util.Feature;
 import org.chromium.chrome.browser.infobar.InfoBarContainer;
 import org.chromium.chrome.browser.tab.EmptyTabObserver;
@@ -97,6 +98,7 @@
     @Smoke
     @MediumTest
     @Feature({"Location", "Main"})
+    @DisableIf.Build(sdk_is_greater_than = 22, message = "crbug.com/592953")
     public void testGeolocationPlumbing() throws Exception {
         final String url = mTestServer.getURL(TEST_FILE);
 
@@ -119,6 +121,7 @@
      */
     @MediumTest
     @Feature({"Location"})
+    @DisableIf.Build(sdk_is_greater_than = 22, message = "crbug.com/592953")
     public void testGeolocationWatch() throws Exception {
         final String url = mTestServer.getURL(TEST_FILE);
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/overlays/strip/TabStripTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/overlays/strip/TabStripTest.java
index fe58bd7..3d060ec9 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/overlays/strip/TabStripTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/overlays/strip/TabStripTest.java
@@ -5,6 +5,7 @@
 package org.chromium.chrome.browser.compositor.overlays.strip;
 
 import android.content.pm.ActivityInfo;
+import android.test.FlakyTest;
 import android.test.suitebuilder.annotation.LargeTest;
 
 import org.chromium.base.ThreadUtils;
@@ -78,6 +79,7 @@
     @LargeTest
     @Restriction(ChromeRestriction.RESTRICTION_TYPE_TABLET)
     @Feature({"TabStrip"})
+    @FlakyTest // crbug.com/592961
     public void testNewTabButtonWithManyTabs() throws InterruptedException {
         ChromeTabUtils.newTabsFromMenu(getInstrumentation(), getActivity(), 3);
         getInstrumentation().runOnMainSync(new Runnable() {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuTest.java
index bf400dc2..6b3b3bb 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuTest.java
@@ -13,7 +13,6 @@
 import android.view.ContextMenu;
 import android.view.KeyEvent;
 
-import org.chromium.base.ThreadUtils;
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.DisableIf;
 import org.chromium.base.test.util.Feature;
@@ -22,19 +21,20 @@
 import org.chromium.chrome.browser.compositor.layouts.LayoutManager;
 import org.chromium.chrome.browser.download.DownloadTestBase;
 import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.tabmodel.EmptyTabModelSelectorObserver;
 import org.chromium.chrome.browser.tabmodel.TabModel;
+import org.chromium.chrome.test.util.ChromeTabUtils;
 import org.chromium.chrome.test.util.browser.contextmenu.ContextMenuUtils;
+import org.chromium.content.browser.test.util.CallbackHelper;
 import org.chromium.content.browser.test.util.Criteria;
 import org.chromium.content.browser.test.util.CriteriaHelper;
 import org.chromium.content.browser.test.util.DOMUtils;
-import org.chromium.content.browser.test.util.TestCallbackHelperContainer;
-import org.chromium.content.browser.test.util.TestCallbackHelperContainer.OnPageFinishedHelper;
 import org.chromium.content.browser.test.util.TestTouchUtils;
 import org.chromium.net.test.EmbeddedTestServer;
 
 import java.io.IOException;
-import java.util.concurrent.Callable;
 import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicReference;
 
 /**
  * Context menu related tests
@@ -111,57 +111,51 @@
 
     @MediumTest
     @Feature({"Browser"})
+    @CommandLineFlags.Add(ChromeSwitches.DISABLE_DOCUMENT_MODE)
     public void testLongPressOnImage() throws InterruptedException, TimeoutException {
-        final Tab tab = getActivity().getActivityTab();
-
-        TestCallbackHelperContainer helper =
-                new TestCallbackHelperContainer(tab.getContentViewCore());
-
-        OnPageFinishedHelper callback = helper.getOnPageFinishedHelper();
-        int callbackCount = callback.getCallCount();
-
-        ContextMenuUtils.selectContextMenuItem(this, tab, "testImage",
-                R.id.contextmenu_open_image);
-
-        callback.waitForCallback(callbackCount);
-
-        String expectedUrl = mTestServer.getURL(
-                "/chrome/test/data/android/contextmenu/test_image.png");
-
-        String actualUrl = ThreadUtils.runOnUiThreadBlockingNoException(new Callable<String>() {
-            @Override
-            public String call() throws Exception {
-                return tab.getUrl();
-            }
-        });
-
-        assertEquals("Failed to navigate to the image", expectedUrl, actualUrl);
+        checkOpenImageInNewTab(
+                "testImage", "/chrome/test/data/android/contextmenu/test_image.png");
     }
 
     @MediumTest
     @Feature({"Browser"})
+    @CommandLineFlags.Add(ChromeSwitches.DISABLE_DOCUMENT_MODE)
     public void testLongPressOnImageLink() throws InterruptedException, TimeoutException {
-        final Tab tab = getActivity().getActivityTab();
+        checkOpenImageInNewTab(
+                "testImageLink", "/chrome/test/data/android/contextmenu/test_image.png");
+    }
 
-        TestCallbackHelperContainer helper =
-                new TestCallbackHelperContainer(tab.getContentViewCore());
+    private void checkOpenImageInNewTab(String domId, String expectedUrl)
+            throws InterruptedException, TimeoutException {
+        final Tab activityTab = getActivity().getActivityTab();
 
-        OnPageFinishedHelper callback = helper.getOnPageFinishedHelper();
-        int callbackCount = callback.getCallCount();
-
-        ContextMenuUtils.selectContextMenuItem(this, tab, "testImage",
-                R.id.contextmenu_open_image);
-
-        callback.waitForCallback(callbackCount);
-
-        String actualTitle = ThreadUtils.runOnUiThreadBlockingNoException(new Callable<String>() {
+        final CallbackHelper newTabCallback = new CallbackHelper();
+        final AtomicReference<Tab> newTab = new AtomicReference<>();
+        getActivity().getTabModelSelector().addObserver(new EmptyTabModelSelectorObserver() {
             @Override
-            public String call() throws Exception {
-                return tab.getTitle();
+            public void onNewTabCreated(Tab tab) {
+                super.onNewTabCreated(tab);
+
+                if (tab.getParentId() != activityTab.getId()) return;
+                newTab.set(tab);
+                newTabCallback.notifyCalled();
+
+                getActivity().getTabModelSelector().removeObserver(this);
             }
         });
 
-        assertTrue("Navigated to the wrong page.", actualTitle.startsWith("test_image.png"));
+        int callbackCount = newTabCallback.getCallCount();
+
+        ContextMenuUtils.selectContextMenuItem(this, activityTab, domId,
+                R.id.contextmenu_open_image_in_new_tab);
+
+        try {
+            newTabCallback.waitForCallback(callbackCount);
+        } catch (TimeoutException ex) {
+            fail("New tab never created from context menu press");
+        }
+
+        ChromeTabUtils.waitForTabPageLoaded(newTab.get(), mTestServer.getURL(expectedUrl));
     }
 
     @MediumTest
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
index f5d133d..3cd7597 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
@@ -29,6 +29,7 @@
 import android.support.customtabs.CustomTabsIntent;
 import android.support.customtabs.ICustomTabsCallback;
 import android.test.suitebuilder.annotation.SmallTest;
+import android.text.TextUtils;
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.View;
@@ -63,6 +64,7 @@
 import org.chromium.content.browser.test.util.Criteria;
 import org.chromium.content.browser.test.util.CriteriaHelper;
 import org.chromium.content.browser.test.util.DOMUtils;
+import org.chromium.content.browser.test.util.JavaScriptUtils;
 import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.net.test.EmbeddedTestServer;
 
@@ -100,6 +102,7 @@
             TEST_ACTION = "org.chromium.chrome.browser.customtabs.TEST_PENDING_INTENT_SENT";
     private static final String TEST_PAGE = "/chrome/test/data/android/google.html";
     private static final String TEST_PAGE_2 = "/chrome/test/data/android/test.html";
+    private static final String FRAGMENT_TEST_PAGE = "/chrome/test/data/android/fragment.html";
     private static final String TEST_MENU_TITLE = "testMenuTitle";
 
     private static int sIdToIncrement = 1;
@@ -772,6 +775,109 @@
     }
 
     /**
+     * Tests the following scenario:
+     * - warmup() + mayLaunchUrl("http://example.com/page.html#first-fragment")
+     * - loadUrl("http://example.com/page.html#other-fragment")
+     *
+     * The expected behavior is that the prerender shouldn't be dropped, and that the fragment is
+     * updated.
+     */
+    @SmallTest
+    @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE)
+    public void testPrerenderingAndChangingFragmentIgnoreFragments() throws Exception {
+        prerenderAndChangeFragment(true, true);
+    }
+
+    /** Same as above, but the prerender matching should not ignore the fragment. */
+    @SmallTest
+    @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE)
+    public void testPrerenderingAndChangingFragmentDontIgnoreFragments() throws Exception {
+        prerenderAndChangeFragment(false, true);
+    }
+
+    /** Same as above, prerender matching ignores the fragment, don't wait. */
+    @SmallTest
+    @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE)
+    public void testPrerenderingAndChangingFragmentDontWait() throws Exception {
+        prerenderAndChangeFragment(true, false);
+    }
+
+    /** Same as above, prerender matching doesn't ignore the fragment, don't wait. */
+    @SmallTest
+    @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE)
+    public void testPrerenderingAndChangingFragmentDontWaitDrop() throws Exception {
+        prerenderAndChangeFragment(false, false);
+    }
+
+    /**
+     * Tests the following scenario:
+     * - warmup() + mayLaunchUrl("http://example.com/page.html#first-fragment")
+     * - loadUrl("http://example.com/page.html#other-fragment")
+     *
+     * There are two parameters changing the bahavior:
+     * @param ignoreFragments Whether the prerender should be kept.
+     * @param wait Whether to wait for the prerender to load.
+     *
+     * The prerender state is assessed through monitoring the properties of the test page.
+     */
+    private void prerenderAndChangeFragment(boolean ignoreFragments, boolean wait)
+            throws Exception {
+        String testUrl = mTestServer.getURL(FRAGMENT_TEST_PAGE);
+        String initialFragment = "#test";
+        final String initialUrl = testUrl + initialFragment;
+        String fragment = "#yeah";
+        String urlWithFragment = testUrl + fragment;
+
+        Context context = getInstrumentation().getTargetContext().getApplicationContext();
+        final CustomTabsConnection connection = warmUpAndWait();
+        ICustomTabsCallback cb = new CustomTabsTestUtils.DummyCallback();
+        connection.newSession(cb);
+        connection.setIgnoreUrlFragmentsForSession(cb.asBinder(), ignoreFragments);
+        assertTrue(connection.mayLaunchUrl(cb, Uri.parse(initialUrl), null, null));
+
+        if (wait) {
+            // Check that there is a prerender.
+            CriteriaHelper.pollForUIThreadCriteria(new Criteria("No Prerender") {
+                @Override
+                public boolean isSatisfied() {
+                    return connection.mPrerender != null
+                            && connection.mPrerender.mWebContents != null
+                            && ExternalPrerenderHandler.hasPrerenderedAndFinishedLoadingUrl(
+                                    Profile.getLastUsedProfile(), initialUrl,
+                                    connection.mPrerender.mWebContents);
+                }
+            });
+        }
+
+        try {
+            startCustomTabActivityWithIntent(CustomTabsTestUtils.createMinimalCustomTabIntent(
+                    context, urlWithFragment, cb.asBinder()));
+        } catch (InterruptedException e) {
+            fail();
+        }
+        final Tab tab = mActivity.getActivityTab();
+        ElementContentCriteria initialVisibilityCriteria = new ElementContentCriteria(
+                tab, "visibility", ignoreFragments ? "prerender" : "visible");
+        ElementContentCriteria initialFragmentCriteria = new ElementContentCriteria(
+                tab, "initial-fragment", ignoreFragments ? initialFragment : fragment);
+        ElementContentCriteria fragmentCriteria = new ElementContentCriteria(
+                tab, "fragment", fragment);
+
+        if (wait) {
+            // The tab hasn't been reloaded.
+            CriteriaHelper.pollForCriteria(initialVisibilityCriteria, 2000, 200);
+            // No reload (initial fragment is correct).
+            CriteriaHelper.pollForCriteria(initialFragmentCriteria, 2000, 200);
+            if (ignoreFragments) CriteriaHelper.pollForCriteria(fragmentCriteria, 2000, 200);
+        } else {
+            CriteriaHelper.pollForCriteria(new ElementContentCriteria(
+                    tab, "initial-fragment", fragment), 2000, 200);
+        }
+        assertFalse(tab.canGoForward());
+        assertFalse(tab.canGoBack());
+    }
+
+    /**
      * Test whether the url shown on prerender gets updated from about:blank when the prerender
      * completes in the background.
      * Non-regression test for crbug.com/554236.
@@ -908,4 +1014,33 @@
             }
         }
     }
+
+    private static class ElementContentCriteria extends Criteria {
+        private final Tab mTab;
+        private final String mJsFunction;
+        private final String mExpected;
+
+        public ElementContentCriteria(Tab tab, String elementId, String expected) {
+            super("Page element is not as expected.");
+            mTab = tab;
+            mExpected = "\"" + expected + "\"";
+            mJsFunction = "(function () { return document.getElementById(\"" + elementId
+                    + "\").innerHTML; })()";
+        }
+
+        @Override
+        public boolean isSatisfied() {
+            String value = null;
+            try {
+                String jsonText = JavaScriptUtils.executeJavaScriptAndWaitForResult(
+                        mTab.getWebContents(), mJsFunction);
+                if (jsonText.equalsIgnoreCase("null")) jsonText = "";
+                value = jsonText;
+            } catch (InterruptedException | TimeoutException e) {
+                e.printStackTrace();
+                return false;
+            }
+            return TextUtils.equals(mExpected, value);
+        }
+    }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadTest.java
index 5551d68..15e3d85b 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadTest.java
@@ -10,6 +10,7 @@
 
 import org.chromium.base.Log;
 import org.chromium.base.test.util.CommandLineFlags;
+import org.chromium.base.test.util.DisableIf;
 import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Feature;
 import org.chromium.chrome.R;
@@ -58,6 +59,7 @@
 
     @MediumTest
     @Feature({"Downloads"})
+    @DisableIf.Build(sdk_is_greater_than = 22, message = "crbug.com/591224")
     public void testHttpGetDownload() throws Exception {
         loadUrl(mTestServer.getURL("/chrome/test/data/android/download/get.html"));
         waitForFocus();
@@ -74,6 +76,7 @@
 
     @MediumTest
     @Feature({"Downloads"})
+    @DisableIf.Build(sdk_is_greater_than = 22, message = "crbug.com/591224")
     public void testDangerousDownload() throws Exception {
         loadUrl(mTestServer.getURL("/chrome/test/data/android/download/dangerous.html"));
         waitForFocus();
@@ -91,6 +94,7 @@
 
     @MediumTest
     @Feature({"Downloads"})
+    @DisableIf.Build(sdk_is_greater_than = 22, message = "crbug.com/591224")
     public void testHttpPostDownload() throws Exception {
         loadUrl(mTestServer.getURL("/chrome/test/data/android/download/post.html"));
         waitForFocus();
@@ -133,6 +137,7 @@
 
     @MediumTest
     @Feature({"Downloads"})
+    @DisableIf.Build(sdk_is_greater_than = 22, message = "crbug.com/591224")
     public void testDuplicateHttpPostDownload_Overwrite() throws Exception {
         // Download a file.
         loadUrl(mTestServer.getURL("/chrome/test/data/android/download/post.html"));
@@ -162,6 +167,7 @@
 
     @MediumTest
     @Feature({"Downloads"})
+    @DisableIf.Build(sdk_is_greater_than = 22, message = "crbug.com/591224")
     public void testDuplicateHttpPostDownload_CreateNew() throws Exception {
         // Download a file.
         loadUrl(mTestServer.getURL("/chrome/test/data/android/download/post.html"));
@@ -194,6 +200,7 @@
     */
     @MediumTest
     @Feature({"Downloads"})
+    @DisableIf.Build(sdk_is_greater_than = 22, message = "crbug.com/591224")
     public void testDuplicateHttpPostDownload_Dismiss() throws Exception {
         // Download a file.
         loadUrl(mTestServer.getURL("/chrome/test/data/android/download/post.html"));
@@ -223,6 +230,7 @@
 
     @MediumTest
     @Feature({"Downloads"})
+    @DisableIf.Build(sdk_is_greater_than = 22, message = "crbug.com/591224")
     public void testDuplicateHttpPostDownload_AllowMultipleInfoBars() throws Exception {
         assertFalse(hasDownload("superbo.txt", SUPERBO_CONTENTS));
         // Download a file.
@@ -318,6 +326,7 @@
     @CommandLineFlags.Add(ChromeSwitches.DISABLE_DOCUMENT_MODE)
     @MediumTest
     @Feature({"Downloads"})
+    @DisableIf.Build(sdk_is_greater_than = 22, message = "crbug.com/591224")
     public void testDuplicateHttpPostDownload_OpenNewTabAndReplace() throws Exception {
         final String url =
                 mTestServer.getURL("/chrome/test/data/android/download/get.html");
@@ -356,6 +365,7 @@
 
     @MediumTest
     @Feature({"Downloads"})
+    @DisableIf.Build(sdk_is_greater_than = 22, message = "crbug.com/591224")
     public void testUrlEscaping() throws Exception {
         loadUrl(mTestServer.getURL("/chrome/test/data/android/download/urlescaping.html"));
         waitForFocus();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/InfoBarTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/InfoBarTest.java
index f4f6cdd..73b06a42 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/InfoBarTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/InfoBarTest.java
@@ -12,6 +12,7 @@
 
 import org.chromium.base.CommandLine;
 import org.chromium.base.ThreadUtils;
+import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.UrlUtils;
 import org.chromium.chrome.browser.ChromeActivity;
@@ -87,6 +88,7 @@
     @Smoke
     @MediumTest
     @Feature({"Browser", "Main"})
+    @DisabledTest // crbug.com/593003
     public void testInfoBarForPopUp() throws InterruptedException {
         loadUrl(mTestServer.getURL(POPUP_PAGE));
         assertTrue("InfoBar not added", mListener.addInfoBarAnimationFinished());
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java
index 5a8d04f..829f4fa94 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java
@@ -13,6 +13,7 @@
 import android.view.ViewGroup;
 
 import org.chromium.base.ThreadUtils;
+import org.chromium.base.test.util.DisableIf;
 import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Feature;
 import org.chromium.chrome.R;
@@ -128,6 +129,7 @@
      */
     @SmallTest
     @Feature({"NewTabPage"})
+    @DisableIf.Build(sdk_is_greater_than = 22, message = "crbug.com/593007")
     public void testSearchFromFakebox() throws InterruptedException {
         singleClickView(mFakebox);
         waitForFakeboxFocusAnimationComplete(mNtp);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/UndoTabModelTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/UndoTabModelTest.java
index f2e99c6..db27686 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/UndoTabModelTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/UndoTabModelTest.java
@@ -4,6 +4,7 @@
 
 package org.chromium.chrome.browser.tabmodel;
 
+import android.test.FlakyTest;
 import android.test.suitebuilder.annotation.MediumTest;
 
 import org.chromium.base.ThreadUtils;
@@ -996,6 +997,7 @@
      * @throws InterruptedException
      */
     @MediumTest
+    @FlakyTest // crbug.com/592969
     public void testOutOfOrder2() throws InterruptedException {
         TabModel model = getActivity().getTabModelSelector().getModel(false);
         ChromeTabCreator tabCreator = getActivity().getTabCreator(false);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/util/UrlUtilitiesTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/util/UrlUtilitiesTest.java
index bfd8f4c3..10a35fb 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/util/UrlUtilitiesTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/util/UrlUtilitiesTest.java
@@ -11,6 +11,7 @@
 
 import java.net.URI;
 
+/** Tests for {@link UrlUtilities}. */
 public class UrlUtilitiesTest extends NativeLibraryTestBase {
     @SmallTest
     public void testIsAcceptedScheme() {
@@ -177,4 +178,27 @@
                 + "S.goat=&leg;end"));
     }
 
+    @SmallTest
+    public void testUrlsMatchIgnoringFragments() {
+        loadNativeLibraryNoBrowserProcess();
+
+        String url = "http://www.example.com/path";
+        assertTrue(UrlUtilities.urlsMatchIgnoringFragments(url, url));
+        assertTrue(UrlUtilities.urlsMatchIgnoringFragments(url + "#fragment", url));
+        assertTrue(UrlUtilities.urlsMatchIgnoringFragments(url + "#fragment", url + "#fragment2"));
+        assertTrue(UrlUtilities.urlsMatchIgnoringFragments("HTTP://www.example.com/path"
+                        + "#fragment",
+                url + "#fragment2"));
+        assertFalse(UrlUtilities.urlsMatchIgnoringFragments(
+                url + "#fragment", "http://example.com:443/path#fragment"));
+    }
+
+    @SmallTest
+    public void testUrlsFragmentsDiffer() {
+        loadNativeLibraryNoBrowserProcess();
+
+        String url = "http://www.example.com/path";
+        assertFalse(UrlUtilities.urlsFragmentsDiffer(url, url));
+        assertTrue(UrlUtilities.urlsFragmentsDiffer(url + "#fragment", url));
+    }
 }
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 08a164f8..60d76318 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -5522,12 +5522,20 @@
       <message name="IDS_FLAGS_WEBRTC_STUN_ORIGIN_DESCRIPTION" desc="Description of chrome:flags option to turn on Origin header for WebRTC STUN messages">
         When enabled, Stun messages generated by WebRTC will contain the Origin header.
       </message>
+      <if expr="enable_webrtc">
+        <message name="IDS_FLAGS_WEBRTC_H264_WITH_OPENH264_FFMPEG_NAME" desc="Name of chrome:flags option to enable WebRTC H.264 sw encoder/decoder">
+          WebRTC H.264 software video encoder/decoder
+        </message>
+        <message name="IDS_FLAGS_WEBRTC_H264_WITH_OPENH264_FFMPEG_DESCRIPTION" desc="Description of chrome:flags option to enable WebRTC H.264 sw encoder/decoder">
+          When enabled, an H.264 software video encoder/decoder pair is included. (If a hardware decoder is also available it may be used instead of this decoder).
+        </message>
+      </if>
       <message name="IDS_FLAGS_WEBVR_NAME" desc="Name of the 'Enable WebVR' flag.">
         WebVR
       </message>
       <message name="IDS_FLAGS_WEBVR_DESCRIPTION" desc="Description for the flag to enable WebVR APIs.">
         Enabling this option allows web applications to access experimental Virtual Reality APIs.
-      </message>     
+      </message>
       <message name="IDS_FLAGS_COMPOSITING_FOR_FIXED_POSITION_NAME" desc="Name of the 'Compositing for fixed position elements' lab.">
         Compositing for fixed position elements.
       </message>
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index ae1bfa97..db1a329 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -190,6 +190,8 @@
     "//components/webdata_services",
     "//content/public/browser",
     "//content/public/common",
+    "//content/public/common:feature_h264_with_openh264_ffmpeg",
+    "//content/public/common:features",
     "//courgette:courgette_lib",
     "//crypto",
     "//google_apis",
@@ -365,7 +367,6 @@
       "//media/midi",
       "//mojo/common",
       "//mojo/edk/system",
-      "//mojo/environment:chromium",
       "//mojo/public/cpp/bindings",
       "//mojo/public/js",
       "//mojo/shell/public/cpp",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 6ec41ea..ff41b43 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -57,6 +57,8 @@
 #include "content/public/browser/user_metrics.h"
 #include "content/public/common/content_features.h"
 #include "content/public/common/content_switches.h"
+#include "content/public/common/feature_h264_with_openh264_ffmpeg.h"
+#include "content/public/common/features.h"
 #include "grit/components_strings.h"
 #include "media/base/media_switches.h"
 #include "media/midi/midi_switches.h"
@@ -1786,13 +1788,20 @@
 #if defined(ENABLE_EXTENSIONS)
     {"enable-tab-for-desktop-share", IDS_FLAG_ENABLE_TAB_FOR_DESKTOP_SHARE,
      IDS_FLAG_ENABLE_TAB_FOR_DESKTOP_SHARE_DESCRIPTION, kOsAll,
-     SINGLE_VALUE_TYPE(extensions::switches::kEnableTabForDesktopShare)}
+     SINGLE_VALUE_TYPE(extensions::switches::kEnableTabForDesktopShare)},
 #endif
 #if defined(OS_ANDROID)
     {"enable-ntp-snippets", IDS_FLAGS_ENABLE_NTP_SNIPPETS_NAME,
      IDS_FLAGS_ENABLE_NTP_SNIPPETS_DESCRIPTION, kOsAndroid,
      FEATURE_VALUE_TYPE(chrome::android::kNTPSnippetsFeature)},
 #endif  // defined(OS_ANDROID)
+#if defined(ENABLE_WEBRTC) && BUILDFLAG(RTC_USE_H264)
+    {"enable-webrtc-h264-with-openh264-ffmpeg",
+     IDS_FLAGS_WEBRTC_H264_WITH_OPENH264_FFMPEG_NAME,
+     IDS_FLAGS_WEBRTC_H264_WITH_OPENH264_FFMPEG_DESCRIPTION,
+     kOsDesktop,
+     FEATURE_VALUE_TYPE(content::kWebRtcH264WithOpenH264FFmpeg)},
+#endif  // defined(ENABLE_WEBRTC) && BUILDFLAG(RTC_USE_H264)
 #if defined(OS_ANDROID)
     {"ime-thread", IDS_FLAGS_IME_THREAD_NAME,
      IDS_FLAGS_IME_THREAD_DESCRIPTION, kOsAndroid,
diff --git a/chrome/browser/android/url_utilities.cc b/chrome/browser/android/url_utilities.cc
index 1a3b6739..a70609fe 100644
--- a/chrome/browser/android/url_utilities.cc
+++ b/chrome/browser/android/url_utilities.cc
@@ -126,6 +126,36 @@
              : ScopedJavaLocalRef<jstring>();
 }
 
+static jboolean UrlsMatchIgnoringFragments(JNIEnv* env,
+                                           const JavaParamRef<jclass>& clazz,
+                                           const JavaParamRef<jstring>& url,
+                                           const JavaParamRef<jstring>& url2) {
+  GURL gurl = ConvertJavaStringToGURL(env, url);
+  GURL gurl2 = ConvertJavaStringToGURL(env, url2);
+  if (gurl.is_empty())
+    return gurl2.is_empty();
+  if (!gurl.is_valid() || !gurl2.is_valid())
+    return false;
+
+  GURL::Replacements replacements;
+  replacements.SetRefStr("");
+  return gurl.ReplaceComponents(replacements) ==
+         gurl2.ReplaceComponents(replacements);
+}
+
+static jboolean UrlsFragmentsDiffer(JNIEnv* env,
+                                    const JavaParamRef<jclass>& clazz,
+                                    const JavaParamRef<jstring>& url,
+                                    const JavaParamRef<jstring>& url2) {
+  GURL gurl = ConvertJavaStringToGURL(env, url);
+  GURL gurl2 = ConvertJavaStringToGURL(env, url2);
+  if (gurl.is_empty())
+    return !gurl2.is_empty();
+  if (!gurl.is_valid() || !gurl2.is_valid())
+    return true;
+  return gurl.ref() != gurl2.ref();
+}
+
 // Register native methods
 bool RegisterUrlUtilities(JNIEnv* env) {
   return RegisterNativesImpl(env);
diff --git a/chrome/browser/custom_handlers/protocol_handler_registry_unittest.cc b/chrome/browser/custom_handlers/protocol_handler_registry_unittest.cc
index 8dfd2f7b..94251aa 100644
--- a/chrome/browser/custom_handlers/protocol_handler_registry_unittest.cc
+++ b/chrome/browser/custom_handlers/protocol_handler_registry_unittest.cc
@@ -234,9 +234,8 @@
   if (state == shell_integration::STATE_IS_DEFAULT) {
     delegate->FakeRegisterWithOS(protocol);
   }
-  if (state != shell_integration::STATE_PROCESSING) {
-    base::MessageLoop::current()->QuitWhenIdle();
-  }
+
+  base::MessageLoop::current()->QuitWhenIdle();
 }
 
 void FakeDelegate::RegisterWithOSAsDefaultClient(
diff --git a/chrome/browser/extensions/api/metrics_private/metrics_apitest.cc b/chrome/browser/extensions/api/metrics_private/metrics_apitest.cc
index d4c5e3c..3160400 100644
--- a/chrome/browser/extensions/api/metrics_private/metrics_apitest.cc
+++ b/chrome/browser/extensions/api/metrics_private/metrics_apitest.cc
@@ -128,7 +128,7 @@
 
 }  // anonymous namespace
 
-IN_PROC_BROWSER_TEST_F(ExtensionApiTest, DISABLED_Metrics) {
+IN_PROC_BROWSER_TEST_F(ExtensionApiTest, Metrics) {
   base::UserActionTester user_action_tester;
 
   base::FieldTrialList::CreateFieldTrial("apitestfieldtrial2", "group1");
diff --git a/chrome/browser/extensions/extension_service_unittest.cc b/chrome/browser/extensions/extension_service_unittest.cc
index a68d8f9..19db4d8 100644
--- a/chrome/browser/extensions/extension_service_unittest.cc
+++ b/chrome/browser/extensions/extension_service_unittest.cc
@@ -69,6 +69,9 @@
 #include "chrome/browser/extensions/updater/extension_updater.h"
 #include "chrome/browser/policy/profile_policy_connector.h"
 #include "chrome/browser/policy/profile_policy_connector_factory.h"
+#include "chrome/browser/ui/global_error/global_error.h"
+#include "chrome/browser/ui/global_error/global_error_service.h"
+#include "chrome/browser/ui/global_error/global_error_service_factory.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/extensions/api/plugins/plugins_handler.h"
@@ -193,8 +196,26 @@
 const char theme2_crx[] = "pjpgmfcmabopnnfonnhmdjglfpjjfkbf";
 const char permissions_crx[] = "eagpmdpfmaekmmcejjbmjoecnejeiiin";
 const char updates_from_webstore[] = "akjooamlhcgeopfifcmlggaebeocgokj";
+const char updates_from_webstore2[] = "oolblhbomdbcpmafphaodhjfcgbihcdg";
+const char updates_from_webstore3[] = "bmfoocgfinpmkmlbjhcbofejhkhlbchk";
 const char permissions_blocklist[] = "noffkehfcaggllbcojjbopcmlhcnhcdn";
 
+struct BubbleErrorsTestData {
+  BubbleErrorsTestData(const std::string& id,
+                       const std::string& version,
+                       const base::FilePath& crx_path,
+                       size_t expected_bubble_error_count)
+      : id(id),
+        version(version),
+        crx_path(crx_path),
+        expected_bubble_error_count(expected_bubble_error_count) {}
+  std::string id;
+  std::string version;
+  base::FilePath crx_path;
+  size_t expected_bubble_error_count;
+  bool expect_has_shown_bubble_view;
+};
+
 static void AddPattern(URLPatternSet* extent, const std::string& pattern) {
   int schemes = URLPattern::SCHEME_ALL;
   extent->AddPattern(URLPattern(schemes, pattern));
@@ -225,6 +246,15 @@
   return found != errors.end();
 }
 
+size_t GetExternalInstallBubbleCount(ExtensionService* service) {
+  size_t bubble_count = 0u;
+  std::vector<ExternalInstallError*> errors =
+      service->external_install_manager()->GetErrorsForTesting();
+  for (const auto& error : errors)
+    bubble_count += error->alert_type() == ExternalInstallError::BUBBLE_ALERT;
+  return bubble_count;
+}
+
 }  // namespace
 
 class MockExtensionProvider : public extensions::ExternalProviderInterface {
@@ -6073,6 +6103,221 @@
   EXPECT_FALSE(HasExternalInstallErrors(service_));
 }
 
+TEST_F(ExtensionServiceTest, MultipleExternalInstallBubbleErrors) {
+  FeatureSwitch::ScopedOverride prompt(
+      FeatureSwitch::prompt_for_external_extensions(), true);
+  // This sets up the ExtensionPrefs used by our ExtensionService to be
+  // post-first run.
+  ExtensionServiceInitParams params = CreateDefaultInitParams();
+  params.is_first_run = false;
+  InitializeExtensionService(params);
+
+  MockExtensionProvider* provider =
+      new MockExtensionProvider(service(), Manifest::EXTERNAL_PREF);
+  AddMockExternalProvider(provider);
+
+  std::vector<BubbleErrorsTestData> data;
+  data.push_back(
+      BubbleErrorsTestData(updates_from_webstore, "1",
+                           temp_dir().path().AppendASCII("webstore.crx"), 1u));
+  data.push_back(
+      BubbleErrorsTestData(updates_from_webstore2, "1",
+                           temp_dir().path().AppendASCII("webstore2.crx"), 2u));
+  data.push_back(BubbleErrorsTestData(good_crx, "1.0.0.0",
+                                      data_dir().AppendASCII("good.crx"), 2u));
+
+  PackCRX(data_dir().AppendASCII("update_from_webstore"),
+          data_dir().AppendASCII("update_from_webstore.pem"), data[0].crx_path);
+  PackCRX(data_dir().AppendASCII("update_from_webstore2"),
+          data_dir().AppendASCII("update_from_webstore2.pem"),
+          data[1].crx_path);
+
+  // Install extensions from |data| one by one and expect each of them to result
+  // in an error. The first two extensions are from webstore, so they will
+  // trigger BUBBLE_ALERT type errors. After each step, we verify that we got
+  // the expected number of errors in external_install_manager(). We also verify
+  // that only the first BUBBLE_ALERT error is shown.
+  for (size_t i = 0; i < data.size(); ++i) {
+    content::WindowedNotificationObserver global_error_observer(
+        chrome::NOTIFICATION_GLOBAL_ERRORS_CHANGED,
+        content::NotificationService::AllSources());
+    content::WindowedNotificationObserver observer(
+        extensions::NOTIFICATION_CRX_INSTALLER_DONE,
+        content::NotificationService::AllSources());
+    provider->UpdateOrAddExtension(data[i].id, data[i].version,
+                                   data[i].crx_path);
+    service()->CheckForExternalUpdates();
+    observer.Wait();
+    // Make sure ExternalInstallError::OnDialogReady() fires.
+    global_error_observer.Wait();
+
+    const size_t expected_error_count = i + 1u;
+    std::vector<ExternalInstallError*> errors =
+        service_->external_install_manager()->GetErrorsForTesting();
+    EXPECT_EQ(expected_error_count, errors.size());
+    EXPECT_EQ(data[i].expected_bubble_error_count,
+              GetExternalInstallBubbleCount(service()));
+    EXPECT_TRUE(service()
+                    ->external_install_manager()
+                    ->has_currently_visible_install_alert());
+    // Make sure that the first error is only being shown.
+    EXPECT_EQ(errors[0], service()
+                             ->external_install_manager()
+                             ->currently_visible_install_alert_for_testing());
+    EXPECT_FALSE(service()->IsExtensionEnabled(data[i].id));
+  }
+
+  // Cancel all the install prompts.
+  for (size_t i = 0; i < data.size(); ++i) {
+    const std::string& extension_id = data[i].id;
+    EXPECT_TRUE(GetError(extension_id));
+    GetError(extension_id)
+        ->OnInstallPromptDone(ExtensionInstallPrompt::Result::USER_CANCELED);
+    EXPECT_FALSE(GetError(extension_id));
+  }
+  EXPECT_FALSE(service()
+                   ->external_install_manager()
+                   ->has_currently_visible_install_alert());
+  EXPECT_EQ(0u, GetExternalInstallBubbleCount(service()));
+  EXPECT_FALSE(HasExternalInstallErrors(service()));
+
+  // Add a new webstore install. Verify that this shows an error bubble since
+  // there are no error bubbles pending at this point. Also verify that the
+  // error bubble is for this newly added extension.
+  {
+    base::FilePath webstore_crx_three =
+        temp_dir().path().AppendASCII("webstore3.crx");
+    PackCRX(data_dir().AppendASCII("update_from_webstore3"),
+            data_dir().AppendASCII("update_from_webstore3.pem"),
+            webstore_crx_three);
+
+    content::WindowedNotificationObserver global_error_observer(
+        chrome::NOTIFICATION_GLOBAL_ERRORS_CHANGED,
+        content::NotificationService::AllSources());
+    content::WindowedNotificationObserver observer(
+        extensions::NOTIFICATION_CRX_INSTALLER_DONE,
+        content::NotificationService::AllSources());
+    provider->UpdateOrAddExtension(
+        updates_from_webstore3, "1",
+        temp_dir().path().AppendASCII("webstore3.crx"));
+    service()->CheckForExternalUpdates();
+    observer.Wait();
+    // Make sure ExternalInstallError::OnDialogReady() fires.
+    global_error_observer.Wait();
+
+    std::vector<ExternalInstallError*> errors =
+        service_->external_install_manager()->GetErrorsForTesting();
+    EXPECT_EQ(1u, errors.size());
+    EXPECT_EQ(1u, GetExternalInstallBubbleCount(service()));
+    EXPECT_TRUE(service()
+                    ->external_install_manager()
+                    ->has_currently_visible_install_alert());
+    // Verify that the visible alert is for the current error.
+    EXPECT_EQ(errors[0], service()
+                             ->external_install_manager()
+                             ->currently_visible_install_alert_for_testing());
+    EXPECT_FALSE(service()->IsExtensionEnabled(updates_from_webstore3));
+  }
+}
+
+// Verifies that an error alert of type BUBBLE_ALERT does not replace an
+// existing visible alert that was previously opened by clicking menu item.
+TEST_F(ExtensionServiceTest, BubbleAlertDoesNotHideAnotherAlertFromMenu) {
+  FeatureSwitch::ScopedOverride prompt(
+      FeatureSwitch::prompt_for_external_extensions(), true);
+  // This sets up the ExtensionPrefs used by our ExtensionService to be
+  // post-first run.
+  ExtensionServiceInitParams params = CreateDefaultInitParams();
+  params.is_first_run = false;
+  InitializeExtensionService(params);
+
+  MockExtensionProvider* provider =
+      new MockExtensionProvider(service(), Manifest::EXTERNAL_PREF);
+  AddMockExternalProvider(provider);
+
+  std::vector<BubbleErrorsTestData> data;
+  data.push_back(
+      BubbleErrorsTestData(updates_from_webstore, "1",
+                           temp_dir().path().AppendASCII("webstore.crx"), 1u));
+  data.push_back(
+      BubbleErrorsTestData(updates_from_webstore2, "1",
+                           temp_dir().path().AppendASCII("webstore2.crx"), 2u));
+
+  PackCRX(data_dir().AppendASCII("update_from_webstore"),
+          data_dir().AppendASCII("update_from_webstore.pem"), data[0].crx_path);
+  PackCRX(data_dir().AppendASCII("update_from_webstore2"),
+          data_dir().AppendASCII("update_from_webstore2.pem"),
+          data[1].crx_path);
+  {
+    content::WindowedNotificationObserver global_error_observer(
+        chrome::NOTIFICATION_GLOBAL_ERRORS_CHANGED,
+        content::NotificationService::AllSources());
+    content::WindowedNotificationObserver observer(
+        extensions::NOTIFICATION_CRX_INSTALLER_DONE,
+        content::NotificationService::AllSources());
+    provider->UpdateOrAddExtension(data[0].id, data[0].version,
+                                   data[0].crx_path);
+    service()->CheckForExternalUpdates();
+    observer.Wait();
+    // Make sure ExternalInstallError::OnDialogReady() fires.
+    global_error_observer.Wait();
+
+    std::vector<ExternalInstallError*> errors =
+        service_->external_install_manager()->GetErrorsForTesting();
+    EXPECT_EQ(1u, errors.size());
+    EXPECT_EQ(1u, GetExternalInstallBubbleCount(service()));
+    EXPECT_TRUE(service()
+                    ->external_install_manager()
+                    ->has_currently_visible_install_alert());
+    // Verify that the visible alert is for the current error.
+    EXPECT_EQ(errors[0], service()
+                             ->external_install_manager()
+                             ->currently_visible_install_alert_for_testing());
+  }
+
+  ExternalInstallError* first_extension_error = GetError(data[0].id);
+
+  // Close the bubble alert.
+  GlobalError* global_error =
+      GlobalErrorServiceFactory::GetForProfile(profile())
+          ->GetHighestSeverityGlobalErrorWithAppMenuItem();
+  first_extension_error->DidCloseBubbleView();
+
+  // Bring the bubble alert error again by clicking its menu item.
+  global_error->ExecuteMenuItem(nullptr);
+
+  // Install another webstore extension that will trigger an erorr of type
+  // BUBBLE_ALERT.
+  // Make sure that this bubble alert does not replace the current bubble alert.
+  {
+    content::WindowedNotificationObserver global_error_observer(
+        chrome::NOTIFICATION_GLOBAL_ERRORS_CHANGED,
+        content::NotificationService::AllSources());
+    content::WindowedNotificationObserver observer(
+        extensions::NOTIFICATION_CRX_INSTALLER_DONE,
+        content::NotificationService::AllSources());
+    provider->UpdateOrAddExtension(data[1].id, data[1].version,
+                                   data[1].crx_path);
+    service()->CheckForExternalUpdates();
+    observer.Wait();
+    // Make sure ExternalInstallError::OnDialogReady() fires.
+    global_error_observer.Wait();
+
+    std::vector<ExternalInstallError*> errors =
+        service_->external_install_manager()->GetErrorsForTesting();
+    EXPECT_EQ(2u, errors.size());
+    EXPECT_EQ(2u, GetExternalInstallBubbleCount(service()));
+    EXPECT_TRUE(service()
+                    ->external_install_manager()
+                    ->has_currently_visible_install_alert());
+    // Verify that the old bubble alert was *not* replaced by the new alert.
+    EXPECT_EQ(first_extension_error,
+              service()
+                  ->external_install_manager()
+                  ->currently_visible_install_alert_for_testing());
+  }
+}
+
 // Test that there is a bubble for external extensions that update
 // from the webstore if the profile is not new.
 TEST_F(ExtensionServiceTest, ExternalInstallUpdatesFromWebstoreOldProfile) {
diff --git a/chrome/browser/extensions/external_install_error.cc b/chrome/browser/extensions/external_install_error.cc
index 8280d3e..640faa9 100644
--- a/chrome/browser/extensions/external_install_error.cc
+++ b/chrome/browser/extensions/external_install_error.cc
@@ -197,7 +197,10 @@
 }
 
 void ExternalInstallBubbleAlert::ExecuteMenuItem(Browser* browser) {
-  ShowBubbleView(browser);
+  // |browser| is nullptr in unit test.
+  if (browser)
+    ShowBubbleView(browser);
+  error_->DidOpenBubbleView();
 }
 
 gfx::Image ExternalInstallBubbleAlert::GetBubbleViewIcon() {
@@ -264,6 +267,7 @@
 }
 
 void ExternalInstallBubbleAlert::OnBubbleViewDidClose(Browser* browser) {
+  error_->DidCloseBubbleView();
 }
 
 void ExternalInstallBubbleAlert::BubbleViewAcceptButtonPressed(
@@ -339,11 +343,20 @@
       }
       break;
     case ExtensionInstallPrompt::Result::ABORTED:
+      manager_->DidChangeInstallAlertVisibility(this, false);
       break;
   }
   // NOTE: We may be deleted here!
 }
 
+void ExternalInstallError::DidOpenBubbleView() {
+  manager_->DidChangeInstallAlertVisibility(this, true);
+}
+
+void ExternalInstallError::DidCloseBubbleView() {
+  manager_->DidChangeInstallAlertVisibility(this, false);
+}
+
 void ExternalInstallError::ShowDialog(Browser* browser) {
   DCHECK(install_ui_.get());
   DCHECK(prompt_.get());
@@ -352,6 +365,7 @@
   web_contents = browser->tab_strip_model()->GetActiveWebContents();
   install_ui_show_params_.reset(
       new ExtensionInstallPromptShowParams(web_contents));
+  manager_->DidChangeInstallAlertVisibility(this, true);
   ExtensionInstallPrompt::GetDefaultShowDialogCallback().Run(
       install_ui_show_params_.get(),
       base::Bind(&ExternalInstallError::OnInstallPromptDone,
@@ -422,10 +436,16 @@
     global_error_.reset(new ExternalInstallBubbleAlert(this, prompt_.get()));
     error_service_->AddGlobalError(global_error_.get());
 
-    Browser* browser = chrome::FindTabbedBrowser(
-        Profile::FromBrowserContext(browser_context_), true);
-    if (browser)
-      global_error_->ShowBubbleView(browser);
+    if (!manager_->has_currently_visible_install_alert()) {
+      // |browser| is nullptr during unit tests, so call
+      // DidChangeInstallAlertVisibility() regardless because we depend on this
+      // in unit tests.
+      manager_->DidChangeInstallAlertVisibility(this, true);
+      Browser* browser = chrome::FindTabbedBrowser(
+          Profile::FromBrowserContext(browser_context_), true);
+      if (browser)
+        global_error_->ShowBubbleView(browser);
+    }
   } else {
     DCHECK(alert_type_ == MENU_ALERT);
     global_error_.reset(new ExternalInstallMenuAlert(this));
diff --git a/chrome/browser/extensions/external_install_error.h b/chrome/browser/extensions/external_install_error.h
index abb06974..a74288b8 100644
--- a/chrome/browser/extensions/external_install_error.h
+++ b/chrome/browser/extensions/external_install_error.h
@@ -52,6 +52,9 @@
 
   void OnInstallPromptDone(ExtensionInstallPrompt::Result result);
 
+  void DidOpenBubbleView();
+  void DidCloseBubbleView();
+
   // Show the associated dialog. This should only be called once the dialog is
   // ready.
   void ShowDialog(Browser* browser);
diff --git a/chrome/browser/extensions/external_install_manager.cc b/chrome/browser/extensions/external_install_manager.cc
index 3908e49..70737e83 100644
--- a/chrome/browser/extensions/external_install_manager.cc
+++ b/chrome/browser/extensions/external_install_manager.cc
@@ -62,6 +62,7 @@
     : browser_context_(browser_context),
       is_first_run_(is_first_run),
       extension_prefs_(ExtensionPrefs::Get(browser_context_)),
+      currently_visible_install_alert_(nullptr),
       extension_registry_observer_(this) {
   DCHECK(browser_context_);
   extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context_));
@@ -94,8 +95,14 @@
 
 void ExternalInstallManager::RemoveExternalInstallError(
     const std::string& extension_id) {
-  if (errors_.erase(extension_id) > 0)
+  std::map<std::string, scoped_ptr<ExternalInstallError>>::iterator iter =
+      errors_.find(extension_id);
+  if (iter != errors_.end()) {
+    if (iter->second.get() == currently_visible_install_alert_)
+      currently_visible_install_alert_ = nullptr;
+    errors_.erase(iter);
     UpdateExternalExtensionAlert();
+  }
 }
 
 void ExternalInstallManager::UpdateExternalExtensionAlert() {
@@ -141,6 +148,17 @@
   UpdateExternalExtensionAlert();
 }
 
+void ExternalInstallManager::DidChangeInstallAlertVisibility(
+    ExternalInstallError* external_install_error,
+    bool visible) {
+  if (visible) {
+    currently_visible_install_alert_ = external_install_error;
+  } else if (!visible &&
+             currently_visible_install_alert_ == external_install_error) {
+    currently_visible_install_alert_ = nullptr;
+  }
+}
+
 std::vector<ExternalInstallError*>
 ExternalInstallManager::GetErrorsForTesting() {
   std::vector<ExternalInstallError*> errors;
diff --git a/chrome/browser/extensions/external_install_manager.h b/chrome/browser/extensions/external_install_manager.h
index afc7cb9..82732fac 100644
--- a/chrome/browser/extensions/external_install_manager.h
+++ b/chrome/browser/extensions/external_install_manager.h
@@ -43,6 +43,20 @@
   // acknowledged.
   void AcknowledgeExternalExtension(const std::string& extension_id);
 
+  // Notifies the manager that |external_install_error| has changed its alert
+  // visibility.
+  void DidChangeInstallAlertVisibility(
+      ExternalInstallError* external_install_error,
+      bool visible);
+
+  bool has_currently_visible_install_alert() {
+    return currently_visible_install_alert_ != nullptr;
+  }
+
+  ExternalInstallError* currently_visible_install_alert_for_testing() const {
+    return currently_visible_install_alert_;
+  }
+
   // Returns a mutable copy of the list of global errors for testing purposes.
   std::vector<ExternalInstallError*> GetErrorsForTesting();
 
@@ -85,6 +99,9 @@
 
   std::set<std::string> shown_ids_;
 
+  // The error that is currently showing an alert dialog/bubble.
+  ExternalInstallError* currently_visible_install_alert_;
+
   content::NotificationRegistrar registrar_;
 
   ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver>
diff --git a/chrome/browser/external_protocol/external_protocol_handler.cc b/chrome/browser/external_protocol/external_protocol_handler.cc
index 66449d1..a433f3e9 100644
--- a/chrome/browser/external_protocol/external_protocol_handler.cc
+++ b/chrome/browser/external_protocol/external_protocol_handler.cc
@@ -103,11 +103,6 @@
     shell_integration::DefaultWebClientUIState state) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
-  // If we are still working out if we're the default, or we've found
-  // out we definately are the default, we end here.
-  if (state == shell_integration::STATE_PROCESSING)
-    return;
-
   if (delegate)
     delegate->FinishedProcessingCheck();
 
diff --git a/chrome/browser/media/chrome_webrtc_video_quality_browsertest.cc b/chrome/browser/media/chrome_webrtc_video_quality_browsertest.cc
index 63594572..177c2e0 100644
--- a/chrome/browser/media/chrome_webrtc_video_quality_browsertest.cc
+++ b/chrome/browser/media/chrome_webrtc_video_quality_browsertest.cc
@@ -30,6 +30,8 @@
 #include "chrome/test/base/in_process_browser_test.h"
 #include "components/infobars/core/infobar.h"
 #include "content/public/browser/notification_service.h"
+#include "content/public/common/feature_h264_with_openh264_ffmpeg.h"
+#include "content/public/common/features.h"
 #include "content/public/test/browser_test_utils.h"
 #include "media/base/media_switches.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
@@ -374,3 +376,19 @@
                        MANUAL_TestVideoQualityVp9) {
   TestVideoQuality("VP9");
 }
+
+#if BUILDFLAG(RTC_USE_H264)
+
+IN_PROC_BROWSER_TEST_P(WebRtcVideoQualityBrowserTest,
+                       MANUAL_TestVideoQualityH264) {
+  // Only run test if run-time feature corresponding to |rtc_use_h264| is on.
+  if (!base::FeatureList::IsEnabled(content::kWebRtcH264WithOpenH264FFmpeg)) {
+    LOG(WARNING) << "Run-time feature WebRTC-H264WithOpenH264FFmpeg disabled. "
+        "Skipping WebRtcVideoQualityBrowserTest.MANUAL_TestVideoQualityH264 "
+        "(test \"OK\")";
+    return;
+  }
+  TestVideoQuality("H264");
+}
+
+#endif  // BUILDFLAG(RTC_USE_H264)
diff --git a/chrome/browser/safe_browsing/client_side_detection_service.cc b/chrome/browser/safe_browsing/client_side_detection_service.cc
index 1a8dbe4..569836a 100644
--- a/chrome/browser/safe_browsing/client_side_detection_service.cc
+++ b/chrome/browser/safe_browsing/client_side_detection_service.cc
@@ -30,6 +30,7 @@
 #include "crypto/sha2.h"
 #include "google_apis/google_api_keys.h"
 #include "net/base/escape.h"
+#include "net/base/ip_address.h"
 #include "net/base/load_flags.h"
 #include "net/http/http_response_headers.h"
 #include "net/http/http_status_code.h"
@@ -189,14 +190,14 @@
 
 bool ClientSideDetectionService::IsPrivateIPAddress(
     const std::string& ip_address) const {
-  net::IPAddressNumber ip_number;
-  if (!net::ParseIPLiteralToNumber(ip_address, &ip_number)) {
+  net::IPAddress address;
+  if (!address.AssignFromIPLiteral(ip_address)) {
     DVLOG(2) << "Unable to parse IP address: '" << ip_address << "'";
     // Err on the side of safety and assume this might be private.
     return true;
   }
 
-  return net::IsIPAddressReserved(ip_number);
+  return address.IsReserved();
 }
 
 void ClientSideDetectionService::OnURLFetchComplete(
diff --git a/chrome/browser/safe_browsing/safe_browsing_database.cc b/chrome/browser/safe_browsing/safe_browsing_database.cc
index cd78d76..74ae7bb 100644
--- a/chrome/browser/safe_browsing/safe_browsing_database.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_database.cc
@@ -27,7 +27,7 @@
 #include "components/safe_browsing_db/prefix_set.h"
 #include "content/public/browser/browser_thread.h"
 #include "crypto/sha2.h"
-#include "net/base/ip_address_number.h"
+#include "net/base/ip_address.h"
 #include "url/gurl.h"
 
 #if defined(OS_MACOSX)
@@ -973,12 +973,12 @@
 }
 
 bool SafeBrowsingDatabaseNew::ContainsMalwareIP(const std::string& ip_address) {
-  net::IPAddressNumber ip_number;
-  if (!net::ParseIPLiteralToNumber(ip_address, &ip_number))
+  net::IPAddress address;
+  if (!address.AssignFromIPLiteral(ip_address))
     return false;
-  if (ip_number.size() == net::kIPv4AddressSize)
-    ip_number = net::ConvertIPv4NumberToIPv6Number(ip_number);
-  if (ip_number.size() != net::kIPv6AddressSize)
+  if (address.IsIPv4())
+    address = net::ConvertIPv4ToIPv4MappedIPv6(address);
+  if (!address.IsIPv6())
     return false;  // better safe than sorry.
 
   scoped_ptr<ReadTransaction> txn = state_manager_.BeginReadTransaction();
@@ -986,10 +986,10 @@
   for (IPBlacklist::const_iterator it = ip_blacklist->begin();
        it != ip_blacklist->end(); ++it) {
     const std::string& mask = it->first;
-    DCHECK_EQ(mask.size(), ip_number.size());
-    std::string subnet(net::kIPv6AddressSize, '\0');
-    for (size_t i = 0; i < net::kIPv6AddressSize; ++i) {
-      subnet[i] = ip_number[i] & mask[i];
+    DCHECK_EQ(mask.size(), address.size());
+    std::string subnet(net::IPAddress::kIPv6AddressSize, '\0');
+    for (size_t i = 0; i < net::IPAddress::kIPv6AddressSize; ++i) {
+      subnet[i] = address.bytes()[i] & mask[i];
     }
     const std::string hash = base::SHA1HashString(subnet);
     DVLOG(2) << "Lookup Malware IP: "
diff --git a/chrome/browser/safe_browsing/safe_browsing_database_unittest.cc b/chrome/browser/safe_browsing/safe_browsing_database_unittest.cc
index 6d27a1f..7eb3ddd2 100644
--- a/chrome/browser/safe_browsing/safe_browsing_database_unittest.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_database_unittest.cc
@@ -21,7 +21,7 @@
 #include "chrome/browser/safe_browsing/chunk.pb.h"
 #include "chrome/browser/safe_browsing/safe_browsing_store_file.h"
 #include "crypto/sha2.h"
-#include "net/base/ip_address_number.h"
+#include "net/base/ip_address.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
@@ -53,11 +53,11 @@
 }
 
 std::string HashedIpPrefix(const std::string& ip_prefix, size_t prefix_size) {
-  net::IPAddressNumber ip_number;
-  EXPECT_TRUE(net::ParseIPLiteralToNumber(ip_prefix, &ip_number));
-  EXPECT_EQ(net::kIPv6AddressSize, ip_number.size());
-  const std::string hashed_ip_prefix = base::SHA1HashString(
-      net::IPAddressToPackedString(ip_number));
+  net::IPAddress ip_address;
+  EXPECT_TRUE(ip_address.AssignFromIPLiteral(ip_prefix));
+  EXPECT_TRUE(ip_address.IsIPv6());
+  const std::string hashed_ip_prefix =
+      base::SHA1HashString(net::IPAddressToPackedString(ip_address));
   std::string hash(crypto::kSHA256Length, '\0');
   hash.replace(0, hashed_ip_prefix.size(), hashed_ip_prefix);
   hash[base::kSHA1Length] = static_cast<char>(prefix_size);
diff --git a/chrome/browser/shell_integration.cc b/chrome/browser/shell_integration.cc
index 4e49b1c..0bba6d3 100644
--- a/chrome/browser/shell_integration.cc
+++ b/chrome/browser/shell_integration.cc
@@ -155,8 +155,6 @@
     : callback_(callback) {}
 
 void DefaultWebClientWorker::StartCheckIsDefault() {
-  RunCallback(STATE_PROCESSING);
-
   BrowserThread::PostTask(
       BrowserThread::FILE, FROM_HERE,
       base::Bind(&DefaultWebClientWorker::CheckIsDefault, this));
@@ -174,8 +172,6 @@
   }
 
   set_as_default_in_progress_ = true;
-  RunCallback(STATE_PROCESSING);
-
   set_as_default_initialized_ = InitializeSetAsDefault();
 
   // Remember the start time.
@@ -234,11 +230,6 @@
   }
 }
 
-void DefaultWebClientWorker::RunCallback(DefaultWebClientUIState state) {
-  if (!callback_.is_null())
-    callback_.Run(state);
-}
-
 void DefaultWebClientWorker::ReportAttemptResult(AttemptResult result) {
   const char* histogram_prefix = GetHistogramPrefix();
 
@@ -268,18 +259,20 @@
 void DefaultWebClientWorker::FinalizeSetAsDefault() {}
 
 void DefaultWebClientWorker::UpdateUI(DefaultWebClientState state) {
-  switch (state) {
-    case NOT_DEFAULT:
-      RunCallback(STATE_NOT_DEFAULT);
-      break;
-    case IS_DEFAULT:
-      RunCallback(STATE_IS_DEFAULT);
-      break;
-    case UNKNOWN_DEFAULT:
-      RunCallback(STATE_UNKNOWN);
-      break;
-    case NUM_DEFAULT_STATES:
-      break;
+  if (!callback_.is_null()) {
+    switch (state) {
+      case NOT_DEFAULT:
+        callback_.Run(STATE_NOT_DEFAULT);
+        break;
+      case IS_DEFAULT:
+        callback_.Run(STATE_IS_DEFAULT);
+        break;
+      case UNKNOWN_DEFAULT:
+        callback_.Run(STATE_UNKNOWN);
+        break;
+      case NUM_DEFAULT_STATES:
+        break;
+    }
   }
 }
 
diff --git a/chrome/browser/shell_integration.h b/chrome/browser/shell_integration.h
index 8d2b536..2329566 100644
--- a/chrome/browser/shell_integration.h
+++ b/chrome/browser/shell_integration.h
@@ -184,7 +184,6 @@
 // application for a url protocol, and communicates the state and result of
 // a request.
 enum DefaultWebClientUIState {
-  STATE_PROCESSING,
   STATE_NOT_DEFAULT,
   STATE_IS_DEFAULT,
   STATE_UNKNOWN
@@ -272,9 +271,6 @@
   // after StartSetAsDefault() is invoked.
   void OnSetAsDefaultAttemptComplete(AttemptResult result);
 
-  // Runs the callback but only if it is not null.
-  void RunCallback(DefaultWebClientUIState state);
-
   // Returns true if FinalizeSetAsDefault() will be called.
   bool set_as_default_initialized() const {
     return set_as_default_initialized_;
diff --git a/chrome/browser/ui/apps/chrome_app_delegate.cc b/chrome/browser/ui/apps/chrome_app_delegate.cc
index 419d1be..9327521 100644
--- a/chrome/browser/ui/apps/chrome_app_delegate.cc
+++ b/chrome/browser/ui/apps/chrome_app_delegate.cc
@@ -91,8 +91,6 @@
   if (!profile)
     return;
   switch (state) {
-    case shell_integration::STATE_PROCESSING:
-      break;
     case shell_integration::STATE_IS_DEFAULT:
       OpenURLFromTabInternal(profile, params);
       break;
diff --git a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos_unittest.cc b/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos_unittest.cc
index 016613dd..c43d298 100644
--- a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos_unittest.cc
+++ b/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos_unittest.cc
@@ -15,7 +15,9 @@
 #include "ash/test/test_shell_delegate.h"
 #include "ash/wm/maximize_mode/maximize_mode_controller.h"
 #include "ash/wm/maximize_mode/maximize_mode_window_manager.h"
+#include "ash/wm/mru_window_tracker.h"
 #include "ash/wm/window_state.h"
+#include "ash/wm/window_util.h"
 #include "ash/wm/wm_event.h"
 #include "base/command_line.h"
 #include "base/compiler_specific.h"
@@ -1476,5 +1478,56 @@
   EXPECT_TRUE(::wm::CanActivateWindow(window(1)));
 }
 
+// Tests that the window order is preserved when switching between users. Also
+// tests that the window's activation is restored correctly if one user's MRU
+// window list is empty.
+TEST_F(MultiUserWindowManagerChromeOSTest, WindowsOrderPreservedTests) {
+  SetUpForThisManyWindows(3);
+
+  const AccountId account_id_A(AccountId::FromUserEmail("A"));
+  const AccountId account_id_B(AccountId::FromUserEmail("B"));
+  AddTestUser(account_id_A);
+  AddTestUser(account_id_B);
+  session_state_delegate()->set_logged_in_users(2);
+  user_manager()->SwitchActiveUser(account_id_A);
+  multi_user_window_manager()->ActiveUserChanged(account_id_A);
+
+  // Set the windows owner.
+  aura::client::ActivationClient* activation_client =
+      aura::client::GetActivationClient(window(0)->GetRootWindow());
+  multi_user_window_manager()->SetWindowOwner(window(0), account_id_A);
+  multi_user_window_manager()->SetWindowOwner(window(1), account_id_A);
+  multi_user_window_manager()->SetWindowOwner(window(2), account_id_A);
+  EXPECT_EQ("S[A], S[A], S[A]", GetStatus());
+
+  // Activate the windows one by one.
+  activation_client->ActivateWindow(window(2));
+  activation_client->ActivateWindow(window(1));
+  activation_client->ActivateWindow(window(0));
+  EXPECT_EQ(wm::GetActiveWindow(), window(0));
+
+  ash::MruWindowTracker::WindowList mru_list =
+      ash::Shell::GetInstance()->mru_window_tracker()->BuildMruWindowList();
+  EXPECT_EQ(mru_list[0], window(0));
+  EXPECT_EQ(mru_list[1], window(1));
+  EXPECT_EQ(mru_list[2], window(2));
+
+  user_manager()->SwitchActiveUser(account_id_B);
+  multi_user_window_manager()->ActiveUserChanged(account_id_B);
+  EXPECT_EQ("H[A], H[A], H[A]", GetStatus());
+  EXPECT_EQ(wm::GetActiveWindow(), nullptr);
+
+  user_manager()->SwitchActiveUser(account_id_A);
+  multi_user_window_manager()->ActiveUserChanged(account_id_A);
+  EXPECT_EQ("S[A], S[A], S[A]", GetStatus());
+  EXPECT_EQ(wm::GetActiveWindow(), window(0));
+
+  mru_list =
+      ash::Shell::GetInstance()->mru_window_tracker()->BuildMruWindowList();
+  EXPECT_EQ(mru_list[0], window(0));
+  EXPECT_EQ(mru_list[1], window(1));
+  EXPECT_EQ(mru_list[2], window(2));
+}
+
 }  // namespace test
 }  // namespace ash
diff --git a/chrome/browser/ui/ash/multi_user/user_switch_animator_chromeos.cc b/chrome/browser/ui/ash/multi_user/user_switch_animator_chromeos.cc
index 30818ad..2ad2a72 100644
--- a/chrome/browser/ui/ash/multi_user/user_switch_animator_chromeos.cc
+++ b/chrome/browser/ui/ash/multi_user/user_switch_animator_chromeos.cc
@@ -381,15 +381,6 @@
           if (client)
             client->ActivateWindow(window);
         }
-      } else {
-        // If the new user has no windows at all in his MRU windows list, we
-        // must deactivate any active window (by setting the active window to
-        // |nullptr|).
-        aura::Window* root_window = ash::Shell::GetPrimaryRootWindow();
-        aura::client::ActivationClient* client =
-            aura::client::GetActivationClient(root_window);
-        if (client)
-          client->ActivateWindow(nullptr);
       }
 
       owner_->notification_blocker()->ActiveUserChanged(new_account_id_);
diff --git a/chrome/browser/ui/browser.h b/chrome/browser/ui/browser.h
index 1f11741..f9a8392 100644
--- a/chrome/browser/ui/browser.h
+++ b/chrome/browser/ui/browser.h
@@ -373,11 +373,6 @@
   // FullscreenController::ToggleFullscreenModeWithExtension.
   void ToggleFullscreenModeWithExtension(const GURL& extension_url);
 
-#if defined(OS_WIN)
-  // See the description of FullscreenController::ToggleMetroSnapMode.
-  void SetMetroSnapMode(bool enable);
-#endif
-
   // Returns true if the Browser supports the specified feature. The value of
   // this varies during the lifetime of the browser. For example, if the window
   // is fullscreen this may return a different value. If you only care about
diff --git a/chrome/browser/ui/browser_win.cc b/chrome/browser/ui/browser_win.cc
deleted file mode 100644
index ad4bdab..0000000
--- a/chrome/browser/ui/browser_win.cc
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/browser.h"
-
-#include "chrome/browser/ui/exclusive_access/fullscreen_controller.h"
-
-void Browser::SetMetroSnapMode(bool enable) {
-  exclusive_access_manager_->fullscreen_controller()->SetMetroSnapMode(enable);
-}
diff --git a/chrome/browser/ui/exclusive_access/fullscreen_controller.cc b/chrome/browser/ui/exclusive_access/fullscreen_controller.cc
index 1f223d7a..427f6ee 100644
--- a/chrome/browser/ui/exclusive_access/fullscreen_controller.cc
+++ b/chrome/browser/ui/exclusive_access/fullscreen_controller.cc
@@ -131,15 +131,6 @@
       return;
   }
 
-#if defined(OS_WIN)
-  // For now, avoid breaking when initiating full screen tab mode while in
-  // a metro snap.
-  // TODO(robertshield): Find a way to reconcile tab-initiated fullscreen
-  //                     modes with metro snap.
-  if (IsInMetroSnapMode())
-    return;
-#endif
-
   SetTabWithExclusiveAccess(web_contents);
   fullscreened_origin_ = origin;
 
@@ -186,15 +177,6 @@
     return;
   }
 
-#if defined(OS_WIN)
-  // For now, avoid breaking when initiating full screen tab mode while in
-  // a metro snap.
-  // TODO(robertshield): Find a way to reconcile tab-initiated fullscreen
-  //                     modes with metro snap.
-  if (IsInMetroSnapMode())
-    return;
-#endif
-
   ExclusiveAccessContext* exclusive_access_context =
       exclusive_access_manager()->context();
 
@@ -230,24 +212,6 @@
   PostFullscreenChangeNotification(true);
 }
 
-#if defined(OS_WIN)
-bool FullscreenController::IsInMetroSnapMode() {
-  return exclusive_access_manager()->context()->IsInMetroSnapMode();
-}
-
-void FullscreenController::SetMetroSnapMode(bool enable) {
-  reentrant_window_state_change_call_check_ = false;
-
-  toggled_into_fullscreen_ = false;
-  exclusive_access_manager()->context()->SetMetroSnapMode(enable);
-
-  // FullscreenController unit tests for metro snap assume that on Windows calls
-  // to WindowFullscreenStateChanged are reentrant. If that assumption is
-  // invalidated, the tests must be updated to maintain coverage.
-  CHECK(reentrant_window_state_change_call_check_);
-}
-#endif  // defined(OS_WIN)
-
 void FullscreenController::OnTabDetachedFromView(WebContents* old_contents) {
   if (!IsFullscreenForCapturedTab(old_contents))
     return;
@@ -435,12 +399,6 @@
 
 void FullscreenController::ToggleFullscreenModeInternal(
     FullscreenInternalOption option) {
-#if defined(OS_WIN)
-  // When in Metro snap mode, toggling in and out of fullscreen is prevented.
-  if (IsInMetroSnapMode())
-    return;
-#endif
-
   ExclusiveAccessContext* const exclusive_access_context =
       exclusive_access_manager()->context();
   bool enter_fullscreen = !exclusive_access_context->IsFullscreen();
diff --git a/chrome/browser/ui/exclusive_access/fullscreen_controller.h b/chrome/browser/ui/exclusive_access/fullscreen_controller.h
index e61d891..768789d 100644
--- a/chrome/browser/ui/exclusive_access/fullscreen_controller.h
+++ b/chrome/browser/ui/exclusive_access/fullscreen_controller.h
@@ -117,15 +117,6 @@
 
   // Platform Fullscreen ///////////////////////////////////////////////////////
 
-#if defined(OS_WIN)
-  // Returns whether we are currently in a Metro snap view.
-  bool IsInMetroSnapMode();
-
-  // API that puts the window into a mode suitable for rendering when Chrome
-  // is rendered in a 20% screen-width Metro snap view on Windows 8.
-  void SetMetroSnapMode(bool enable);
-#endif  // OS_WIN
-
   // Overrde from ExclusiveAccessControllerBase.
   void OnTabDetachedFromView(content::WebContents* web_contents) override;
   void OnTabClosing(content::WebContents* web_contents) override;
diff --git a/chrome/browser/ui/exclusive_access/fullscreen_controller_state_test.cc b/chrome/browser/ui/exclusive_access/fullscreen_controller_state_test.cc
index a8514c6..56b62484 100644
--- a/chrome/browser/ui/exclusive_access/fullscreen_controller_state_test.cc
+++ b/chrome/browser/ui/exclusive_access/fullscreen_controller_state_test.cc
@@ -44,8 +44,6 @@
       STATE_TO_BROWSER_FULLSCREEN_WITH_CHROME,// Event TOGGLE_FULLSCREEN_CHROME
       STATE_TO_TAB_FULLSCREEN,                // Event TAB_FULLSCREEN_TRUE
       STATE_NORMAL,                           // Event TAB_FULLSCREEN_FALSE
-      STATE_METRO_SNAP,                       // Event METRO_SNAP_TRUE
-      STATE_NORMAL,                           // Event METRO_SNAP_FALSE
       STATE_NORMAL,                           // Event BUBBLE_EXIT_LINK
       STATE_NORMAL,                           // Event BUBBLE_ALLOW
       STATE_NORMAL,                           // Event BUBBLE_DENY
@@ -56,8 +54,6 @@
       STATE_TO_NORMAL,                        // Event TOGGLE_FULLSCREEN_CHROME
       STATE_TAB_BROWSER_FULLSCREEN,           // Event TAB_FULLSCREEN_TRUE
       STATE_BROWSER_FULLSCREEN_NO_CHROME,     // Event TAB_FULLSCREEN_FALSE
-      STATE_METRO_SNAP,                       // Event METRO_SNAP_TRUE
-      STATE_BROWSER_FULLSCREEN_NO_CHROME,     // Event METRO_SNAP_FALSE
       STATE_TO_NORMAL,                        // Event BUBBLE_EXIT_LINK
       STATE_BROWSER_FULLSCREEN_NO_CHROME,     // Event BUBBLE_ALLOW
       STATE_BROWSER_FULLSCREEN_NO_CHROME,     // Event BUBBLE_DENY
@@ -68,32 +64,16 @@
       STATE_TO_NORMAL,                        // Event TOGGLE_FULLSCREEN_CHROME
       STATE_TAB_BROWSER_FULLSCREEN_CHROME,    // Event TAB_FULLSCREEN_TRUE
       STATE_BROWSER_FULLSCREEN_WITH_CHROME,   // Event TAB_FULLSCREEN_FALSE
-      STATE_BROWSER_FULLSCREEN_WITH_CHROME,   // Event METRO_SNAP_TRUE
-      STATE_BROWSER_FULLSCREEN_WITH_CHROME,   // Event METRO_SNAP_FALSE
       STATE_TO_NORMAL,                        // Event BUBBLE_EXIT_LINK
       STATE_BROWSER_FULLSCREEN_WITH_CHROME,   // Event BUBBLE_ALLOW
       STATE_BROWSER_FULLSCREEN_WITH_CHROME,   // Event BUBBLE_DENY
       STATE_BROWSER_FULLSCREEN_WITH_CHROME,   // Event WINDOW_CHANGE
     },
-    { // STATE_METRO_SNAP:
-      STATE_METRO_SNAP,                       // Event TOGGLE_FULLSCREEN
-      STATE_METRO_SNAP,                       // Event TOGGLE_FULLSCREEN_CHROME
-      STATE_METRO_SNAP,                       // Event TAB_FULLSCREEN_TRUE
-      STATE_METRO_SNAP,                       // Event TAB_FULLSCREEN_FALSE
-      STATE_METRO_SNAP,                       // Event METRO_SNAP_TRUE
-      STATE_NORMAL,                           // Event METRO_SNAP_FALSE
-      STATE_METRO_SNAP,                       // Event BUBBLE_EXIT_LINK
-      STATE_METRO_SNAP,                       // Event BUBBLE_ALLOW
-      STATE_METRO_SNAP,                       // Event BUBBLE_DENY
-      STATE_METRO_SNAP,                       // Event WINDOW_CHANGE
-    },
     { // STATE_TAB_FULLSCREEN:
       STATE_TO_NORMAL,                        // Event TOGGLE_FULLSCREEN
       STATE_TO_NORMAL,                        // Event TOGGLE_FULLSCREEN_CHROME
       STATE_TAB_FULLSCREEN,                   // Event TAB_FULLSCREEN_TRUE
       STATE_TO_NORMAL,                        // Event TAB_FULLSCREEN_FALSE
-      STATE_METRO_SNAP,                       // Event METRO_SNAP_TRUE
-      STATE_TAB_FULLSCREEN,                   // Event METRO_SNAP_FALSE
       STATE_TO_NORMAL,                        // Event BUBBLE_EXIT_LINK
       STATE_TAB_FULLSCREEN,                   // Event BUBBLE_ALLOW
       STATE_TO_NORMAL,                        // Event BUBBLE_DENY
@@ -104,8 +84,6 @@
       STATE_TO_NORMAL,                        // Event TOGGLE_FULLSCREEN_CHROME
       STATE_TAB_BROWSER_FULLSCREEN,           // Event TAB_FULLSCREEN_TRUE
       STATE_BROWSER_FULLSCREEN_NO_CHROME,     // Event TAB_FULLSCREEN_FALSE
-      STATE_METRO_SNAP,                       // Event METRO_SNAP_TRUE
-      STATE_TAB_BROWSER_FULLSCREEN,           // Event METRO_SNAP_FALSE
       STATE_BROWSER_FULLSCREEN_NO_CHROME,     // Event BUBBLE_EXIT_LINK
       STATE_TAB_BROWSER_FULLSCREEN,           // Event BUBBLE_ALLOW
       STATE_BROWSER_FULLSCREEN_NO_CHROME,     // Event BUBBLE_DENY
@@ -116,8 +94,6 @@
       STATE_TO_NORMAL,                        // Event TOGGLE_FULLSCREEN_CHROME
       STATE_TAB_BROWSER_FULLSCREEN_CHROME,    // Event TAB_FULLSCREEN_TRUE
       STATE_BROWSER_FULLSCREEN_WITH_CHROME,   // Event TAB_FULLSCREEN_FALSE
-      STATE_METRO_SNAP,                       // Event METRO_SNAP_TRUE
-      STATE_TAB_BROWSER_FULLSCREEN_CHROME,    // Event METRO_SNAP_FALSE
       STATE_BROWSER_FULLSCREEN_WITH_CHROME,   // Event BUBBLE_EXIT_LINK
       STATE_TAB_BROWSER_FULLSCREEN_CHROME,    // Event BUBBLE_ALLOW
       STATE_BROWSER_FULLSCREEN_WITH_CHROME,   // Event BUBBLE_DENY
@@ -129,8 +105,6 @@
       // TODO(scheib) Should be a route back to TAB. http://crbug.com/154196
       STATE_TO_NORMAL,                        // Event TAB_FULLSCREEN_TRUE
       STATE_TO_NORMAL,                        // Event TAB_FULLSCREEN_FALSE
-      STATE_METRO_SNAP,                       // Event METRO_SNAP_TRUE
-      STATE_TO_NORMAL,                        // Event METRO_SNAP_FALSE
       STATE_TO_NORMAL,                        // Event BUBBLE_EXIT_LINK
       STATE_TO_NORMAL,                        // Event BUBBLE_ALLOW
       STATE_TO_NORMAL,                        // Event BUBBLE_DENY
@@ -142,8 +116,6 @@
       // TODO(scheib) Should be a route to TAB_BROWSER http://crbug.com/154196
       STATE_TO_BROWSER_FULLSCREEN_NO_CHROME,  // Event TAB_FULLSCREEN_TRUE
       STATE_TO_BROWSER_FULLSCREEN_NO_CHROME,  // Event TAB_FULLSCREEN_FALSE
-      STATE_METRO_SNAP,                       // Event METRO_SNAP_TRUE
-      STATE_TO_BROWSER_FULLSCREEN_NO_CHROME,  // Event METRO_SNAP_FALSE
 #if defined(OS_MACOSX)
       // Mac window reports fullscreen immediately and an exit triggers exit.
       STATE_TO_NORMAL,                        // Event BUBBLE_EXIT_LINK
@@ -160,8 +132,6 @@
       // TODO(scheib) Should be a route to TAB_BROWSER http://crbug.com/154196
       STATE_TAB_BROWSER_FULLSCREEN,           // Event TAB_FULLSCREEN_TRUE
       STATE_TO_BROWSER_FULLSCREEN_WITH_CHROME,// Event TAB_FULLSCREEN_FALSE
-      STATE_TO_BROWSER_FULLSCREEN_WITH_CHROME,// Event METRO_SNAP_TRUE
-      STATE_TO_BROWSER_FULLSCREEN_WITH_CHROME,// Event METRO_SNAP_FALSE
       STATE_TO_NORMAL,                        // Event BUBBLE_EXIT_LINK
       STATE_TO_BROWSER_FULLSCREEN_WITH_CHROME,// Event BUBBLE_ALLOW
       STATE_TO_BROWSER_FULLSCREEN_WITH_CHROME,// Event BUBBLE_DENY
@@ -179,8 +149,6 @@
       // TODO(scheib) Should be a route back to NORMAL. http://crbug.com/154196
       STATE_TO_BROWSER_FULLSCREEN_NO_CHROME,  // Event TAB_FULLSCREEN_FALSE
 #endif
-      STATE_METRO_SNAP,                       // Event METRO_SNAP_TRUE
-      STATE_TO_TAB_FULLSCREEN,                // Event METRO_SNAP_FALSE
 #if defined(OS_MACOSX)
       // Mac window reports fullscreen immediately and an exit triggers exit.
       STATE_TO_NORMAL,                        // Event BUBBLE_EXIT_LINK
@@ -234,7 +202,6 @@
     ENUM_TO_STRING(STATE_NORMAL);
     ENUM_TO_STRING(STATE_BROWSER_FULLSCREEN_NO_CHROME);
     ENUM_TO_STRING(STATE_BROWSER_FULLSCREEN_WITH_CHROME);
-    ENUM_TO_STRING(STATE_METRO_SNAP);
     ENUM_TO_STRING(STATE_TAB_FULLSCREEN);
     ENUM_TO_STRING(STATE_TAB_BROWSER_FULLSCREEN);
     ENUM_TO_STRING(STATE_TAB_BROWSER_FULLSCREEN_CHROME);
@@ -256,8 +223,6 @@
     ENUM_TO_STRING(TOGGLE_FULLSCREEN_CHROME);
     ENUM_TO_STRING(TAB_FULLSCREEN_TRUE);
     ENUM_TO_STRING(TAB_FULLSCREEN_FALSE);
-    ENUM_TO_STRING(METRO_SNAP_TRUE);
-    ENUM_TO_STRING(METRO_SNAP_FALSE);
     ENUM_TO_STRING(BUBBLE_EXIT_LINK);
     ENUM_TO_STRING(BUBBLE_ALLOW);
     ENUM_TO_STRING(BUBBLE_DENY);
@@ -284,7 +249,6 @@
     case STATE_NORMAL:
     case STATE_BROWSER_FULLSCREEN_NO_CHROME:
     case STATE_BROWSER_FULLSCREEN_WITH_CHROME:
-    case STATE_METRO_SNAP:
     case STATE_TAB_FULLSCREEN:
     case STATE_TAB_BROWSER_FULLSCREEN:
     case STATE_TAB_BROWSER_FULLSCREEN_CHROME:
@@ -400,22 +364,6 @@
       break;
     }
 
-    case METRO_SNAP_TRUE:
-#if defined(OS_WIN)
-      GetFullscreenController()->SetMetroSnapMode(true);
-#else
-      NOTREACHED() << GetAndClearDebugLog();
-#endif
-      break;
-
-    case METRO_SNAP_FALSE:
-#if defined(OS_WIN)
-      GetFullscreenController()->SetMetroSnapMode(false);
-#else
-      NOTREACHED() << GetAndClearDebugLog();
-#endif
-      break;
-
     case BUBBLE_EXIT_LINK:
       GetFullscreenController()->ExitExclusiveAccessToPreviousState();
       break;
@@ -458,50 +406,37 @@
     case STATE_NORMAL:
       VerifyWindowStateExpectations(FULLSCREEN_WITH_CHROME_FALSE,
                                     FULLSCREEN_FOR_BROWSER_FALSE,
-                                    FULLSCREEN_FOR_TAB_FALSE,
-                                    IN_METRO_SNAP_FALSE);
+                                    FULLSCREEN_FOR_TAB_FALSE);
       break;
     case STATE_BROWSER_FULLSCREEN_NO_CHROME:
       VerifyWindowStateExpectations(FULLSCREEN_WITH_CHROME_FALSE,
                                     FULLSCREEN_FOR_BROWSER_TRUE,
-                                    FULLSCREEN_FOR_TAB_FALSE,
-                                    IN_METRO_SNAP_FALSE);
+                                    FULLSCREEN_FOR_TAB_FALSE);
       break;
     case STATE_BROWSER_FULLSCREEN_WITH_CHROME:
       VerifyWindowStateExpectations(FULLSCREEN_WITH_CHROME_TRUE,
                                     FULLSCREEN_FOR_BROWSER_TRUE,
-                                    FULLSCREEN_FOR_TAB_FALSE,
-                                    IN_METRO_SNAP_FALSE);
-      break;
-    case STATE_METRO_SNAP:
-      VerifyWindowStateExpectations(FULLSCREEN_WITH_CHROME_NO_EXPECTATION,
-                                    FULLSCREEN_FOR_BROWSER_NO_EXPECTATION,
-                                    FULLSCREEN_FOR_TAB_NO_EXPECTATION,
-                                    IN_METRO_SNAP_TRUE);
+                                    FULLSCREEN_FOR_TAB_FALSE);
       break;
     case STATE_TAB_FULLSCREEN:
       VerifyWindowStateExpectations(FULLSCREEN_WITH_CHROME_FALSE,
                                     FULLSCREEN_FOR_BROWSER_FALSE,
-                                    FULLSCREEN_FOR_TAB_TRUE,
-                                    IN_METRO_SNAP_FALSE);
+                                    FULLSCREEN_FOR_TAB_TRUE);
       break;
     case STATE_TAB_BROWSER_FULLSCREEN:
       VerifyWindowStateExpectations(FULLSCREEN_WITH_CHROME_FALSE,
                                     FULLSCREEN_FOR_BROWSER_TRUE,
-                                    FULLSCREEN_FOR_TAB_TRUE,
-                                    IN_METRO_SNAP_FALSE);
+                                    FULLSCREEN_FOR_TAB_TRUE);
       break;
     case STATE_TAB_BROWSER_FULLSCREEN_CHROME:
       VerifyWindowStateExpectations(FULLSCREEN_WITH_CHROME_FALSE,
                                     FULLSCREEN_FOR_BROWSER_TRUE,
-                                    FULLSCREEN_FOR_TAB_TRUE,
-                                    IN_METRO_SNAP_FALSE);
+                                    FULLSCREEN_FOR_TAB_TRUE);
       break;
     case STATE_TO_NORMAL:
       VerifyWindowStateExpectations(FULLSCREEN_WITH_CHROME_FALSE,
                                     FULLSCREEN_FOR_BROWSER_NO_EXPECTATION,
-                                    FULLSCREEN_FOR_TAB_NO_EXPECTATION,
-                                    IN_METRO_SNAP_FALSE);
+                                    FULLSCREEN_FOR_TAB_NO_EXPECTATION);
       break;
 
     case STATE_TO_BROWSER_FULLSCREEN_NO_CHROME:
@@ -511,8 +446,7 @@
 #else
                                     FULLSCREEN_FOR_BROWSER_FALSE,
 #endif
-                                    FULLSCREEN_FOR_TAB_NO_EXPECTATION,
-                                    IN_METRO_SNAP_FALSE);
+                                    FULLSCREEN_FOR_TAB_NO_EXPECTATION);
       break;
 
     case STATE_TO_BROWSER_FULLSCREEN_WITH_CHROME:
@@ -522,8 +456,7 @@
 #else
                                     FULLSCREEN_FOR_BROWSER_FALSE,
 #endif
-                                    FULLSCREEN_FOR_TAB_NO_EXPECTATION,
-                                    IN_METRO_SNAP_FALSE);
+                                    FULLSCREEN_FOR_TAB_NO_EXPECTATION);
       break;
 
     case STATE_TO_TAB_FULLSCREEN:
@@ -539,8 +472,7 @@
 #endif
       VerifyWindowStateExpectations(FULLSCREEN_WITH_CHROME_NO_EXPECTATION,
                                     FULLSCREEN_FOR_BROWSER_FALSE,
-                                    FULLSCREEN_FOR_TAB_TRUE,
-                                    IN_METRO_SNAP_FALSE);
+                                    FULLSCREEN_FOR_TAB_TRUE);
       break;
 
     default:
@@ -652,14 +584,6 @@
   if (state == STATE_TO_NORMAL && event == TAB_FULLSCREEN_TRUE)
     return true;
 
-  // Skip metro snap state and events when not on windows.
-#if !defined(OS_WIN)
-  if (state == STATE_METRO_SNAP ||
-      event == METRO_SNAP_TRUE ||
-      event == METRO_SNAP_FALSE)
-    return true;
-#endif
-
   // Skip Mac Lion Fullscreen state and events when not on OSX 10.7+.
   if (!SupportsMacSystemFullscreen()) {
     if (state == STATE_BROWSER_FULLSCREEN_WITH_CHROME ||
@@ -674,16 +598,6 @@
 }
 
 bool FullscreenControllerStateTest::ShouldSkipTest(State state, Event event) {
-  // Quietly skip metro snap tests when not on windows.
-#if !defined(OS_WIN)
-  if (state == STATE_METRO_SNAP ||
-      event == METRO_SNAP_TRUE ||
-      event == METRO_SNAP_FALSE) {
-    debugging_log_ << "\nSkipping metro snap test on non-Windows.\n";
-    return true;
-  }
-#endif
-
   // Quietly skip Mac Lion Fullscreen tests when not on OSX 10.7+.
   if (!SupportsMacSystemFullscreen()) {
     if (state == STATE_BROWSER_FULLSCREEN_WITH_CHROME ||
@@ -740,8 +654,7 @@
 void FullscreenControllerStateTest::VerifyWindowStateExpectations(
     FullscreenWithToolbarExpectation fullscreen_with_toolbar,
     FullscreenForBrowserExpectation fullscreen_for_browser,
-    FullscreenForTabExpectation fullscreen_for_tab,
-    InMetroSnapExpectation in_metro_snap) {
+    FullscreenForTabExpectation fullscreen_for_tab) {
   ExclusiveAccessContext* context =
       GetBrowser()->window()->GetExclusiveAccessContext();
   if (fullscreen_with_toolbar != FULLSCREEN_WITH_CHROME_NO_EXPECTATION &&
@@ -757,13 +670,6 @@
     EXPECT_EQ(GetFullscreenController()->IsWindowFullscreenForTabOrPending(),
               !!fullscreen_for_tab) << GetAndClearDebugLog();
   }
-
-#if defined(OS_WIN)
-  if (in_metro_snap != IN_METRO_SNAP_NO_EXPECTATION) {
-    EXPECT_EQ(GetFullscreenController()->IsInMetroSnapMode(),
-              !!in_metro_snap) << GetAndClearDebugLog();
-  }
-#endif  // OS_WIN
 }
 
 FullscreenController* FullscreenControllerStateTest::GetFullscreenController() {
diff --git a/chrome/browser/ui/exclusive_access/fullscreen_controller_state_test.h b/chrome/browser/ui/exclusive_access/fullscreen_controller_state_test.h
index 14f855c..3aad269 100644
--- a/chrome/browser/ui/exclusive_access/fullscreen_controller_state_test.h
+++ b/chrome/browser/ui/exclusive_access/fullscreen_controller_state_test.h
@@ -36,8 +36,6 @@
     TOGGLE_FULLSCREEN_CHROME,  // ToggleBrowserFullscreenWithToolbar()
     TAB_FULLSCREEN_TRUE,       // ToggleFullscreenModeForTab(, true)
     TAB_FULLSCREEN_FALSE,      // ToggleFullscreenModeForTab(, false)
-    METRO_SNAP_TRUE,           // SetMetroSnapMode(true)
-    METRO_SNAP_FALSE,          // SetMetroSnapMode(false)
     BUBBLE_EXIT_LINK,          // ExitTabOrBrowserFullscreenToPreviousState()
     BUBBLE_ALLOW,              // OnAcceptFullscreenPermission()
     BUBBLE_DENY,               // OnDenyFullscreenPermission()
@@ -55,9 +53,6 @@
     STATE_BROWSER_FULLSCREEN_NO_CHROME,
     // Mac User-initiated 'Lion Fullscreen' with browser chrome. OSX 10.7+ only.
     STATE_BROWSER_FULLSCREEN_WITH_CHROME,
-    // Windows 8 Metro Snap mode, which puts the window at 20% screen-width.
-    // No TO_ state for Metro, as the windows implementation is only reentrant.
-    STATE_METRO_SNAP,
     // HTML5 tab-initiated fullscreen.
     STATE_TAB_FULLSCREEN,
     // Both tab and browser fullscreen.
@@ -145,7 +140,6 @@
   EXPECTATION_ENUM(FullscreenWithToolbarExpectation, FULLSCREEN_WITH_CHROME);
   EXPECTATION_ENUM(FullscreenForBrowserExpectation, FULLSCREEN_FOR_BROWSER);
   EXPECTATION_ENUM(FullscreenForTabExpectation, FULLSCREEN_FOR_TAB);
-  EXPECTATION_ENUM(InMetroSnapExpectation, IN_METRO_SNAP);
 
   // Generated information about the transitions between states.
   struct StateTransitionInfo {
@@ -180,8 +174,7 @@
   virtual void VerifyWindowStateExpectations(
       FullscreenWithToolbarExpectation fullscreen_with_toolbar,
       FullscreenForBrowserExpectation fullscreen_for_browser,
-      FullscreenForTabExpectation fullscreen_for_tab,
-      InMetroSnapExpectation in_metro_snap);
+      FullscreenForTabExpectation fullscreen_for_tab);
 
   virtual Browser* GetBrowser() = 0;
   FullscreenController* GetFullscreenController();
diff --git a/chrome/browser/ui/exclusive_access/fullscreen_controller_state_tests.h b/chrome/browser/ui/exclusive_access/fullscreen_controller_state_tests.h
index 244b9c6..230dbc3 100644
--- a/chrome/browser/ui/exclusive_access/fullscreen_controller_state_tests.h
+++ b/chrome/browser/ui/exclusive_access/fullscreen_controller_state_tests.h
@@ -13,31 +13,19 @@
 // fullscreen_controller_state_interactive_browsertest.cc and
 // fullscreen_controller_state_unittest.cc.
 
-#define TEST_ALL_EVENTS_NON_METRO(state) \
-    TEST_EVENT(state, TOGGLE_FULLSCREEN) \
-    TEST_EVENT(state, TOGGLE_FULLSCREEN_CHROME) \
-    TEST_EVENT(state, TAB_FULLSCREEN_TRUE) \
-    TEST_EVENT(state, TAB_FULLSCREEN_FALSE) \
-    TEST_EVENT(state, BUBBLE_EXIT_LINK) \
-    TEST_EVENT(state, BUBBLE_ALLOW) \
-    TEST_EVENT(state, BUBBLE_DENY) \
-    TEST_EVENT(state, WINDOW_CHANGE)
-
-#if defined(OS_WIN)
-#define TEST_ALL_EVENTS(state) \
-    TEST_ALL_EVENTS_NON_METRO(state) \
-    TEST_EVENT(state, METRO_SNAP_TRUE) \
-    TEST_EVENT(state, METRO_SNAP_FALSE)
-#else
-#define TEST_ALL_EVENTS(state) TEST_ALL_EVENTS_NON_METRO(state)
-#endif
+#define TEST_ALL_EVENTS(state)                \
+  TEST_EVENT(state, TOGGLE_FULLSCREEN)        \
+  TEST_EVENT(state, TOGGLE_FULLSCREEN_CHROME) \
+  TEST_EVENT(state, TAB_FULLSCREEN_TRUE)      \
+  TEST_EVENT(state, TAB_FULLSCREEN_FALSE)     \
+  TEST_EVENT(state, BUBBLE_EXIT_LINK)         \
+  TEST_EVENT(state, BUBBLE_ALLOW)             \
+  TEST_EVENT(state, BUBBLE_DENY)              \
+  TEST_EVENT(state, WINDOW_CHANGE)
 
 TEST_ALL_EVENTS(STATE_NORMAL);
 TEST_ALL_EVENTS(STATE_BROWSER_FULLSCREEN_NO_CHROME);
 TEST_ALL_EVENTS(STATE_BROWSER_FULLSCREEN_WITH_CHROME);
-#if defined(OS_WIN)
-TEST_ALL_EVENTS(STATE_METRO_SNAP);
-#endif
 TEST_ALL_EVENTS(STATE_TAB_FULLSCREEN);
 TEST_ALL_EVENTS(STATE_TAB_BROWSER_FULLSCREEN);
 TEST_ALL_EVENTS(STATE_TAB_BROWSER_FULLSCREEN_CHROME);
diff --git a/chrome/browser/ui/exclusive_access/fullscreen_controller_state_unittest.cc b/chrome/browser/ui/exclusive_access/fullscreen_controller_state_unittest.cc
index 21bd59b..77ae80d 100644
--- a/chrome/browser/ui/exclusive_access/fullscreen_controller_state_unittest.cc
+++ b/chrome/browser/ui/exclusive_access/fullscreen_controller_state_unittest.cc
@@ -38,8 +38,6 @@
   enum WindowState {
     NORMAL,
     FULLSCREEN,
-    // No TO_ state for METRO_SNAP, the windows implementation is synchronous.
-    METRO_SNAP,
     TO_NORMAL,
     TO_FULLSCREEN,
   };
@@ -53,10 +51,6 @@
   bool SupportsFullscreenWithToolbar() const override;
   void UpdateFullscreenWithToolbar(bool with_toolbar) override;
   bool IsFullscreenWithToolbar() const override;
-#if defined(OS_WIN)
-  void SetMetroSnapMode(bool enable) override;
-  bool IsInMetroSnapMode() const override;
-#endif
   static const char* GetWindowStateString(WindowState state);
   WindowState state() const { return state_; }
   void set_browser(Browser* browser) { browser_ = browser; }
@@ -145,27 +139,12 @@
   return IsFullscreen() && mac_with_toolbar_mode_;
 }
 
-#if defined(OS_WIN)
-void FullscreenControllerTestWindow::SetMetroSnapMode(bool enable) {
-  if (enable != IsInMetroSnapMode())
-    state_ = enable ? METRO_SNAP : NORMAL;
-
-  if (FullscreenControllerStateTest::IsWindowFullscreenStateChangedReentrant())
-    ChangeWindowFullscreenState();
-}
-
-bool FullscreenControllerTestWindow::IsInMetroSnapMode() const {
-  return state_ == METRO_SNAP;
-}
-#endif
-
 // static
 const char* FullscreenControllerTestWindow::GetWindowStateString(
     WindowState state) {
   switch (state) {
     ENUM_TO_STRING(NORMAL);
     ENUM_TO_STRING(FULLSCREEN);
-    ENUM_TO_STRING(METRO_SNAP);
     ENUM_TO_STRING(TO_FULLSCREEN);
     ENUM_TO_STRING(TO_NORMAL);
     default:
@@ -315,13 +294,6 @@
                 window_->state()) << GetAndClearDebugLog();
       break;
 
-#if defined(OS_WIN)
-    case STATE_METRO_SNAP:
-      EXPECT_EQ(FullscreenControllerTestWindow::METRO_SNAP,
-                window_->state()) << GetAndClearDebugLog();
-      break;
-#endif
-
     case STATE_TO_NORMAL:
       EXPECT_EQ(FullscreenControllerTestWindow::TO_NORMAL,
                 window_->state()) << GetAndClearDebugLog();
diff --git a/chrome/browser/ui/libgtk2ui/BUILD.gn b/chrome/browser/ui/libgtk2ui/BUILD.gn
index df0649d..318f307 100644
--- a/chrome/browser/ui/libgtk2ui/BUILD.gn
+++ b/chrome/browser/ui/libgtk2ui/BUILD.gn
@@ -101,7 +101,6 @@
     "//components/resources",
     "//content/public/browser",
     "//mojo/edk/system",
-    "//mojo/environment:chromium",
     "//printing",
     "//skia",
     "//ui/aura",
diff --git a/chrome/browser/ui/passwords/manage_passwords_view_utils.cc b/chrome/browser/ui/passwords/manage_passwords_view_utils.cc
index 338dd3e..274d7543 100644
--- a/chrome/browser/ui/passwords/manage_passwords_view_utils.cc
+++ b/chrome/browser/ui/passwords/manage_passwords_view_utils.cc
@@ -96,7 +96,14 @@
   // Check whether the registry controlled domains for user-visible URL (i.e.
   // the one seen in the omnibox) and the password form post-submit navigation
   // URL differs or not.
-  if (!SameDomainOrHost(user_visible_url, form_origin_url)) {
+  password_manager::FacetURI facet_uri =
+      password_manager::FacetURI::FromPotentiallyInvalidSpec(
+          form_origin_url.spec());
+  if (facet_uri.IsValidAndroidFacetURI()) {
+    title_id = IDS_SAVE_PASSWORD_TITLE;
+    replacements.push_back(
+        base::ASCIIToUTF16(GetHumanReadableOriginForAndroidUri(facet_uri)));
+  } else if (!SameDomainOrHost(user_visible_url, form_origin_url)) {
     title_id = IDS_SAVE_PASSWORD_TITLE;
     // TODO(palmer): Look into passing real language prefs here, not "".
     // crbug.com/498069.
@@ -126,7 +133,14 @@
   // Check whether the registry controlled domains for user-visible URL
   // (i.e. the one seen in the omnibox) and the managed password origin URL
   // differ or not.
-  if (!SameDomainOrHost(user_visible_url, password_origin_url)) {
+  password_manager::FacetURI facet_uri =
+      password_manager::FacetURI::FromPotentiallyInvalidSpec(
+          password_origin_url.spec());
+  if (facet_uri.IsValidAndroidFacetURI()) {
+    *title = l10n_util::GetStringFUTF16(
+        IDS_MANAGE_PASSWORDS_TITLE_DIFFERENT_DOMAIN,
+        base::ASCIIToUTF16(GetHumanReadableOriginForAndroidUri(facet_uri)));
+  } else if (!SameDomainOrHost(user_visible_url, password_origin_url)) {
     // TODO(palmer): Look into passing real language prefs here, not "".
     base::string16 formatted_url = url_formatter::FormatUrlForSecurityDisplay(
         password_origin_url, std::string());
diff --git a/chrome/browser/ui/passwords/manage_passwords_view_utils_unittest.cc b/chrome/browser/ui/passwords/manage_passwords_view_utils_unittest.cc
index 15f0828..946be457 100644
--- a/chrome/browser/ui/passwords/manage_passwords_view_utils_unittest.cc
+++ b/chrome/browser/ui/passwords/manage_passwords_view_utils_unittest.cc
@@ -80,7 +80,18 @@
      PasswordTittleType::SAVE_ACCOUNT, "this site", 0, 0},
     {"https://a.example.com/landing",
      "https://b.example.com/login#form?value=3", true,
-     PasswordTittleType::SAVE_ACCOUNT, "this site", 12, 29}};
+     PasswordTittleType::SAVE_ACCOUNT, "this site", 12, 29},
+
+     // Android update.
+     {"https://another.org", "android://m3HSJL1i83hdltRq0-o9czGb-8KJDKra4t_3JR"
+      "lnPKcjI8PZm6XBHXx6zG4UuMXaDEZjR1wuXDre9G9zvN7AQw==@com.example.android",
+      false, PasswordTittleType::SAVE_PASSWORD, "android://com.example.android",
+      0, 0},
+     {"https://another.org","android://m3HSJL1i83hdltRq0-o9czGb-8KJDKra4t_3JR"
+      "lnPKcjI8PZm6XBHXx6zG4UuMXaDEZjR1wuXDre9G9zvN7AQw==@com.example.android",
+      true, PasswordTittleType::SAVE_PASSWORD, "android://com.example.android",
+      12, 29},
+};
 
 }  // namespace
 
diff --git a/chrome/browser/ui/views/extensions/extension_message_bubble_view.cc b/chrome/browser/ui/views/extensions/extension_message_bubble_view.cc
index a3c156d..698a6c31 100644
--- a/chrome/browser/ui/views/extensions/extension_message_bubble_view.cc
+++ b/chrome/browser/ui/views/extensions/extension_message_bubble_view.cc
@@ -214,7 +214,7 @@
     controller_->OnBubbleAction();
   } else {
     DCHECK_EQ(dismiss_button_, sender);
-    controller_->OnBubbleDismiss(false /* not closed by deactivation */ );
+    controller_->OnBubbleDismiss(false);  // Not closed by deactivation.
   }
   GetWidget()->Close();
 }
diff --git a/chrome/browser/ui/views/uninstall_view.cc b/chrome/browser/ui/views/uninstall_view.cc
index f24ded6..d3558eb 100644
--- a/chrome/browser/ui/views/uninstall_view.cc
+++ b/chrome/browser/ui/views/uninstall_view.cc
@@ -79,11 +79,8 @@
   BrowserDistribution* dist = BrowserDistribution::GetDistribution();
   if (dist->GetDefaultBrowserControlPolicy() !=
           BrowserDistribution::DEFAULT_BROWSER_UNSUPPORTED &&
-      shell_integration::GetDefaultBrowser() == shell_integration::IS_DEFAULT &&
-      (shell_integration::CanSetAsDefaultBrowser() ==
-           shell_integration::SET_DEFAULT_NOT_ALLOWED ||
-       shell_integration::CanSetAsDefaultBrowser() ==
-           shell_integration::SET_DEFAULT_UNATTENDED)) {
+      ShellUtil::CanMakeChromeDefaultUnattended() &&
+      shell_integration::GetDefaultBrowser() == shell_integration::IS_DEFAULT) {
     browsers_.reset(new BrowsersMap());
     ShellUtil::GetRegisteredBrowsers(dist, browsers_.get());
     if (!browsers_->empty()) {
diff --git a/chrome/browser/ui/webui/media_router/media_router_ui.cc b/chrome/browser/ui/webui/media_router/media_router_ui.cc
index 52f2ec2..9b7aa31 100644
--- a/chrome/browser/ui/webui/media_router/media_router_ui.cc
+++ b/chrome/browser/ui/webui/media_router/media_router_ui.cc
@@ -264,14 +264,16 @@
   query_result_manager_.reset(new QueryResultManager(router_));
   query_result_manager_->AddObserver(this);
 
-  // These modes are always available.
+  // Desktop mirror mode is always available.
   query_result_manager_->StartSinksQuery(MediaCastMode::DESKTOP_MIRROR,
                                          MediaSourceForDesktop());
   initiator_ = initiator;
-  MediaSource mirroring_source(
-      MediaSourceForTab(SessionTabHelper::IdForTab(initiator)));
-  query_result_manager_->StartSinksQuery(MediaCastMode::TAB_MIRROR,
-                                         mirroring_source);
+  SessionID::id_type tab_id = SessionTabHelper::IdForTab(initiator);
+  if (tab_id != -1) {
+    MediaSource mirroring_source(MediaSourceForTab(tab_id));
+    query_result_manager_->StartSinksQuery(MediaCastMode::TAB_MIRROR,
+                                           mirroring_source);
+  }
   UpdateCastModes();
 }
 
diff --git a/chrome/browser/ui/webui/media_router/media_router_ui_unittest.cc b/chrome/browser/ui/webui/media_router/media_router_ui_unittest.cc
index 6f0d1d2..8183aa6 100644
--- a/chrome/browser/ui/webui/media_router/media_router_ui_unittest.cc
+++ b/chrome/browser/ui/webui/media_router/media_router_ui_unittest.cc
@@ -8,6 +8,7 @@
 #include "chrome/browser/media/router/mock_media_router.h"
 #include "chrome/browser/media/router/route_request_result.h"
 #include "chrome/browser/media/router/test_helper.h"
+#include "chrome/browser/sessions/session_tab_helper.h"
 #include "chrome/browser/ui/webui/media_router/media_router_ui.h"
 #include "chrome/browser/ui/webui/media_router/media_router_webui_message_handler.h"
 #include "chrome/grit/generated_resources.h"
@@ -49,6 +50,7 @@
   void CreateMediaRouterUI(Profile* profile) {
     initiator_.reset(content::WebContents::Create(
         content::WebContents::CreateParams(profile)));
+    SessionTabHelper::CreateForWebContents(initiator_.get());
     web_contents_.reset(content::WebContents::Create(
         content::WebContents::CreateParams(profile)));
     web_ui_.set_web_contents(web_contents_.get());
diff --git a/chrome/browser/ui/webui/settings/settings_default_browser_handler.cc b/chrome/browser/ui/webui/settings/settings_default_browser_handler.cc
index 881be4d..50b06b3 100644
--- a/chrome/browser/ui/webui/settings/settings_default_browser_handler.cc
+++ b/chrome/browser/ui/webui/settings/settings_default_browser_handler.cc
@@ -62,9 +62,6 @@
 
 void DefaultBrowserHandler::OnDefaultBrowserWorkerFinished(
     shell_integration::DefaultWebClientUIState state) {
-  if (state == shell_integration::STATE_PROCESSING)
-    return;
-
   if (state == shell_integration::STATE_IS_DEFAULT) {
     // Notify the user in the future if Chrome ceases to be the user's chosen
     // default browser.
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 01b4820..4daba223 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -3354,6 +3354,8 @@
             '../components/components.gyp:webusb',
             '../components/components_resources.gyp:components_resources',
             '../content/app/resources/content_resources.gyp:content_resources',
+            '../content/content.gyp:common_features',
+            '../content/content.gyp:feature_h264_with_openh264_ffmpeg',
             '../device/core/core.gyp:device_core',
             '../device/usb/usb.gyp:device_usb',
             '../device/usb/usb.gyp:device_usb_mojo_bindings',
@@ -3363,7 +3365,6 @@
             '../media/mojo/interfaces/mojo_bindings.gyp:platform_verification_api',
             '../mojo/mojo_base.gyp:mojo_application_base',
             '../mojo/mojo_base.gyp:mojo_common_lib',
-            '../mojo/mojo_base.gyp:mojo_environment_chromium',
             '../mojo/mojo_base.gyp:mojo_url_type_converters',
             '../mojo/mojo_edk.gyp:mojo_system_impl',
             '../mojo/mojo_public.gyp:mojo_cpp_bindings',
diff --git a/chrome/chrome_browser_ui.gypi b/chrome/chrome_browser_ui.gypi
index ac8a862c..795ffd9 100644
--- a/chrome/chrome_browser_ui.gypi
+++ b/chrome/chrome_browser_ui.gypi
@@ -79,7 +79,6 @@
       'browser/ui/browser_navigator_params.h',
       'browser/ui/browser_ui_prefs.cc',
       'browser/ui/browser_ui_prefs.h',
-      'browser/ui/browser_win.cc',
       'browser/ui/browser_window.h',
       'browser/ui/chrome_select_file_policy.cc',
       'browser/ui/chrome_select_file_policy.h',
diff --git a/chrome/chrome_common.gypi b/chrome/chrome_common.gypi
index 9328cf7..b64dd6e83 100644
--- a/chrome/chrome_common.gypi
+++ b/chrome/chrome_common.gypi
@@ -645,7 +645,6 @@
         'common/resource_usage_reporter.mojom',
       ],
       'dependencies': [
-        '../mojo/mojo_base.gyp:mojo_environment_chromium',
         '../mojo/mojo_public.gyp:mojo_cpp_bindings',
       ],
     },
diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi
index c0bbb801..636b0f7 100644
--- a/chrome/chrome_tests_unit.gypi
+++ b/chrome/chrome_tests_unit.gypi
@@ -2171,7 +2171,6 @@
         'common',
         'test_support_common',
         '../base/base.gyp:base',
-        '../mojo/mojo_base.gyp:mojo_environment_chromium',
         '../mojo/mojo_edk.gyp:mojo_system_impl',
         '../skia/skia.gyp:skia',
         '../sync/sync.gyp:sync',
diff --git a/chrome/common/extensions/permissions/chrome_permission_message_provider.cc b/chrome/common/extensions/permissions/chrome_permission_message_provider.cc
index cc2aae7..49db418 100644
--- a/chrome/common/extensions/permissions/chrome_permission_message_provider.cc
+++ b/chrome/common/extensions/permissions/chrome_permission_message_provider.cc
@@ -44,15 +44,6 @@
 };
 using ComparablePermissions = std::vector<ComparablePermission>;
 
-void DropPermissionParameter(APIPermission::ID id,
-                             PermissionIDSet* permissions) {
-  if (permissions->ContainsID(id)) {
-    // Erase the permission, and insert it again without a parameter.
-    permissions->erase(id);
-    permissions->insert(id);
-  }
-}
-
 }  // namespace
 
 typedef std::set<PermissionMessage> PermissionMsgSet;
@@ -185,20 +176,6 @@
   AddAPIPermissions(new_permissions, &new_ids);
   AddManifestPermissions(new_permissions, &new_ids);
 
-  // Ugly hack: Before M46 beta, we didn't store the parameter for settings
-  // override permissions in prefs (which is where |old_permissions| is coming
-  // from). To avoid a spurious permission increase warning, drop the parameter.
-  // See crbug.com/533086.
-  // TODO(treib,devlin): Remove this for M48, when hopefully all users will have
-  // updated prefs.
-  const APIPermission::ID kSettingsOverrideIDs[] = {
-      APIPermission::kHomepage, APIPermission::kSearchProvider,
-      APIPermission::kStartupPages};
-  for (auto id : kSettingsOverrideIDs) {
-    DropPermissionParameter(id, &old_ids);
-    DropPermissionParameter(id, &new_ids);
-  }
-
   // If all the IDs were already there, it's not a privilege increase.
   if (old_ids.Includes(new_ids))
     return false;
diff --git a/chrome/common/extensions/permissions/chrome_permission_message_provider_unittest.cc b/chrome/common/extensions/permissions/chrome_permission_message_provider_unittest.cc
index 2eab2a4..9ff56ddd 100644
--- a/chrome/common/extensions/permissions/chrome_permission_message_provider_unittest.cc
+++ b/chrome/common/extensions/permissions/chrome_permission_message_provider_unittest.cc
@@ -131,30 +131,4 @@
   EXPECT_FALSE(message1.submessages().empty());
 }
 
-// Anti-test: Check that adding a parameter to a SettingsOverridePermission
-// doesn't trigger a privilege increase. This is because prior to M46 beta, we
-// failed to store the parameter in the granted_permissions pref. Now we do, and
-// we don't want to bother every user with a spurious permissions warning.
-// See crbug.com/533086.
-// TODO(treib,devlin): Remove this for M48, when hopefully all users will have
-// updated prefs.
-TEST_F(ChromePermissionMessageProviderUnittest,
-       EvilHackToSuppressSettingsOverrideParameter) {
-  const APIPermissionInfo* info =
-      PermissionsInfo::GetInstance()->GetByID(APIPermission::kSearchProvider);
-
-  APIPermissionSet granted_permissions;
-  granted_permissions.insert(new SettingsOverrideAPIPermission(info));
-
-  APIPermissionSet actual_permissions;
-  actual_permissions.insert(new SettingsOverrideAPIPermission(info, "a.com"));
-
-  EXPECT_FALSE(IsPrivilegeIncrease(granted_permissions, actual_permissions));
-
-  // Just to be safe: Adding the permission (with or without parameter) should
-  // still be considered a privilege escalation.
-  EXPECT_TRUE(IsPrivilegeIncrease(APIPermissionSet(), granted_permissions));
-  EXPECT_TRUE(IsPrivilegeIncrease(APIPermissionSet(), actual_permissions));
-}
-
 }  // namespace extensions
diff --git a/chrome/installer/gcapi_mac/gcapi.mm b/chrome/installer/gcapi_mac/gcapi.mm
index c383b0b..c95c2ab 100644
--- a/chrome/installer/gcapi_mac/gcapi.mm
+++ b/chrome/installer/gcapi_mac/gcapi.mm
@@ -58,8 +58,8 @@
   // 10.2.
   int mac_os_x_minor_version = darwin_major_version - 4;
 
-  // Chrome is known to work on 10.6 - 10.10.
-  return mac_os_x_minor_version >= 6 && mac_os_x_minor_version <= 10;
+  // Chrome is known to work on 10.9 - 10.11.
+  return mac_os_x_minor_version >= 9 && mac_os_x_minor_version <= 11;
 }
 
 // Returns the pid/gid of the logged-in user, even if getuid() claims that the
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index c57b98c..2f0e7ab 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -2223,7 +2223,6 @@
     "//chrome/browser",
     "//chrome/common",
     "//mojo/edk/system",
-    "//mojo/environment:chromium",
   ]
 
   if (!is_android && use_ash) {
diff --git a/chrome/test/data/android/fragment.html b/chrome/test/data/android/fragment.html
new file mode 100644
index 0000000..b57d023
--- /dev/null
+++ b/chrome/test/data/android/fragment.html
@@ -0,0 +1,27 @@
+<html>
+
+<head>
+<title>Fragment Navigation Test.</title>
+</head>
+
+<body>
+    <a href="#test-fragment">Test Fragment</a>
+    <h1 id="visibility"></h1>
+    <h1 id="fragment"></h1>
+    <h1 id="initial-fragment"></h1>
+    <script>
+     var initialVisibility = "";
+     window.onhashchange = function () {
+         var hash = window.location.hash;
+         document.getElementById("fragment").innerHTML = hash;
+     }
+     window.onload = function () {
+         if (initialVisibility == "") {
+             initialVisibility = document.visibilityState;
+             document.getElementById("visibility").innerHTML = initialVisibility;
+         }
+         document.getElementById("initial-fragment").innerHTML = window.location.hash;
+     }
+    </script>
+</body>
+</html>
diff --git a/chrome/test/data/extensions/update_from_webstore2.pem b/chrome/test/data/extensions/update_from_webstore2.pem
new file mode 100644
index 0000000..f93c2bc
--- /dev/null
+++ b/chrome/test/data/extensions/update_from_webstore2.pem
@@ -0,0 +1,15 @@
+-----BEGIN PRIVATE KEY-----
+MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAMWHeR/rCAn3Bk8NV
+Rbet1j7x6pZ8u80IJDw26ejxnwDL1iQc8GFbcejNxDNZOa+j82dniqL25sQfoP8KZ
+7p9EoT6iK+YoLQDxeZCskEK+lxe2e6h+51qEN8ASAHpq6KJ2kIruClixl/0rWrMIp
+w8KiYNoYxZhHy7nMgu8RQD2bvAgMBAAECgYANi4Kky6sbc9L87L8e+Fq+QVWpus1L
+1dk91yZY0oQz0MwYWJ93b7zdabXG8y6uG/ckdGB6Lmj6syDZ0BrSiNx1cRlz5DSH2
+kGpSTrYRj4/c5s8E7VESTbvqa9GersHjD7VVm7t0gcgzkEENS6Xqi+qxS1d0iQdXN
+8VLXHAn9g9kQJBAOe/N4mWu0D3fmQt2WYFbL+O7ujWphrvpKiiS7/aso/vvhccSAn
+hrLJByEFhavyWEgml1EUOkxOPHPSMHXDEFesCQQDaM4VfYbUr4xpaHE8kjsAJJ56X
+Dl0P6eboZNuvgDSHIHMo7WI1httZmIjNVol6i0uoMQ0YUoLNzUal7IsYql4NAkApE
+1tkp7LI8RUV7Ip76ro7ubneyyzl2VP2D84dU0YS/QtUTU73cWiKr94uuHWeD3ti+m
+GFW+/1p4gaUDtnoVnBAkBvd1hPxHMvq0E//Sw06bOSOaobUpwZ0AxEdZmASwcKbHp
+H0xSTcYPGflSMSQPMFTKeBgjBfw0RIydPBcp83DNVAkB0r8S2vQyMQzlyq8L05qXg
+SHel0mIgxqLmCC6wi2sPKuKauqztTpRavfR060tnNz2otXX3hENxtu0chpsSRJov
+-----END PRIVATE KEY-----
diff --git a/chrome/test/data/extensions/update_from_webstore2/manifest.json b/chrome/test/data/extensions/update_from_webstore2/manifest.json
new file mode 100644
index 0000000..b35bb03
--- /dev/null
+++ b/chrome/test/data/extensions/update_from_webstore2/manifest.json
@@ -0,0 +1,6 @@
+{
+  "name": "Second test extension that updates from webstore",
+  "version": "1",
+  "manifest_version": 2,
+  "update_url": "https://clients2.google.com/service/update2/crx"
+}
diff --git a/chrome/test/data/extensions/update_from_webstore3.pem b/chrome/test/data/extensions/update_from_webstore3.pem
new file mode 100644
index 0000000..f69f4964
--- /dev/null
+++ b/chrome/test/data/extensions/update_from_webstore3.pem
@@ -0,0 +1,16 @@
+-----BEGIN PRIVATE KEY-----
+MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAMRkvle1bZcmaeGv1
+/Ia8WRIosC5dr7E70gP3XOfwE+70EnC+Ytj3aU99VBbFow2tTgC2uAY+0P5HXvH9K
+woeJdPtOOPdRZ+VvE9JqwsEKps+C915YPb7iYIIoU3IXEe3O3ox8F4bPu1iiNabtr
+n6lopCH7E22QeSR5hPdVO8fq5AgMBAAECgYEAn0I23HdClHTRHfPzwN+6aqFAYdrE
+AXU/uQcshKvCTqY2BOq4ZCGqxmoU+YG0KiXfFLmz9lAryfZEw3Dl54m2J0oKHLgpX
+Fh2NsNPBAFTIgz8LLqXZxQ/30luxPLipTOX4mcN0ULX0MkQsxf/TgS0PrCPfgzFBU
+SKDETsBO7g/dUCQQDjE2zhcxMrmuqpF1Cy0G28+IzBjI0YooM2ZHiaSh/r/yO8ywN
+DLS3TTD0RggHJiqRCZnlrYgzDeqPW1aPv2tSXAkEA3WjRFEhAjtB5Ct4npVIyqGzW
+q+hQncG48T7PmOXdN+jL72XafEkKTJ0N0wghr9YwFda2EyBD0HD1FKnW+xIFLwJAW
+p3A4IMUjl0m8c1tFb6ZXETvnrlhAQixRf54JlIYRQwvDcMSDTe1RtHwuNDht7TM8f
+aE07ZwE34Ybb4ZyrjQBwJAfW7MRDlKmZ3xdP62ZypSGKjQVUOfqD//jmyPH4fZ87q
+nDlEdnhujAhRXqJ6KtxsY0sZ5EAzPXl8f+Tze1g43cQJAQa/Ycwm+IuaSkYeOM7oJ
+by7PRPZ7CqQknxBLfGgCnfmhEIcfNaa1+o+Fbf8GZNlQNzkxmq3zD9TDEn5zCdRa/
+w==
+-----END PRIVATE KEY-----
diff --git a/chrome/test/data/extensions/update_from_webstore3/manifest.json b/chrome/test/data/extensions/update_from_webstore3/manifest.json
new file mode 100644
index 0000000..dfba7e5
--- /dev/null
+++ b/chrome/test/data/extensions/update_from_webstore3/manifest.json
@@ -0,0 +1,6 @@
+{
+  "name": "Third test extension that updates from webstore",
+  "version": "1",
+  "manifest_version": 2,
+  "update_url": "https://clients2.google.com/service/update2/crx"
+}
diff --git a/chrome/test/data/translate/OWNERS b/chrome/test/data/translate/OWNERS
index 65f9e61..a214ab1 100644
--- a/chrome/test/data/translate/OWNERS
+++ b/chrome/test/data/translate/OWNERS
@@ -1,4 +1,3 @@
-set noparent
 hajimehoshi@chromium.org
 mad@chromium.org
 toyoshim@chromium.org
diff --git a/chromecast/browser/media/cast_renderer.cc b/chromecast/browser/media/cast_renderer.cc
index badc7cb..0e0512f 100644
--- a/chromecast/browser/media/cast_renderer.cc
+++ b/chromecast/browser/media/cast_renderer.cc
@@ -98,6 +98,7 @@
       init_cb.Run(status);
       return;
     }
+    audio_stream->EnableBitstreamConverter();
   }
 
   // Initialize video.
@@ -124,6 +125,7 @@
       init_cb.Run(status);
       return;
     }
+    video_stream->EnableBitstreamConverter();
   }
 
   ended_cb_ = ended_cb;
diff --git a/chromecast/media/media.gyp b/chromecast/media/media.gyp
index 51a772c..6cabfc7 100644
--- a/chromecast/media/media.gyp
+++ b/chromecast/media/media.gyp
@@ -35,6 +35,7 @@
       'type': '<(component)',
       'dependencies': [
         '../../media/media.gyp:media',
+        'cma_backend_manager',
       ],
       'sources': [
         'audio/cast_audio_manager.cc',
@@ -156,16 +157,28 @@
       'sources': [
         'cma/backend/audio_decoder_default.cc',
         'cma/backend/audio_decoder_default.h',
-        'cma/backend/audio_decoder_wrapper.cc',
-        'cma/backend/audio_decoder_wrapper.h',
         'cma/backend/media_pipeline_backend_default.cc',
         'cma/backend/media_pipeline_backend_default.h',
+        'cma/backend/video_decoder_default.cc',
+        'cma/backend/video_decoder_default.h',
+      ],
+    },
+    {
+      'target_name': 'cma_backend_manager',
+      'type': '<(component)',
+      'dependencies': [
+        '../../base/base.gyp:base',
+      ],
+      'include_dirs': [
+        '../..',
+      ],
+      'sources': [
+        'cma/backend/audio_decoder_wrapper.cc',
+        'cma/backend/audio_decoder_wrapper.h',
         'cma/backend/media_pipeline_backend_manager.cc',
         'cma/backend/media_pipeline_backend_manager.h',
         'cma/backend/media_pipeline_backend_wrapper.cc',
         'cma/backend/media_pipeline_backend_wrapper.h',
-        'cma/backend/video_decoder_default.cc',
-        'cma/backend/video_decoder_default.h',
       ],
     },
     {
diff --git a/chromeos/audio/cras_audio_handler.cc b/chromeos/audio/cras_audio_handler.cc
index 64114c9..d008d86 100644
--- a/chromeos/audio/cras_audio_handler.cc
+++ b/chromeos/audio/cras_audio_handler.cc
@@ -425,6 +425,11 @@
 void CrasAudioHandler::SaveDeviceState(const AudioDevice& device,
                                        bool active,
                                        DeviceActivateType activate_by) {
+  // Don't save the active state for non-simple usage device, which is invisible
+  // to end users.
+  if (!device.is_for_simple_usage())
+    return;
+
   if (!active) {
     audio_pref_handler_->SetDeviceActive(device, false, false);
   } else {
@@ -924,7 +929,7 @@
   for (AudioDeviceMap::const_iterator it = audio_devices_.begin();
        it != audio_devices_.end(); ++it) {
     AudioDevice device = it->second;
-    if (device.is_input != is_input)
+    if (device.is_input != is_input || !device.is_for_simple_usage())
       continue;
 
     bool active = false;
@@ -993,7 +998,6 @@
     return;
 
   if (hotplug_nodes.empty()) {
-    // Unplugged a non-active device.
     if (has_device_removed) {
       if (!active_device_removed && has_current_active_node) {
         // Removed a non-active device, keep the current active device.
@@ -1010,7 +1014,7 @@
     // Some unexpected error happens on cras side. See crbug.com/586026.
     // Either cras sent stale nodes to chrome again or cras triggered some
     // error. Restore the previously selected active.
-    VLOG(1) << "Odd case from cras, the active node is lost unexpectedly. ";
+    VLOG(1) << "Odd case from cras, the active node is lost unexpectedly.";
     SwitchToPreviousActiveDeviceIfAvailable(is_input);
   } else {
     // Looks like a new chrome session starts.
@@ -1021,6 +1025,12 @@
 void CrasAudioHandler::HandleHotPlugDevice(
     const AudioDevice& hotplug_device,
     const AudioDevicePriorityQueue& device_priority_queue) {
+  // This most likely may happen during the transition period of cras
+  // initialization phase, in which a non-simple-usage node may appear like
+  // a hotplug node.
+  if (!hotplug_device.is_for_simple_usage())
+    return;
+
   bool last_state_active = false;
   bool last_activate_by_user = false;
   if (!audio_pref_handler_->GetDeviceActive(hotplug_device, &last_state_active,
@@ -1046,12 +1056,14 @@
 void CrasAudioHandler::SwitchToTopPriorityDevice(bool is_input) {
   AudioDevice top_device =
       is_input ? input_devices_pq_.top() : output_devices_pq_.top();
-  SwitchToDevice(top_device, true, ACTIVATE_BY_PRIORITY);
+  if (top_device.is_for_simple_usage())
+    SwitchToDevice(top_device, true, ACTIVATE_BY_PRIORITY);
 }
 
 void CrasAudioHandler::SwitchToPreviousActiveDeviceIfAvailable(bool is_input) {
   AudioDevice previous_active_device;
   if (GetActiveDeviceFromUserPref(is_input, &previous_active_device)) {
+    DCHECK(previous_active_device.is_for_simple_usage());
     // Switch to previous active device stored in user prefs.
     SwitchToDevice(previous_active_device, true,
                    ACTIVATE_BY_RESTORE_PREVIOUS_STATE);
diff --git a/chromeos/audio/cras_audio_handler_unittest.cc b/chromeos/audio/cras_audio_handler_unittest.cc
index 9566065..5fadd6f 100644
--- a/chromeos/audio/cras_audio_handler_unittest.cc
+++ b/chromeos/audio/cras_audio_handler_unittest.cc
@@ -575,6 +575,27 @@
   EXPECT_FALSE(inactive_keyboard_mic->active);
 }
 
+TEST_F(CrasAudioHandlerTest, KeyboardMicNotSetAsPrimaryActive) {
+  AudioNodeList audio_nodes;
+  audio_nodes.push_back(kKeyboardMic);
+  SetUpCrasAudioHandler(audio_nodes);
+
+  // Verify keyboard mic is not set as primary active input.
+  AudioDeviceList audio_devices;
+  cras_audio_handler_->GetAudioDevices(&audio_devices);
+  EXPECT_EQ(audio_nodes.size(), audio_devices.size());
+  EXPECT_TRUE(cras_audio_handler_->HasKeyboardMic());
+  EXPECT_EQ(0u, cras_audio_handler_->GetPrimaryActiveInputNode());
+
+  // Verify the internal mic is set as primary input.
+  audio_nodes.push_back(kInternalMic);
+  ChangeAudioNodes(audio_nodes);
+  cras_audio_handler_->GetAudioDevices(&audio_devices);
+  EXPECT_EQ(audio_nodes.size(), audio_devices.size());
+  EXPECT_TRUE(cras_audio_handler_->HasKeyboardMic());
+  EXPECT_EQ(kInternalMic.id, cras_audio_handler_->GetPrimaryActiveInputNode());
+}
+
 TEST_F(CrasAudioHandlerTest, SwitchActiveOutputDevice) {
   AudioNodeList audio_nodes;
   audio_nodes.push_back(kInternalSpeaker);
diff --git a/components/arc/BUILD.gn b/components/arc/BUILD.gn
index 7e8349d..47ff2492 100644
--- a/components/arc/BUILD.gn
+++ b/components/arc/BUILD.gn
@@ -110,7 +110,6 @@
     "//base",
     "//chromeos",
     "//ipc/mojo:mojo",
-    "//mojo/public/cpp/environment:environment",
     "//mojo/public/cpp/system:system",
     "//testing/gtest",
     "//ui/aura",
diff --git a/components/arc/arc_bridge_service_unittest.cc b/components/arc/arc_bridge_service_unittest.cc
index 79b1fd0..c753f23 100644
--- a/components/arc/arc_bridge_service_unittest.cc
+++ b/components/arc/arc_bridge_service_unittest.cc
@@ -12,7 +12,6 @@
 #include "components/arc/arc_bridge_service_impl.h"
 #include "components/arc/test/fake_arc_bridge_instance.h"
 #include "ipc/mojo/scoped_ipc_support.h"
-#include "mojo/public/cpp/environment/environment.h"
 #include "mojo/public/cpp/system/message_pipe.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/components/contextual_search/BUILD.gn b/components/contextual_search/BUILD.gn
index 096c54a..8d54602 100644
--- a/components/contextual_search/BUILD.gn
+++ b/components/contextual_search/BUILD.gn
@@ -40,7 +40,6 @@
     "//content/public/common",
     "//content/public/renderer",
     "//gin",
-    "//mojo/environment:chromium",
     "//mojo/public/cpp/bindings",
     "//third_party/WebKit/public:blink_headers",
     "//v8",
diff --git a/components/dom_distiller.gypi b/components/dom_distiller.gypi
index b6d25e3..adf078e1 100644
--- a/components/dom_distiller.gypi
+++ b/components/dom_distiller.gypi
@@ -162,7 +162,6 @@
             'dom_distiller_protos',
             '../base/base.gyp:base',
             '../content/content.gyp:content_browser',
-            '../mojo/mojo_base.gyp:mojo_environment_chromium',
             '../mojo/mojo_public.gyp:mojo_cpp_bindings',
             '../net/net.gyp:net',
             '../skia/skia.gyp:skia',
@@ -214,7 +213,6 @@
             '../base/base.gyp:base',
             '../content/content.gyp:content_browser',
             '../gin/gin.gyp:gin',
-            '../mojo/mojo_base.gyp:mojo_environment_chromium',
             '../mojo/mojo_public.gyp:mojo_cpp_bindings',
           ],
           'include_dirs': [
diff --git a/components/dom_distiller/content/browser/BUILD.gn b/components/dom_distiller/content/browser/BUILD.gn
index db8c9fed..db24bc2 100644
--- a/components/dom_distiller/content/browser/BUILD.gn
+++ b/components/dom_distiller/content/browser/BUILD.gn
@@ -36,7 +36,6 @@
     "//components/strings",
     "//content/public/browser",
     "//content/public/common",
-    "//mojo/environment:chromium",
     "//mojo/public/cpp/bindings",
     "//net",
     "//skia",
diff --git a/components/dom_distiller/content/renderer/BUILD.gn b/components/dom_distiller/content/renderer/BUILD.gn
index f4e1f1e..a442dec9 100644
--- a/components/dom_distiller/content/renderer/BUILD.gn
+++ b/components/dom_distiller/content/renderer/BUILD.gn
@@ -26,7 +26,6 @@
     "//content/public/common",
     "//content/public/renderer",
     "//gin",
-    "//mojo/environment:chromium",
     "//mojo/public/cpp/bindings",
     "//skia",
     "//third_party/WebKit/public:blink_headers",
diff --git a/components/filesystem/BUILD.gn b/components/filesystem/BUILD.gn
index 5cfeed20..ff284242 100644
--- a/components/filesystem/BUILD.gn
+++ b/components/filesystem/BUILD.gn
@@ -44,7 +44,6 @@
     "//base",
     "//components/filesystem/public/interfaces",
     "//mojo/common",
-    "//mojo/environment:chromium",
     "//mojo/platform_handle:for_shared_library",
     "//mojo/public/cpp/bindings",
     "//mojo/public/cpp/system",
diff --git a/components/leveldb/BUILD.gn b/components/leveldb/BUILD.gn
index d713fa376..32787b4 100644
--- a/components/leveldb/BUILD.gn
+++ b/components/leveldb/BUILD.gn
@@ -42,7 +42,6 @@
     ":manifest",
     "//components/leveldb/public/interfaces",
     "//mojo/common",
-    "//mojo/environment:chromium",
     "//mojo/platform_handle:for_shared_library",
     "//mojo/public/cpp/bindings",
     "//mojo/public/cpp/system",
diff --git a/components/mus/public/cpp/BUILD.gn b/components/mus/public/cpp/BUILD.gn
index d750a9d7..7df9d20 100644
--- a/components/mus/public/cpp/BUILD.gn
+++ b/components/mus/public/cpp/BUILD.gn
@@ -55,7 +55,6 @@
     "//mojo/gles2",
     "//mojo/gpu:mojo_gles2_implementation",
     "//mojo/public/cpp/bindings:bindings",
-    "//mojo/public/cpp/environment",
     "//mojo/public/cpp/system",
     "//mojo/shell/public/cpp",
     "//mojo/shell/public/interfaces",
diff --git a/components/mus/ws/BUILD.gn b/components/mus/ws/BUILD.gn
index 8543f976..e9f94f0 100644
--- a/components/mus/ws/BUILD.gn
+++ b/components/mus/ws/BUILD.gn
@@ -174,7 +174,6 @@
     "//mojo/converters/input_events",
     "//mojo/converters/transform",
     "//mojo/edk/test:run_all_unittests",
-    "//mojo/environment:chromium",
     "//mojo/gles2",
     "//mojo/platform_handle:for_shared_library",
     "//mojo/public/cpp/bindings:bindings",
diff --git a/components/page_load_metrics/browser/metrics_web_contents_observer.cc b/components/page_load_metrics/browser/metrics_web_contents_observer.cc
index 886d3cb1..9452877 100644
--- a/components/page_load_metrics/browser/metrics_web_contents_observer.cc
+++ b/components/page_load_metrics/browser/metrics_web_contents_observer.cc
@@ -103,10 +103,7 @@
 
   if (!EventsInOrder(timing.dom_content_loaded_event_start,
                      timing.load_event_start)) {
-    // TODO(csharrison) crbug.com/536203 shows that sometimes we can get a load
-    // event without a DCL. Figure out if we can change this condition to use a
-    // DLOG(FATAL) in the condition.
-    DLOG(ERROR) << "Invalid dom_content_loaded_event_start "
+    DLOG(FATAL) << "Invalid dom_content_loaded_event_start "
                 << timing.dom_content_loaded_event_start
                 << " for load_event_start " << timing.load_event_start;
     return false;
diff --git a/components/resource_provider/BUILD.gn b/components/resource_provider/BUILD.gn
index 6a7a7e5..bcdb01a 100644
--- a/components/resource_provider/BUILD.gn
+++ b/components/resource_provider/BUILD.gn
@@ -34,7 +34,6 @@
       "//base",
       "//build/config/sanitizers:deps",
       "//components/resource_provider/public/interfaces",
-      "//mojo/environment:chromium",
       "//mojo/platform_handle:for_shared_library",
       "//mojo/public/c/system:for_shared_library",
       "//mojo/shell/public/cpp",
@@ -75,7 +74,6 @@
       ":manifest",
       "//base",
       "//components/resource_provider/public/interfaces",
-      "//mojo/environment:chromium",
       "//mojo/shell/public/cpp",
       "//url",
     ]
@@ -119,7 +117,6 @@
     "//base/test:test_config",
     "//components/resource_provider/public/interfaces",
     "//mojo/edk/test:run_all_unittests",
-    "//mojo/environment:chromium",
     "//mojo/platform_handle:for_shared_library",
     "//testing/gtest",
     "//url",
diff --git a/content/app/BUILD.gn b/content/app/BUILD.gn
index 435a39e..96dca6d 100644
--- a/content/app/BUILD.gn
+++ b/content/app/BUILD.gn
@@ -59,7 +59,6 @@
   content_app_deps += [
     "//mojo/shell/public/interfaces",
     "//mojo/edk/system",
-    "//mojo/environment:chromium",
   ]
 }
 
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 6233648..a455bac 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -6,6 +6,7 @@
 import("//build/config/ui.gni")
 import("//content/browser/browser.gni")
 import("//media/media_options.gni")
+import("//mojo/public/mojo_application_manifest.gni")
 
 source_set("browser") {
   # Only the public target should depend on this. All other targets (even
@@ -22,6 +23,7 @@
 
   # Shared deps. See also non-iOS deps below.
   deps = [
+    ":chrome_renderer_manifest",
     "//base",
     "//base:base_static",
     "//components/mime_util",
@@ -535,3 +537,9 @@
     ]
   }
 }
+
+mojo_application_manifest("chrome_renderer_manifest") {
+  type = "exe"
+  application_name = "chrome_renderer"
+  source = "mojo/chrome_renderer_manifest.json"
+}
diff --git a/content/browser/mojo/OWNERS b/content/browser/mojo/OWNERS
deleted file mode 100644
index 570120f..0000000
--- a/content/browser/mojo/OWNERS
+++ /dev/null
@@ -1,13 +0,0 @@
-# Changes to the renderer capability filter require a security review to avoid
-# exposing new sandbox escapes and undesirable services.
-per-file renderer_capability_filter.cc=set noparent
-per-file renderer_capability_filter.cc=dcheng@chromium.org
-per-file renderer_capability_filter.cc=inferno@chromium.org
-per-file renderer_capability_filter.cc=jln@chromium.org
-per-file renderer_capability_filter.cc=jschuh@chromium.org
-per-file renderer_capability_filter.cc=kenrb@chromium.org
-per-file renderer_capability_filter.cc=mkwst@chromium.org
-per-file renderer_capability_filter.cc=nasko@chromium.org
-per-file renderer_capability_filter.cc=palmer@chromium.org
-per-file renderer_capability_filter.cc=tsepez@chromium.org
-per-file renderer_capability_filter.cc=wfh@chromium.org
diff --git a/content/browser/mojo/chrome_renderer_manifest.json b/content/browser/mojo/chrome_renderer_manifest.json
new file mode 100644
index 0000000..463be6d2
--- /dev/null
+++ b/content/browser/mojo/chrome_renderer_manifest.json
@@ -0,0 +1,5 @@
+{
+  "name": "exe:chrome_renderer",
+  "display_name": "Chrome Renderer",
+  "capabilities": { "mojo:mus": [ "mus::mojom::Gpu" ] }
+}
diff --git a/content/browser/mojo/mojo_shell_client_host.cc b/content/browser/mojo/mojo_shell_client_host.cc
index e762c225..a0e23a9 100644
--- a/content/browser/mojo/mojo_shell_client_host.cc
+++ b/content/browser/mojo/mojo_shell_client_host.cc
@@ -25,26 +25,26 @@
 namespace content {
 namespace {
 
-const char kMojoShellInstanceURL[] = "mojo_shell_instance_url";
+const char kMojoShellInstanceIdentity[] = "mojo_shell_instance_identity";
 
-class InstanceURL : public base::SupportsUserData::Data {
+class InstanceIdentity : public base::SupportsUserData::Data {
  public:
-  explicit InstanceURL(const std::string& instance_url)
-      : instance_url_(instance_url) {}
-  ~InstanceURL() override {}
+  explicit InstanceIdentity(const mojo::Identity& identity)
+      : identity_(identity) {}
+  ~InstanceIdentity() override {}
 
-  std::string get() const { return instance_url_; }
+  mojo::Identity get() const { return identity_; }
 
  private:
-  std::string instance_url_;
+  mojo::Identity identity_;
 
-  DISALLOW_COPY_AND_ASSIGN(InstanceURL);
+  DISALLOW_COPY_AND_ASSIGN(InstanceIdentity);
 };
 
-void SetMojoApplicationInstanceURL(RenderProcessHost* render_process_host,
-                                   const std::string& instance_url) {
-  render_process_host->SetUserData(kMojoShellInstanceURL,
-                                   new InstanceURL(instance_url));
+void SetMojoIdentity(RenderProcessHost* render_process_host,
+                     const mojo::Identity& identity) {
+  render_process_host->SetUserData(kMojoShellInstanceIdentity,
+                                   new InstanceIdentity(identity));
 }
 
 class PIDSender : public RenderProcessHostObserver {
@@ -105,16 +105,6 @@
   MojoShellConnection::Get()->GetConnector()->ConnectToInterface(
       "mojo:shell", &shell);
 
-  // The content of the URL/qualifier we pass is actually meaningless, it's only
-  // important that they're unique per process.
-  // TODO(beng): We need to specify a restrictive CapabilityFilter here that
-  //             matches the needs of the target process. Figure out where that
-  //             specification is best determined (not here, this is a common
-  //             chokepoint for all process types) and how to wire it through.
-  //             http://crbug.com/555393
-  std::string url = base::StringPrintf(
-      "exe:chrome_renderer%d_%d", child_process_id, instance_id);
-
   mojo::shell::mojom::PIDReceiverPtr pid_receiver;
   mojo::InterfaceRequest<mojo::shell::mojom::PIDReceiver> request =
       GetProxy(&pid_receiver);
@@ -124,26 +114,25 @@
   factory.Bind(mojo::InterfacePtrInfo<mojo::shell::mojom::ShellClientFactory>(
       std::move(request_pipe), 0u));
 
-  mojo::shell::mojom::IdentityPtr target(mojo::shell::mojom::Identity::New());
-  target->name = url;
-  target->user_id = mojo::shell::mojom::kInheritUserID;
-  target->instance = "";
-  shell->CreateInstance(std::move(factory), std::move(target),
-                        CreateCapabilityFilterForRenderer(),
+  mojo::Identity target("exe:chrome_renderer",
+                        mojo::shell::mojom::kInheritUserID,
+                        base::StringPrintf("%d_%d", child_process_id,
+                                           instance_id));
+  shell->CreateInstance(std::move(factory),
+                        mojo::shell::mojom::Identity::From(target),
                         std::move(request), base::Bind(&OnConnectionComplete));
 
-  // Store the URL on the RPH so client code can access it later via
-  // GetMojoApplicationInstanceURL().
-  SetMojoApplicationInstanceURL(render_process_host, url);
+  // Store the Identity on the RPH so client code can access it later via
+  // GetMojoIdentity().
+  SetMojoIdentity(render_process_host, target);
 
   return pipe_token;
 }
 
-std::string GetMojoApplicationInstanceURL(
-    RenderProcessHost* render_process_host) {
-  InstanceURL* instance_url = static_cast<InstanceURL*>(
-      render_process_host->GetUserData(kMojoShellInstanceURL));
-  return instance_url ? instance_url->get() : std::string();
+mojo::Identity GetMojoIdentity(RenderProcessHost* render_process_host) {
+  InstanceIdentity* instance_identity = static_cast<InstanceIdentity*>(
+      render_process_host->GetUserData(kMojoShellInstanceIdentity));
+  return instance_identity ? instance_identity->get() : mojo::Identity();
 }
 
 }  // namespace content
diff --git a/content/browser/mojo/mojo_shell_client_host.h b/content/browser/mojo/mojo_shell_client_host.h
index 3b1484f4..faed042 100644
--- a/content/browser/mojo/mojo_shell_client_host.h
+++ b/content/browser/mojo/mojo_shell_client_host.h
@@ -8,6 +8,7 @@
 #include <string>
 
 #include "base/process/process_handle.h"
+#include "mojo/shell/public/cpp/identity.h"
 #include "mojo/shell/public/interfaces/shell.mojom.h"
 
 namespace content {
@@ -28,18 +29,10 @@
     int instance_id,
     RenderProcessHost* render_process_host);
 
-// Returns the URL associated with an instance corresponding to the renderer
-// process in the external shell. This URL can be passed to
-// ConnectToApplication() to open a new connection to this renderer.
-std::string GetMojoApplicationInstanceURL(
-    RenderProcessHost* render_process_host);
-
-// Constructs a Capability Filter for the renderer's application instance in the
-// external shell. This contains the restrictions imposed on what applications
-// and interfaces the renderer can see. The implementation lives in
-// renderer_capability_filter.cc so that it can be subject to specific security
-// review.
-mojo::shell::mojom::CapabilityFilterPtr CreateCapabilityFilterForRenderer();
+// Returns the Identity associated with an instance corresponding to the
+// renderer process in shell. This Identity can be passed to Connect() to open a
+// new connection to this renderer.
+mojo::Identity GetMojoIdentity(RenderProcessHost* render_process_host);
 
 }  // namespace content
 
diff --git a/content/browser/mojo/renderer_capability_filter.cc b/content/browser/mojo/renderer_capability_filter.cc
deleted file mode 100644
index c08f5e9..0000000
--- a/content/browser/mojo/renderer_capability_filter.cc
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <utility>
-
-#include "content/browser/mojo/mojo_shell_client_host.h"
-
-#if defined(MOJO_SHELL_CLIENT)
-#include "components/mus/public/interfaces/gpu.mojom.h"
-#endif
-
-namespace content {
-
-mojo::shell::mojom::CapabilityFilterPtr CreateCapabilityFilterForRenderer() {
-  // See https://goo.gl/gkBtCR for a description of what this is and what to
-  // think about when changing it.
-  mojo::shell::mojom::CapabilityFilterPtr filter(
-      mojo::shell::mojom::CapabilityFilter::New());
-  filter->filter.SetToEmpty();
-#if defined(MOJO_SHELL_CLIENT)
-  mojo::Array<mojo::String> window_manager_interfaces;
-  window_manager_interfaces.push_back(mus::mojom::Gpu::Name_);
-  filter->filter.insert("mojo:mus", std::move(window_manager_interfaces));
-#endif
-  return filter;
-}
-
-}  // namespace content
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 34f50aa..867d81a 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -1055,7 +1055,8 @@
   bool enable_web_bluetooth =
       browser_command_line.HasSwitch(switches::kEnableWebBluetooth);
 #if defined(OS_CHROMEOS) || defined(OS_ANDROID)
-  enable_web_bluetooth = true;
+// TODO(https://crbug.com/584113) Enable Web Bluetooth Experiment.
+// enable_web_bluetooth = true;
 #endif
 
   if (enable_web_bluetooth) {
diff --git a/content/browser/renderer_host/render_widget_host_view_mus.cc b/content/browser/renderer_host/render_widget_host_view_mus.cc
index 9ddef3ee..3157266 100644
--- a/content/browser/renderer_host/render_widget_host_view_mus.cc
+++ b/content/browser/renderer_host/render_widget_host_view_mus.cc
@@ -38,9 +38,10 @@
 
   // Connect to the renderer, pass it a WindowTreeClient interface request
   // and embed that client inside our mus window.
-  std::string url = GetMojoApplicationInstanceURL(host_->GetProcess());
+  mojo::Identity identity = GetMojoIdentity(host_->GetProcess());
   mojom::RenderWidgetWindowTreeClientFactoryPtr factory;
-  MojoShellConnection::Get()->GetConnector()->ConnectToInterface(url, &factory);
+  MojoShellConnection::Get()->GetConnector()->ConnectToInterface(
+      identity, &factory);
 
   mus::mojom::WindowTreeClientPtr window_tree_client;
   factory->CreateWindowTreeClientForRenderWidget(
diff --git a/content/browser/tracing/background_tracing_manager_browsertest.cc b/content/browser/tracing/background_tracing_manager_browsertest.cc
index e2d1177..e0001b8 100644
--- a/content/browser/tracing/background_tracing_manager_browsertest.cc
+++ b/content/browser/tracing/background_tracing_manager_browsertest.cc
@@ -184,18 +184,9 @@
   }
 }
 
-#if defined(THREAD_SANITIZER)
-// There's a race in ConvertableToTraceFormat that's hard to suppress,
-// see http://crbug.com/559117.
-#define MAYBE_CallTriggersMoreThanOnceOnlyGatherOnce \
-    DISABLED_CallTriggersMoreThanOnceOnlyGatherOnce
-#else
-#define MAYBE_CallTriggersMoreThanOnceOnlyGatherOnce \
-    CallTriggersMoreThanOnceOnlyGatherOnce
-#endif
 // This tests triggering more than once still only gathers once.
 IN_PROC_BROWSER_TEST_F(BackgroundTracingManagerBrowserTest,
-                       MAYBE_CallTriggersMoreThanOnceOnlyGatherOnce) {
+                       CallTriggersMoreThanOnceOnlyGatherOnce) {
   {
     SetupBackgroundTracingManager();
 
diff --git a/content/child/BUILD.gn b/content/child/BUILD.gn
index 0ab48e1..0c8384fe 100644
--- a/content/child/BUILD.gn
+++ b/content/child/BUILD.gn
@@ -32,7 +32,6 @@
     "//components/webcrypto",
     "//content/common:mojo_bindings",
     "//mojo/common",
-    "//mojo/environment:chromium",
     "//mojo/message_pump",
     "//mojo/shell/public/interfaces",
     "//net",
diff --git a/content/common/BUILD.gn b/content/common/BUILD.gn
index 3dbb1306..e5e1929 100644
--- a/content/common/BUILD.gn
+++ b/content/common/BUILD.gn
@@ -195,7 +195,6 @@
       "//media/midi",
       "//mojo/common:common_base",
       "//mojo/edk/system",
-      "//mojo/environment:chromium",
       "//mojo/shell/public/interfaces",
       "//sandbox",
       "//storage/common",
diff --git a/content/common/gpu/gpu_channel_manager.cc b/content/common/gpu/gpu_channel_manager.cc
index 7243774..feb2def 100644
--- a/content/common/gpu/gpu_channel_manager.cc
+++ b/content/common/gpu/gpu_channel_manager.cc
@@ -18,7 +18,6 @@
 #include "content/common/gpu/gpu_memory_buffer_factory.h"
 #include "content/common/gpu/gpu_memory_manager.h"
 #include "content/common/gpu/gpu_messages.h"
-#include "content/common/gpu/image_transport_surface.h"
 #include "gpu/command_buffer/common/sync_token.h"
 #include "gpu/command_buffer/common/value_state.h"
 #include "gpu/command_buffer/service/feature_info.h"
@@ -119,20 +118,24 @@
 }
 
 #if defined(OS_MACOSX)
-void GpuChannelManager::AddImageTransportSurface(
+void GpuChannelManager::AddBufferPresentedCallback(
     int32_t surface_id,
-    ImageTransportHelper* image_transport_helper) {
-  image_transport_map_.AddWithID(image_transport_helper, surface_id);
+    const BufferPresentedCallback& callback) {
+  DCHECK(buffer_presented_callback_map_.find(surface_id) ==
+         buffer_presented_callback_map_.end());
+  buffer_presented_callback_map_[surface_id] = callback;
 }
 
-void GpuChannelManager::RemoveImageTransportSurface(int32_t surface_id) {
-  image_transport_map_.Remove(surface_id);
+void GpuChannelManager::RemoveBufferPresentedCallback(int32_t surface_id) {
+  auto it = buffer_presented_callback_map_.find(surface_id);
+  DCHECK(it != buffer_presented_callback_map_.end());
+  buffer_presented_callback_map_.erase(it);
 }
 
 void GpuChannelManager::BufferPresented(const BufferPresentedParams& params) {
-  ImageTransportHelper* helper = image_transport_map_.Lookup(params.surface_id);
-  if (helper)
-    helper->BufferPresented(params);
+  auto it = buffer_presented_callback_map_.find(params.surface_id);
+  if (it != buffer_presented_callback_map_.end())
+    it->second.Run(params);
 }
 #endif
 
diff --git a/content/common/gpu/gpu_channel_manager.h b/content/common/gpu/gpu_channel_manager.h
index b8c3518..c7642aa 100644
--- a/content/common/gpu/gpu_channel_manager.h
+++ b/content/common/gpu/gpu_channel_manager.h
@@ -12,7 +12,6 @@
 #include <vector>
 
 #include "base/containers/scoped_ptr_hash_map.h"
-#include "base/id_map.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
@@ -26,6 +25,11 @@
 #include "ui/gl/gl_surface.h"
 #include "url/gurl.h"
 
+#if defined(OS_MACOSX)
+#include "base/callback.h"
+#include "base/containers/hash_tables.h"
+#endif
+
 namespace base {
 class WaitableEvent;
 }
@@ -58,7 +62,6 @@
 class GpuChannelManagerDelegate;
 class GpuMemoryBufferFactory;
 class GpuWatchdog;
-class ImageTransportHelper;
 struct EstablishChannelParams;
 #if defined(OS_MACOSX)
 struct BufferPresentedParams;
@@ -69,6 +72,10 @@
 // browser process to them based on the corresponding renderer ID.
 class CONTENT_EXPORT GpuChannelManager {
  public:
+#if defined(OS_MACOSX)
+  typedef base::Callback<void(const BufferPresentedParams&)>
+      BufferPresentedCallback;
+#endif
   GpuChannelManager(const gpu::GpuPreferences& gpu_preferences,
                     GpuChannelManagerDelegate* delegate,
                     GpuWatchdog* watchdog,
@@ -100,9 +107,9 @@
   void LoseAllContexts();
 
 #if defined(OS_MACOSX)
-  void AddImageTransportSurface(int32_t routing_id,
-                                ImageTransportHelper* image_transport_helper);
-  void RemoveImageTransportSurface(int32_t routing_id);
+  void AddBufferPresentedCallback(int32_t routing_id,
+                                  const BufferPresentedCallback& callback);
+  void RemoveBufferPresentedCallback(int32_t routing_id);
   void BufferPresented(const BufferPresentedParams& params);
 #endif
 
@@ -176,7 +183,8 @@
 
   GpuChannelManagerDelegate* const delegate_;
 #if defined(OS_MACOSX)
-  IDMap<ImageTransportHelper> image_transport_map_;
+  base::hash_map<int32_t, BufferPresentedCallback>
+      buffer_presented_callback_map_;
 #endif
 
   GpuWatchdog* watchdog_;
diff --git a/content/common/gpu/image_transport_surface.cc b/content/common/gpu/image_transport_surface.cc
index eae07e9d..1606f090a 100644
--- a/content/common/gpu/image_transport_surface.cc
+++ b/content/common/gpu/image_transport_surface.cc
@@ -4,36 +4,11 @@
 
 #include "content/common/gpu/image_transport_surface.h"
 
-#include <stddef.h>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/command_line.h"
-#include "base/trace_event/trace_event.h"
-#include "build/build_config.h"
-#include "content/common/gpu/gpu_channel.h"
 #include "content/common/gpu/gpu_channel_manager.h"
-#include "content/common/gpu/gpu_channel_manager_delegate.h"
-#include "content/common/gpu/gpu_command_buffer_stub.h"
-#include "content/common/gpu/gpu_messages.h"
-#include "gpu/command_buffer/service/sync_point_manager.h"
-#include "ui/gfx/vsync_provider.h"
-#include "ui/gl/gl_context.h"
-#include "ui/gl/gl_implementation.h"
-#include "ui/gl/gl_switches.h"
-
-#if defined(OS_MACOSX)
-#include "content/common/gpu/accelerated_surface_buffers_swapped_params_mac.h"
-#include "ui/accelerated_widget_mac/accelerated_widget_mac.h"
-#endif
 
 namespace content {
 
-ImageTransportSurface::ImageTransportSurface() {}
-
-ImageTransportSurface::~ImageTransportSurface() {}
-
+// static
 scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateSurface(
     GpuChannelManager* manager,
     GpuCommandBufferStub* stub,
@@ -51,245 +26,4 @@
   return surface;
 }
 
-ImageTransportHelper::ImageTransportHelper(ImageTransportSurface* surface,
-                                           GpuChannelManager* manager,
-                                           GpuCommandBufferStub* stub,
-                                           gfx::PluginWindowHandle handle)
-    : surface_(surface),
-      manager_(manager),
-      stub_(stub->AsWeakPtr()),
-      handle_(handle) {
-#if defined(OS_MACOSX)
-  manager_->AddImageTransportSurface(handle_, this);
-#endif
-}
-
-ImageTransportHelper::~ImageTransportHelper() {
-  if (stub_.get()) {
-    stub_->SetLatencyInfoCallback(
-        base::Callback<void(const std::vector<ui::LatencyInfo>&)>());
-  }
-#if defined(OS_MACOSX)
-  manager_->RemoveImageTransportSurface(handle_);
-#endif
-}
-
-bool ImageTransportHelper::Initialize(gfx::GLSurface::Format format) {
-  gpu::gles2::GLES2Decoder* decoder = Decoder();
-
-  if (!decoder)
-    return false;
-
-  stub_->SetLatencyInfoCallback(
-      base::Bind(&ImageTransportHelper::SetLatencyInfo,
-                 base::Unretained(this)));
-
-  return true;
-}
-
-#if defined(OS_MACOSX)
-void ImageTransportHelper::BufferPresented(
-    const BufferPresentedParams& params) {
-  surface_->BufferPresented(params);
-}
-
-void ImageTransportHelper::SendAcceleratedSurfaceBuffersSwapped(
-    AcceleratedSurfaceBuffersSwappedParams params) {
-  // TRACE_EVENT for gpu tests:
-  TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffers",
-                       TRACE_EVENT_SCOPE_THREAD,
-                       "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
-                       "width", params.size.width());
-  // On mac, handle_ is a surface id. See
-  // GpuProcessTransportFactory::CreatePerCompositorData
-  params.surface_id = handle_;
-  manager_->delegate()->SendAcceleratedSurfaceBuffersSwapped(params);
-}
-#endif
-
-bool ImageTransportHelper::MakeCurrent() {
-  gpu::gles2::GLES2Decoder* decoder = Decoder();
-  if (!decoder)
-    return false;
-  return decoder->MakeCurrent();
-}
-
-void ImageTransportHelper::SetSwapInterval(gfx::GLContext* context) {
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kDisableGpuVsync))
-    context->ForceSwapIntervalZero(true);
-  else
-    context->SetSwapInterval(1);
-}
-
-gpu::gles2::GLES2Decoder* ImageTransportHelper::Decoder() {
-  if (!stub_.get())
-    return NULL;
-  return stub_->decoder();
-}
-
-void ImageTransportHelper::SetLatencyInfo(
-    const std::vector<ui::LatencyInfo>& latency_info) {
-  surface_->SetLatencyInfo(latency_info);
-}
-
-PassThroughImageTransportSurface::PassThroughImageTransportSurface(
-    GpuChannelManager* manager,
-    GpuCommandBufferStub* stub,
-    gfx::GLSurface* surface)
-    : GLSurfaceAdapter(surface),
-      did_set_swap_interval_(false),
-      weak_ptr_factory_(this) {
-  helper_.reset(new ImageTransportHelper(this,
-                                         manager,
-                                         stub,
-                                         gfx::kNullPluginWindow));
-}
-
-bool PassThroughImageTransportSurface::Initialize(
-    gfx::GLSurface::Format format) {
-  // The surface is assumed to have already been initialized.
-  return helper_->Initialize(format);
-}
-
-void PassThroughImageTransportSurface::Destroy() {
-  GLSurfaceAdapter::Destroy();
-}
-
-void PassThroughImageTransportSurface::SetLatencyInfo(
-    const std::vector<ui::LatencyInfo>& latency_info) {
-  for (size_t i = 0; i < latency_info.size(); i++)
-    latency_info_.push_back(latency_info[i]);
-}
-
-gfx::SwapResult PassThroughImageTransportSurface::SwapBuffers() {
-  scoped_ptr<std::vector<ui::LatencyInfo>> latency_info = StartSwapBuffers();
-  gfx::SwapResult result = gfx::GLSurfaceAdapter::SwapBuffers();
-  FinishSwapBuffers(std::move(latency_info), result);
-  return result;
-}
-
-void PassThroughImageTransportSurface::SwapBuffersAsync(
-    const GLSurface::SwapCompletionCallback& callback) {
-  scoped_ptr<std::vector<ui::LatencyInfo>> latency_info = StartSwapBuffers();
-
-  // We use WeakPtr here to avoid manual management of life time of an instance
-  // of this class. Callback will not be called once the instance of this class
-  // is destroyed. However, this also means that the callback can be run on
-  // the calling thread only.
-  gfx::GLSurfaceAdapter::SwapBuffersAsync(base::Bind(
-      &PassThroughImageTransportSurface::FinishSwapBuffersAsync,
-      weak_ptr_factory_.GetWeakPtr(), base::Passed(&latency_info), callback));
-}
-
-gfx::SwapResult PassThroughImageTransportSurface::PostSubBuffer(int x,
-                                                                int y,
-                                                                int width,
-                                                                int height) {
-  scoped_ptr<std::vector<ui::LatencyInfo>> latency_info = StartSwapBuffers();
-  gfx::SwapResult result =
-      gfx::GLSurfaceAdapter::PostSubBuffer(x, y, width, height);
-  FinishSwapBuffers(std::move(latency_info), result);
-  return result;
-}
-
-void PassThroughImageTransportSurface::PostSubBufferAsync(
-    int x,
-    int y,
-    int width,
-    int height,
-    const GLSurface::SwapCompletionCallback& callback) {
-  scoped_ptr<std::vector<ui::LatencyInfo>> latency_info = StartSwapBuffers();
-  gfx::GLSurfaceAdapter::PostSubBufferAsync(
-      x, y, width, height,
-      base::Bind(&PassThroughImageTransportSurface::FinishSwapBuffersAsync,
-                 weak_ptr_factory_.GetWeakPtr(), base::Passed(&latency_info),
-                 callback));
-}
-
-gfx::SwapResult PassThroughImageTransportSurface::CommitOverlayPlanes() {
-  scoped_ptr<std::vector<ui::LatencyInfo>> latency_info = StartSwapBuffers();
-  gfx::SwapResult result = gfx::GLSurfaceAdapter::CommitOverlayPlanes();
-  FinishSwapBuffers(std::move(latency_info), result);
-  return result;
-}
-
-void PassThroughImageTransportSurface::CommitOverlayPlanesAsync(
-    const GLSurface::SwapCompletionCallback& callback) {
-  scoped_ptr<std::vector<ui::LatencyInfo>> latency_info = StartSwapBuffers();
-  gfx::GLSurfaceAdapter::CommitOverlayPlanesAsync(base::Bind(
-      &PassThroughImageTransportSurface::FinishSwapBuffersAsync,
-      weak_ptr_factory_.GetWeakPtr(), base::Passed(&latency_info), callback));
-}
-
-bool PassThroughImageTransportSurface::OnMakeCurrent(gfx::GLContext* context) {
-  if (!did_set_swap_interval_) {
-    ImageTransportHelper::SetSwapInterval(context);
-    did_set_swap_interval_ = true;
-  }
-  return true;
-}
-
-#if defined(OS_MACOSX)
-void PassThroughImageTransportSurface::BufferPresented(
-    const BufferPresentedParams& /* params */) {
-  NOTREACHED();
-}
-#endif
-
-gfx::Size PassThroughImageTransportSurface::GetSize() {
-  return GLSurfaceAdapter::GetSize();
-}
-
-PassThroughImageTransportSurface::~PassThroughImageTransportSurface() {}
-
-void PassThroughImageTransportSurface::SendVSyncUpdateIfAvailable() {
-  gfx::VSyncProvider* vsync_provider = GetVSyncProvider();
-  if (vsync_provider) {
-    vsync_provider->GetVSyncParameters(
-        base::Bind(&GpuCommandBufferStub::SendUpdateVSyncParameters,
-                   helper_->stub()->AsWeakPtr()));
-  }
-}
-
-scoped_ptr<std::vector<ui::LatencyInfo>>
-PassThroughImageTransportSurface::StartSwapBuffers() {
-  // GetVsyncValues before SwapBuffers to work around Mali driver bug:
-  // crbug.com/223558.
-  SendVSyncUpdateIfAvailable();
-
-  base::TimeTicks swap_time = base::TimeTicks::Now();
-  for (auto& latency : latency_info_) {
-    latency.AddLatencyNumberWithTimestamp(
-        ui::INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT, 0, 0, swap_time, 1);
-  }
-
-  scoped_ptr<std::vector<ui::LatencyInfo>> latency_info(
-      new std::vector<ui::LatencyInfo>());
-  latency_info->swap(latency_info_);
-
-  return latency_info;
-}
-
-void PassThroughImageTransportSurface::FinishSwapBuffers(
-    scoped_ptr<std::vector<ui::LatencyInfo>> latency_info,
-    gfx::SwapResult result) {
-  base::TimeTicks swap_ack_time = base::TimeTicks::Now();
-  for (auto& latency : *latency_info) {
-    latency.AddLatencyNumberWithTimestamp(
-        ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, 0,
-        swap_ack_time, 1);
-  }
-
-  helper_->stub()->SendSwapBuffersCompleted(*latency_info, result);
-}
-
-void PassThroughImageTransportSurface::FinishSwapBuffersAsync(
-    scoped_ptr<std::vector<ui::LatencyInfo>> latency_info,
-    GLSurface::SwapCompletionCallback callback,
-    gfx::SwapResult result) {
-  FinishSwapBuffers(std::move(latency_info), result);
-  callback.Run(result);
-}
-
 }  // namespace content
diff --git a/content/common/gpu/image_transport_surface.h b/content/common/gpu/image_transport_surface.h
index 130d5cb..7df0193 100644
--- a/content/common/gpu/image_transport_surface.h
+++ b/content/common/gpu/image_transport_surface.h
@@ -7,44 +7,15 @@
 
 #include <stdint.h>
 
-#include <vector>
-
-#include "base/callback.h"
 #include "base/compiler_specific.h"
 #include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/weak_ptr.h"
 #include "build/build_config.h"
 #include "content/common/content_export.h"
-#include "ipc/ipc_listener.h"
-#include "ipc/ipc_message.h"
-#include "ui/events/latency_info.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/geometry/size.h"
-#include "ui/gfx/native_widget_types.h"
-#include "ui/gfx/swap_result.h"
 #include "ui/gl/gl_surface.h"
 
-
-namespace gfx {
-class GLSurface;
-}
-
-namespace gpu {
-class PreemptionFlag;
-namespace gles2 {
-class GLES2Decoder;
-}
-}
-
 namespace content {
 class GpuChannelManager;
 class GpuCommandBufferStub;
-#if defined(OS_MACOSX)
-struct BufferPresentedParams;
-struct AcceleratedSurfaceBuffersSwappedParams;
-#endif
 
 // The GPU process is agnostic as to how it displays results. On some platforms
 // it renders directly to window. On others it renders offscreen and transports
@@ -61,14 +32,6 @@
 
 class ImageTransportSurface {
  public:
-  ImageTransportSurface();
-
-#if defined(OS_MACOSX)
-  virtual void BufferPresented(const BufferPresentedParams& params) = 0;
-#endif
-  virtual void SetLatencyInfo(
-      const std::vector<ui::LatencyInfo>& latency_info) = 0;
-
   // Creates a surface with the given attributes.
   static scoped_refptr<gfx::GLSurface> CreateSurface(
       GpuChannelManager* manager,
@@ -80,11 +43,6 @@
   CONTENT_EXPORT static void SetAllowOSMesaForTesting(bool allow);
 #endif
 
-  virtual gfx::Size GetSize() = 0;
-
- protected:
-  virtual ~ImageTransportSurface();
-
  private:
   // Creates the appropriate native surface depending on the GL implementation.
   // This will be implemented separately by each platform.
@@ -102,114 +60,6 @@
   DISALLOW_COPY_AND_ASSIGN(ImageTransportSurface);
 };
 
-class ImageTransportHelper
-    : public base::SupportsWeakPtr<ImageTransportHelper> {
- public:
-  // Takes weak pointers to objects that outlive the helper.
-  ImageTransportHelper(ImageTransportSurface* surface,
-                       GpuChannelManager* manager,
-                       GpuCommandBufferStub* stub,
-                       gfx::PluginWindowHandle handle);
-  ~ImageTransportHelper();
-
-  bool Initialize(gfx::GLSurface::Format format);
-
-  // Helper send functions. Caller fills in the surface specific params
-  // like size and surface id. The helper fills in the rest.
-#if defined(OS_MACOSX)
-  void BufferPresented(const BufferPresentedParams& params);
-  void SendAcceleratedSurfaceBuffersSwapped(
-      AcceleratedSurfaceBuffersSwappedParams params);
-#endif
-
-  // Make the surface's context current.
-  bool MakeCurrent();
-
-  // Set the default swap interval on the surface.
-  static void SetSwapInterval(gfx::GLContext* context);
-
-  GpuChannelManager* manager() const { return manager_; }
-  GpuCommandBufferStub* stub() const { return stub_.get(); }
-
- private:
-  gpu::gles2::GLES2Decoder* Decoder();
-
-  // Backbuffer resize callback.
-  void Resize(gfx::Size size, float scale_factor);
-
-  void SetLatencyInfo(const std::vector<ui::LatencyInfo>& latency_info);
-
-  // Weak pointers that point to objects that outlive this helper.
-  ImageTransportSurface* surface_;
-  GpuChannelManager* manager_;
-
-  base::WeakPtr<GpuCommandBufferStub> stub_;
-  int32_t route_id_;
-  gfx::PluginWindowHandle handle_;
-
-  DISALLOW_COPY_AND_ASSIGN(ImageTransportHelper);
-};
-
-// An implementation of ImageTransportSurface that implements GLSurface through
-// GLSurfaceAdapter, thereby forwarding GLSurface methods through to it.
-class PassThroughImageTransportSurface
-    : public gfx::GLSurfaceAdapter,
-      public ImageTransportSurface {
- public:
-  PassThroughImageTransportSurface(GpuChannelManager* manager,
-                                   GpuCommandBufferStub* stub,
-                                   gfx::GLSurface* surface);
-
-  // GLSurface implementation.
-  bool Initialize(gfx::GLSurface::Format format) override;
-  void Destroy() override;
-  gfx::SwapResult SwapBuffers() override;
-  void SwapBuffersAsync(const SwapCompletionCallback& callback) override;
-  gfx::SwapResult PostSubBuffer(int x, int y, int width, int height) override;
-  void PostSubBufferAsync(int x,
-                          int y,
-                          int width,
-                          int height,
-                          const SwapCompletionCallback& callback) override;
-  gfx::SwapResult CommitOverlayPlanes() override;
-  void CommitOverlayPlanesAsync(
-      const SwapCompletionCallback& callback) override;
-  bool OnMakeCurrent(gfx::GLContext* context) override;
-
-  // ImageTransportSurface implementation.
-#if defined(OS_MACOSX)
-  void BufferPresented(const BufferPresentedParams& params) override;
-#endif
-  gfx::Size GetSize() override;
-  void SetLatencyInfo(
-      const std::vector<ui::LatencyInfo>& latency_info) override;
-
- protected:
-  ~PassThroughImageTransportSurface() override;
-
-  // If updated vsync parameters can be determined, send this information to
-  // the browser.
-  virtual void SendVSyncUpdateIfAvailable();
-
-  scoped_ptr<std::vector<ui::LatencyInfo>> StartSwapBuffers();
-  void FinishSwapBuffers(scoped_ptr<std::vector<ui::LatencyInfo>> latency_info,
-                         gfx::SwapResult result);
-  void FinishSwapBuffersAsync(
-      scoped_ptr<std::vector<ui::LatencyInfo>> latency_info,
-      GLSurface::SwapCompletionCallback callback,
-      gfx::SwapResult result);
-
-  ImageTransportHelper* GetHelper() { return helper_.get(); }
-
- private:
-  scoped_ptr<ImageTransportHelper> helper_;
-  bool did_set_swap_interval_;
-  std::vector<ui::LatencyInfo> latency_info_;
-  base::WeakPtrFactory<PassThroughImageTransportSurface> weak_ptr_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(PassThroughImageTransportSurface);
-};
-
 }  // namespace content
 
 #endif  // CONTENT_COMMON_GPU_IMAGE_TRANSPORT_SURFACE_H_
diff --git a/content/common/gpu/image_transport_surface_android.cc b/content/common/gpu/image_transport_surface_android.cc
index 84fb25d..d24ee5b 100644
--- a/content/common/gpu/image_transport_surface_android.cc
+++ b/content/common/gpu/image_transport_surface_android.cc
@@ -10,6 +10,7 @@
 #include "content/common/gpu/gpu_channel_manager.h"
 #include "content/common/gpu/gpu_command_buffer_stub.h"
 #include "content/common/gpu/gpu_surface_lookup.h"
+#include "content/common/gpu/pass_through_image_transport_surface.h"
 #include "content/public/common/content_switches.h"
 #include "ui/gl/gl_surface_egl.h"
 
diff --git a/content/common/gpu/image_transport_surface_linux.cc b/content/common/gpu/image_transport_surface_linux.cc
index 57ac5e5..e9412a7b 100644
--- a/content/common/gpu/image_transport_surface_linux.cc
+++ b/content/common/gpu/image_transport_surface_linux.cc
@@ -4,6 +4,8 @@
 
 #include "content/common/gpu/image_transport_surface.h"
 
+#include "content/common/gpu/pass_through_image_transport_surface.h"
+
 namespace content {
 
 // static
diff --git a/content/common/gpu/image_transport_surface_mac.mm b/content/common/gpu/image_transport_surface_mac.mm
index 330d134..25131cc 100644
--- a/content/common/gpu/image_transport_surface_mac.mm
+++ b/content/common/gpu/image_transport_surface_mac.mm
@@ -5,10 +5,8 @@
 #include "content/common/gpu/image_transport_surface.h"
 
 #include "base/macros.h"
-#include "content/common/gpu/gpu_messages.h"
+#include "content/common/gpu/pass_through_image_transport_surface.h"
 #include "ui/gfx/native_widget_types.h"
-#include "ui/gl/gl_context.h"
-#include "ui/gl/gl_implementation.h"
 #include "ui/gl/gl_surface_osmesa.h"
 
 namespace content {
diff --git a/content/common/gpu/image_transport_surface_overlay_mac.h b/content/common/gpu/image_transport_surface_overlay_mac.h
index 76d4eea..4254749b 100644
--- a/content/common/gpu/image_transport_surface_overlay_mac.h
+++ b/content/common/gpu/image_transport_surface_overlay_mac.h
@@ -12,6 +12,7 @@
 #include "base/timer/timer.h"
 #include "content/common/gpu/gpu_command_buffer_stub.h"
 #include "content/common/gpu/image_transport_surface.h"
+#include "ui/events/latency_info.h"
 #include "ui/gl/gl_surface.h"
 #include "ui/gl/gpu_switching_observer.h"
 
@@ -22,9 +23,10 @@
 
 class CALayerTree;
 class CALayerPartialDamageTree;
+struct AcceleratedSurfaceBuffersSwappedParams;
+struct BufferPresentedParams;
 
 class ImageTransportSurfaceOverlayMac : public gfx::GLSurface,
-                                        public ImageTransportSurface,
                                         public ui::GpuSwitchingObserver {
  public:
   ImageTransportSurfaceOverlayMac(GpuChannelManager* manager,
@@ -62,10 +64,6 @@
                        int sorting_context_id) override;
   bool IsSurfaceless() const override;
 
-  // ImageTransportSurface implementation
-  void BufferPresented(const BufferPresentedParams& params) override;
-  void SetLatencyInfo(const std::vector<ui::LatencyInfo>&) override;
-
   // ui::GpuSwitchingObserver implementation.
   void OnGpuSwitched() override;
 
@@ -75,6 +73,10 @@
 
   ~ImageTransportSurfaceOverlayMac() override;
 
+  void SetLatencyInfo(const std::vector<ui::LatencyInfo>& latency_info);
+  void BufferPresented(const BufferPresentedParams& params);
+  void SendAcceleratedSurfaceBuffersSwapped(
+      AcceleratedSurfaceBuffersSwappedParams params);
   gfx::SwapResult SwapBuffersInternal(const gfx::Rect& pixel_damage_rect);
 
   // Returns true if the front of |pending_swaps_| has completed, or has timed
@@ -102,14 +104,17 @@
   base::TimeTicks GetNextVSyncTimeAfter(
       const base::TimeTicks& from, double interval_fraction);
 
-  scoped_ptr<ImageTransportHelper> helper_;
+  GpuChannelManager* manager_;
+  base::WeakPtr<GpuCommandBufferStub> stub_;
+  gfx::PluginWindowHandle handle_;
+  std::vector<ui::LatencyInfo> latency_info_;
+
   bool use_remote_layer_api_;
   base::scoped_nsobject<CAContext> ca_context_;
   base::scoped_nsobject<CALayer> ca_root_layer_;
 
   gfx::Size pixel_size_;
   float scale_factor_;
-  std::vector<ui::LatencyInfo> latency_info_;
 
   // The renderer ID that all contexts made current to this surface should be
   // targeting.
diff --git a/content/common/gpu/image_transport_surface_overlay_mac.mm b/content/common/gpu/image_transport_surface_overlay_mac.mm
index 05f6512..2a95abc 100644
--- a/content/common/gpu/image_transport_surface_overlay_mac.mm
+++ b/content/common/gpu/image_transport_surface_overlay_mac.mm
@@ -20,12 +20,16 @@
 typedef void* GLeglImageOES;
 #endif
 
+#include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/mac/scoped_cftyperef.h"
 #include "base/trace_event/trace_event.h"
 #include "content/common/gpu/accelerated_surface_buffers_swapped_params_mac.h"
 #include "content/common/gpu/buffer_presented_params_mac.h"
 #include "content/common/gpu/ca_layer_partial_damage_tree_mac.h"
 #include "content/common/gpu/ca_layer_tree_mac.h"
+#include "content/common/gpu/gpu_channel_manager.h"
+#include "content/common/gpu/gpu_channel_manager_delegate.h"
 #include "ui/accelerated_widget_mac/io_surface_context.h"
 #include "ui/base/cocoa/animation_utils.h"
 #include "ui/base/cocoa/remote_layer_api.h"
@@ -115,26 +119,40 @@
     GpuChannelManager* manager,
     GpuCommandBufferStub* stub,
     gfx::PluginWindowHandle handle)
-    : use_remote_layer_api_(ui::RemoteLayerAPISupported()),
+    : manager_(manager),
+      stub_(stub->AsWeakPtr()),
+      handle_(handle),
+      use_remote_layer_api_(ui::RemoteLayerAPISupported()),
       scale_factor_(1),
       gl_renderer_id_(0),
       vsync_parameters_valid_(false),
       display_pending_swap_timer_(true, false),
       weak_factory_(this) {
-  helper_.reset(new ImageTransportHelper(this, manager, stub, handle));
+  manager_->AddBufferPresentedCallback(
+      handle_, base::Bind(&ImageTransportSurfaceOverlayMac::BufferPresented,
+                          base::Unretained(this)));
   ui::GpuSwitchingManager::GetInstance()->AddObserver(this);
 }
 
 ImageTransportSurfaceOverlayMac::~ImageTransportSurfaceOverlayMac() {
   ui::GpuSwitchingManager::GetInstance()->RemoveObserver(this);
+  if (stub_.get()) {
+    stub_->SetLatencyInfoCallback(
+        base::Callback<void(const std::vector<ui::LatencyInfo>&)>());
+  }
   Destroy();
+  manager_->RemoveBufferPresentedCallback(handle_);
 }
 
 bool ImageTransportSurfaceOverlayMac::Initialize(
     gfx::GLSurface::Format format) {
-  if (!helper_->Initialize(format))
+  if (!stub_.get() || !stub_->decoder())
     return false;
 
+  stub_->SetLatencyInfoCallback(
+      base::Bind(&ImageTransportSurfaceOverlayMac::SetLatencyInfo,
+                 base::Unretained(this)));
+
   // Create the CAContext to send this to the GPU process, and the layer for
   // the context.
   if (use_remote_layer_api_) {
@@ -160,6 +178,38 @@
   return false;
 }
 
+void ImageTransportSurfaceOverlayMac::SetLatencyInfo(
+    const std::vector<ui::LatencyInfo>& latency_info) {
+  latency_info_.insert(latency_info_.end(), latency_info.begin(),
+                       latency_info.end());
+}
+
+void ImageTransportSurfaceOverlayMac::BufferPresented(
+    const BufferPresentedParams& params) {
+  vsync_timebase_ = params.vsync_timebase;
+  vsync_interval_ = params.vsync_interval;
+  vsync_parameters_valid_ = (vsync_interval_ != base::TimeDelta());
+
+  // Compute |vsync_timebase_| to be the first vsync after time zero.
+  if (vsync_parameters_valid_) {
+    vsync_timebase_ -=
+        vsync_interval_ *
+        ((vsync_timebase_ - base::TimeTicks()) / vsync_interval_);
+  }
+}
+
+void ImageTransportSurfaceOverlayMac::SendAcceleratedSurfaceBuffersSwapped(
+    AcceleratedSurfaceBuffersSwappedParams params) {
+  // TRACE_EVENT for gpu tests:
+  TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffers", TRACE_EVENT_SCOPE_THREAD,
+                       "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
+                       "width", params.size.width());
+  // On mac, handle_ is a surface id. See
+  // GpuProcessTransportFactory::CreatePerCompositorData
+  params.surface_id = handle_;
+  manager_->delegate()->SendAcceleratedSurfaceBuffersSwapped(params);
+}
+
 gfx::SwapResult ImageTransportSurfaceOverlayMac::SwapBuffersInternal(
     const gfx::Rect& pixel_damage_rect) {
   TRACE_EVENT0("gpu", "ImageTransportSurfaceOverlayMac::SwapBuffersInternal");
@@ -320,7 +370,7 @@
   params.size = swap->pixel_size;
   params.scale_factor = swap->scale_factor;
   params.latency_info.swap(swap->latency_info);
-  helper_->SendAcceleratedSurfaceBuffersSwapped(params);
+  SendAcceleratedSurfaceBuffersSwapped(params);
 
   // Remove this from the queue, and reset any callback timers.
   pending_swaps_.pop_front();
@@ -455,20 +505,6 @@
   return true;
 }
 
-void ImageTransportSurfaceOverlayMac::BufferPresented(
-    const BufferPresentedParams& params) {
-  vsync_timebase_ = params.vsync_timebase;
-  vsync_interval_ = params.vsync_interval;
-  vsync_parameters_valid_ = (vsync_interval_ != base::TimeDelta());
-
-  // Compute |vsync_timebase_| to be the first vsync after time zero.
-  if (vsync_parameters_valid_) {
-    vsync_timebase_ -=
-        vsync_interval_ *
-        ((vsync_timebase_ - base::TimeTicks()) / vsync_interval_);
-  }
-}
-
 bool ImageTransportSurfaceOverlayMac::Resize(const gfx::Size& pixel_size,
                                              float scale_factor,
                                              bool has_alpha) {
@@ -479,12 +515,6 @@
   return true;
 }
 
-void ImageTransportSurfaceOverlayMac::SetLatencyInfo(
-    const std::vector<ui::LatencyInfo>& latency_info) {
-  latency_info_.insert(
-      latency_info_.end(), latency_info.begin(), latency_info.end());
-}
-
 void ImageTransportSurfaceOverlayMac::OnGpuSwitched() {
   // Create a new context, and use the GL renderer ID that the new context gets.
   scoped_refptr<ui::IOSurfaceContext> context_on_new_gpu =
diff --git a/content/common/gpu/image_transport_surface_win.cc b/content/common/gpu/image_transport_surface_win.cc
index 589d9c8..3bdbe25 100644
--- a/content/common/gpu/image_transport_surface_win.cc
+++ b/content/common/gpu/image_transport_surface_win.cc
@@ -12,6 +12,7 @@
 #include "base/win/windows_version.h"
 #include "content/common/gpu/child_window_surface_win.h"
 #include "content/common/gpu/gpu_messages.h"
+#include "content/common/gpu/pass_through_image_transport_surface.h"
 #include "content/public/common/content_switches.h"
 #include "ui/gfx/native_widget_types.h"
 #include "ui/gl/gl_bindings.h"
diff --git a/content/common/gpu/pass_through_image_transport_surface.cc b/content/common/gpu/pass_through_image_transport_surface.cc
new file mode 100644
index 0000000..3d0d1c8a
--- /dev/null
+++ b/content/common/gpu/pass_through_image_transport_surface.cc
@@ -0,0 +1,175 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/gpu/pass_through_image_transport_surface.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/command_line.h"
+#include "build/build_config.h"
+#include "content/common/gpu/gpu_command_buffer_stub.h"
+#include "ui/gfx/vsync_provider.h"
+#include "ui/gl/gl_context.h"
+#include "ui/gl/gl_switches.h"
+
+namespace content {
+
+PassThroughImageTransportSurface::PassThroughImageTransportSurface(
+    GpuChannelManager* /* manager */,
+    GpuCommandBufferStub* stub,
+    gfx::GLSurface* surface)
+    : GLSurfaceAdapter(surface),
+      stub_(stub->AsWeakPtr()),
+      did_set_swap_interval_(false),
+      weak_ptr_factory_(this) {}
+
+bool PassThroughImageTransportSurface::Initialize(
+    gfx::GLSurface::Format format) {
+  // The surface is assumed to have already been initialized.
+  if (!stub_.get() || !stub_->decoder())
+    return false;
+  stub_->SetLatencyInfoCallback(
+      base::Bind(&PassThroughImageTransportSurface::SetLatencyInfo,
+                 base::Unretained(this)));
+  return true;
+}
+
+void PassThroughImageTransportSurface::Destroy() {
+  GLSurfaceAdapter::Destroy();
+}
+
+gfx::SwapResult PassThroughImageTransportSurface::SwapBuffers() {
+  scoped_ptr<std::vector<ui::LatencyInfo>> latency_info = StartSwapBuffers();
+  gfx::SwapResult result = gfx::GLSurfaceAdapter::SwapBuffers();
+  FinishSwapBuffers(std::move(latency_info), result);
+  return result;
+}
+
+void PassThroughImageTransportSurface::SwapBuffersAsync(
+    const GLSurface::SwapCompletionCallback& callback) {
+  scoped_ptr<std::vector<ui::LatencyInfo>> latency_info = StartSwapBuffers();
+
+  // We use WeakPtr here to avoid manual management of life time of an instance
+  // of this class. Callback will not be called once the instance of this class
+  // is destroyed. However, this also means that the callback can be run on
+  // the calling thread only.
+  gfx::GLSurfaceAdapter::SwapBuffersAsync(base::Bind(
+      &PassThroughImageTransportSurface::FinishSwapBuffersAsync,
+      weak_ptr_factory_.GetWeakPtr(), base::Passed(&latency_info), callback));
+}
+
+gfx::SwapResult PassThroughImageTransportSurface::PostSubBuffer(int x,
+                                                                int y,
+                                                                int width,
+                                                                int height) {
+  scoped_ptr<std::vector<ui::LatencyInfo>> latency_info = StartSwapBuffers();
+  gfx::SwapResult result =
+      gfx::GLSurfaceAdapter::PostSubBuffer(x, y, width, height);
+  FinishSwapBuffers(std::move(latency_info), result);
+  return result;
+}
+
+void PassThroughImageTransportSurface::PostSubBufferAsync(
+    int x,
+    int y,
+    int width,
+    int height,
+    const GLSurface::SwapCompletionCallback& callback) {
+  scoped_ptr<std::vector<ui::LatencyInfo>> latency_info = StartSwapBuffers();
+  gfx::GLSurfaceAdapter::PostSubBufferAsync(
+      x, y, width, height,
+      base::Bind(&PassThroughImageTransportSurface::FinishSwapBuffersAsync,
+                 weak_ptr_factory_.GetWeakPtr(), base::Passed(&latency_info),
+                 callback));
+}
+
+gfx::SwapResult PassThroughImageTransportSurface::CommitOverlayPlanes() {
+  scoped_ptr<std::vector<ui::LatencyInfo>> latency_info = StartSwapBuffers();
+  gfx::SwapResult result = gfx::GLSurfaceAdapter::CommitOverlayPlanes();
+  FinishSwapBuffers(std::move(latency_info), result);
+  return result;
+}
+
+void PassThroughImageTransportSurface::CommitOverlayPlanesAsync(
+    const GLSurface::SwapCompletionCallback& callback) {
+  scoped_ptr<std::vector<ui::LatencyInfo>> latency_info = StartSwapBuffers();
+  gfx::GLSurfaceAdapter::CommitOverlayPlanesAsync(base::Bind(
+      &PassThroughImageTransportSurface::FinishSwapBuffersAsync,
+      weak_ptr_factory_.GetWeakPtr(), base::Passed(&latency_info), callback));
+}
+
+bool PassThroughImageTransportSurface::OnMakeCurrent(gfx::GLContext* context) {
+  if (!did_set_swap_interval_) {
+    if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+            switches::kDisableGpuVsync))
+      context->ForceSwapIntervalZero(true);
+    else
+      context->SetSwapInterval(1);
+    did_set_swap_interval_ = true;
+  }
+  return true;
+}
+
+PassThroughImageTransportSurface::~PassThroughImageTransportSurface() {
+  if (stub_.get()) {
+    stub_->SetLatencyInfoCallback(
+        base::Callback<void(const std::vector<ui::LatencyInfo>&)>());
+  }
+}
+
+void PassThroughImageTransportSurface::SetLatencyInfo(
+    const std::vector<ui::LatencyInfo>& latency_info) {
+  latency_info_.insert(latency_info_.end(), latency_info.begin(),
+                       latency_info.end());
+}
+
+void PassThroughImageTransportSurface::SendVSyncUpdateIfAvailable() {
+  gfx::VSyncProvider* vsync_provider = GetVSyncProvider();
+  if (vsync_provider) {
+    vsync_provider->GetVSyncParameters(base::Bind(
+        &GpuCommandBufferStub::SendUpdateVSyncParameters, stub_->AsWeakPtr()));
+  }
+}
+
+scoped_ptr<std::vector<ui::LatencyInfo>>
+PassThroughImageTransportSurface::StartSwapBuffers() {
+  // GetVsyncValues before SwapBuffers to work around Mali driver bug:
+  // crbug.com/223558.
+  SendVSyncUpdateIfAvailable();
+
+  base::TimeTicks swap_time = base::TimeTicks::Now();
+  for (auto& latency : latency_info_) {
+    latency.AddLatencyNumberWithTimestamp(
+        ui::INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT, 0, 0, swap_time, 1);
+  }
+
+  scoped_ptr<std::vector<ui::LatencyInfo>> latency_info(
+      new std::vector<ui::LatencyInfo>());
+  latency_info->swap(latency_info_);
+
+  return latency_info;
+}
+
+void PassThroughImageTransportSurface::FinishSwapBuffers(
+    scoped_ptr<std::vector<ui::LatencyInfo>> latency_info,
+    gfx::SwapResult result) {
+  base::TimeTicks swap_ack_time = base::TimeTicks::Now();
+  for (auto& latency : *latency_info) {
+    latency.AddLatencyNumberWithTimestamp(
+        ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, 0,
+        swap_ack_time, 1);
+  }
+
+  stub_->SendSwapBuffersCompleted(*latency_info, result);
+}
+
+void PassThroughImageTransportSurface::FinishSwapBuffersAsync(
+    scoped_ptr<std::vector<ui::LatencyInfo>> latency_info,
+    GLSurface::SwapCompletionCallback callback,
+    gfx::SwapResult result) {
+  FinishSwapBuffers(std::move(latency_info), result);
+  callback.Run(result);
+}
+
+}  // namespace content
diff --git a/content/common/gpu/pass_through_image_transport_surface.h b/content/common/gpu/pass_through_image_transport_surface.h
new file mode 100644
index 0000000..0b5a1e5
--- /dev/null
+++ b/content/common/gpu/pass_through_image_transport_surface.h
@@ -0,0 +1,73 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_COMMON_GPU_PASS_THROUGH_IMAGE_TRANSPORT_SURFACE_H_
+#define CONTENT_COMMON_GPU_PASS_THROUGH_IMAGE_TRANSPORT_SURFACE_H_
+
+#include <stdint.h>
+
+#include <vector>
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "content/common/gpu/image_transport_surface.h"
+#include "ui/events/latency_info.h"
+#include "ui/gl/gl_surface.h"
+
+namespace content {
+class GpuChannelManager;
+class GpuCommandBufferStub;
+
+// An implementation of ImageTransportSurface that implements GLSurface through
+// GLSurfaceAdapter, thereby forwarding GLSurface methods through to it.
+class PassThroughImageTransportSurface : public gfx::GLSurfaceAdapter {
+ public:
+  PassThroughImageTransportSurface(GpuChannelManager* manager,
+                                   GpuCommandBufferStub* stub,
+                                   gfx::GLSurface* surface);
+
+  // GLSurface implementation.
+  bool Initialize(gfx::GLSurface::Format format) override;
+  void Destroy() override;
+  gfx::SwapResult SwapBuffers() override;
+  void SwapBuffersAsync(const SwapCompletionCallback& callback) override;
+  gfx::SwapResult PostSubBuffer(int x, int y, int width, int height) override;
+  void PostSubBufferAsync(int x,
+                          int y,
+                          int width,
+                          int height,
+                          const SwapCompletionCallback& callback) override;
+  gfx::SwapResult CommitOverlayPlanes() override;
+  void CommitOverlayPlanesAsync(
+      const SwapCompletionCallback& callback) override;
+  bool OnMakeCurrent(gfx::GLContext* context) override;
+
+ private:
+  ~PassThroughImageTransportSurface() override;
+
+  // If updated vsync parameters can be determined, send this information to
+  // the browser.
+  void SendVSyncUpdateIfAvailable();
+
+  void SetLatencyInfo(const std::vector<ui::LatencyInfo>& latency_info);
+  scoped_ptr<std::vector<ui::LatencyInfo>> StartSwapBuffers();
+  void FinishSwapBuffers(scoped_ptr<std::vector<ui::LatencyInfo>> latency_info,
+                         gfx::SwapResult result);
+  void FinishSwapBuffersAsync(
+      scoped_ptr<std::vector<ui::LatencyInfo>> latency_info,
+      GLSurface::SwapCompletionCallback callback,
+      gfx::SwapResult result);
+
+  base::WeakPtr<GpuCommandBufferStub> stub_;
+  bool did_set_swap_interval_;
+  std::vector<ui::LatencyInfo> latency_info_;
+  base::WeakPtrFactory<PassThroughImageTransportSurface> weak_ptr_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(PassThroughImageTransportSurface);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_COMMON_GPU_PASS_THROUGH_IMAGE_TRANSPORT_SURFACE_H_
diff --git a/content/content_app.gypi b/content/content_app.gypi
index 7f64025..cca9124 100644
--- a/content/content_app.gypi
+++ b/content/content_app.gypi
@@ -10,7 +10,6 @@
     '../base/base.gyp:base',
     '../base/base.gyp:base_i18n',
     '../crypto/crypto.gyp:crypto',
-    '../mojo/mojo_base.gyp:mojo_environment_chromium',
     '../mojo/mojo_edk.gyp:mojo_system_impl',
     '../ui/base/ui_base.gyp:ui_base',
     '../ui/gfx/gfx.gyp:gfx',
diff --git a/content/content_browser.gypi b/content/content_browser.gypi
index 01e33ec..14d5db3 100644
--- a/content/content_browser.gypi
+++ b/content/content_browser.gypi
@@ -1097,7 +1097,6 @@
       'browser/mojo/mojo_shell_client_host.h',
       'browser/mojo/mojo_shell_context.cc',
       'browser/mojo/mojo_shell_context.h',
-      'browser/mojo/renderer_capability_filter.cc',
       'browser/mojo/service_registrar_android.cc',
       'browser/mojo/service_registrar_android.h',
       'browser/mojo/service_registry_android.cc',
diff --git a/content/content_child.gypi b/content/content_child.gypi
index 2d296ef..9fb7380 100644
--- a/content/content_child.gypi
+++ b/content/content_child.gypi
@@ -10,7 +10,6 @@
     '../components/tracing.gyp:tracing',
     '../components/webcrypto/webcrypto.gyp:webcrypto',
     '../ipc/ipc.gyp:ipc',
-    '../mojo/mojo_base.gyp:mojo_environment_chromium',
     '../mojo/mojo_base.gyp:mojo_common_lib',
     '../mojo/mojo_public.gyp:mojo_message_pump_lib',
     '../skia/skia.gyp:skia',
diff --git a/content/content_common.gypi b/content/content_common.gypi
index 07dcea9..215ca90 100644
--- a/content/content_common.gypi
+++ b/content/content_common.gypi
@@ -24,7 +24,6 @@
     '../media/media.gyp:shared_memory_support',
     '../media/midi/midi.gyp:midi',
     '../mojo/mojo_base.gyp:mojo_application_bindings',
-    '../mojo/mojo_base.gyp:mojo_environment_chromium',
     '../mojo/mojo_edk.gyp:mojo_system_impl',
     '../mojo/mojo_public.gyp:mojo_cpp_bindings',
     '../mojo/mojo_shell.gyp:mojo_runner_connection_lib',
@@ -434,6 +433,8 @@
       'common/gpu/media/media_service.h',
       'common/gpu/media/shared_memory_region.cc',
       'common/gpu/media/shared_memory_region.h',
+      'common/gpu/pass_through_image_transport_surface.cc',
+      'common/gpu/pass_through_image_transport_surface.h',
       'common/gpu/stream_texture_android.cc',
       'common/gpu/stream_texture_android.h',
       'common/host_discardable_shared_memory_manager.cc',
diff --git a/content/content_common_mojo_bindings.gyp b/content/content_common_mojo_bindings.gyp
index a174591e..6e5aade 100644
--- a/content/content_common_mojo_bindings.gyp
+++ b/content/content_common_mojo_bindings.gyp
@@ -37,7 +37,6 @@
       'dependencies': [
         '../components/leveldb/leveldb.gyp:leveldb_bindings_mojom',
         '../mojo/mojo_base.gyp:mojo_application_bindings',
-        '../mojo/mojo_base.gyp:mojo_environment_chromium',
         '../mojo/mojo_public.gyp:mojo_cpp_bindings',
         '../skia/skia.gyp:skia_mojo',
         '../ui/mojo/geometry/mojo_bindings.gyp:mojo_geometry_bindings',
diff --git a/content/content_renderer.gypi b/content/content_renderer.gypi
index 6a8486fd..adf3d1d 100644
--- a/content/content_renderer.gypi
+++ b/content/content_renderer.gypi
@@ -24,7 +24,6 @@
     '../media/blink/media_blink.gyp:media_blink',
     '../media/media.gyp:media',
     '../mojo/mojo_base.gyp:mojo_application_bindings',
-    '../mojo/mojo_base.gyp:mojo_environment_chromium',
     '../mojo/mojo_base.gyp:mojo_geometry_lib',
     '../mojo/mojo_base.gyp:mojo_url_type_converters',
     '../mojo/mojo_edk.gyp:mojo_js_lib',
diff --git a/content/content_tests.gypi b/content/content_tests.gypi
index 4716c1c..fcc0c38 100644
--- a/content/content_tests.gypi
+++ b/content/content_tests.gypi
@@ -842,7 +842,6 @@
       'type': 'static_library',
       'dependencies': [
         '../mojo/mojo_base.gyp:mojo_application_base',
-        '../mojo/mojo_base.gyp:mojo_environment_chromium',
         '../mojo/mojo_edk.gyp:mojo_system_impl',
         '../mojo/mojo_public.gyp:mojo_cpp_bindings',
         '../net/net.gyp:net_test_support',
@@ -934,7 +933,6 @@
             '../media/media.gyp:media',
             '../media/midi/midi.gyp:midi',
             '../mojo/mojo_base.gyp:mojo_application_base',
-            '../mojo/mojo_base.gyp:mojo_environment_chromium',
             '../mojo/mojo_edk.gyp:mojo_common_test_support',
             '../mojo/mojo_public.gyp:mojo_cpp_bindings',
             '../ppapi/ppapi_internal.gyp:ppapi_host',
@@ -1163,7 +1161,6 @@
             '../ipc/ipc.gyp:test_support_ipc',
             '../media/media.gyp:media_test_support',
             '../media/media.gyp:shared_memory_support',
-            '../mojo/mojo_base.gyp:mojo_environment_chromium',
             '../mojo/mojo_edk.gyp:mojo_common_test_support',
             '../mojo/mojo_public.gyp:mojo_cpp_bindings',
             '../net/net.gyp:net_extras',
@@ -1508,7 +1505,6 @@
             '../media/media.gyp:media_test_support',
             '../media/media.gyp:shared_memory_support',
             '../mojo/mojo_base.gyp:mojo_application_base',
-            '../mojo/mojo_base.gyp:mojo_environment_chromium',
             '../mojo/mojo_base.gyp:mojo_test_support',
             '../mojo/mojo_edk.gyp:mojo_common_test_support',
             '../mojo/mojo_edk.gyp:mojo_system_impl',
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn
index 3e64933..bd41605 100644
--- a/content/renderer/BUILD.gn
+++ b/content/renderer/BUILD.gn
@@ -57,7 +57,6 @@
     "//mojo/common",
     "//mojo/converters/geometry",
     "//mojo/edk/js",
-    "//mojo/environment:chromium",
     "//mojo/public/cpp/bindings",
     "//mojo/public/js",
     "//mojo/shell/public/cpp",
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index 4014147b..d831ca9 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -2696,7 +2696,7 @@
     has_scrolled_focused_editable_node_into_rect_ = false;
 }
 
-void RenderViewImpl::DidInitiatePaint() {
+void RenderViewImpl::RenderWidgetDidCommitAndDrawCompositorFrame() {
 #if defined(ENABLE_PLUGINS)
   // Notify all instances that we painted.  The same caveats apply as for
   // ViewFlushedPaint regarding instances closing themselves, so we take
@@ -2709,7 +2709,7 @@
 #endif
 }
 
-void RenderViewImpl::DidFlushPaint() {
+void RenderViewImpl::RenderWidgetDidFlushPaint() {
   // If the RenderWidget is closing down then early-exit, otherwise we'll crash.
   // See crbug.com/112921.
   if (!webview())
diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h
index 1e305e44..4af994a 100644
--- a/content/renderer/render_view_impl.h
+++ b/content/renderer/render_view_impl.h
@@ -461,8 +461,6 @@
   void CloseForFrame() override;
   void Close() override;
   void OnResize(const ResizeParams& params) override;
-  void DidInitiatePaint() override;
-  void DidFlushPaint() override;
   gfx::Vector2d GetScrollOffset() override;
   void OnSetFocus(bool enable) override;
   void OnWasHidden() override;
@@ -584,6 +582,8 @@
       const blink::WebGestureEvent& event) override;
   bool RenderWidgetWillHandleMouseEvent(
       const blink::WebMouseEvent& event) override;
+  void RenderWidgetDidCommitAndDrawCompositorFrame() override;
+  void RenderWidgetDidFlushPaint() override;
 
   // Old WebFrameClient implementations ----------------------------------------
 
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc
index 8220160..75052c4 100644
--- a/content/renderer/render_widget.cc
+++ b/content/renderer/render_widget.cc
@@ -1701,6 +1701,16 @@
 void RenderWidget::OnOrientationChange() {
 }
 
+void RenderWidget::DidInitiatePaint() {
+  if (owner_delegate_)
+    owner_delegate_->RenderWidgetDidCommitAndDrawCompositorFrame();
+}
+
+void RenderWidget::DidFlushPaint() {
+  if (owner_delegate_)
+    owner_delegate_->RenderWidgetDidFlushPaint();
+}
+
 gfx::Vector2d RenderWidget::GetScrollOffset() {
   // Bare RenderWidgets don't support scroll offset.
   return gfx::Vector2d();
diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h
index d189feb..a239554 100644
--- a/content/renderer/render_widget.h
+++ b/content/renderer/render_widget.h
@@ -500,8 +500,8 @@
   // the ACK that the screen has been updated. For a given paint operation,
   // these overrides will always be called in the order DidInitiatePaint,
   // DidFlushPaint.
-  virtual void DidInitiatePaint() {}
-  virtual void DidFlushPaint() {}
+  virtual void DidInitiatePaint();
+  virtual void DidFlushPaint();
 
   virtual GURL GetURLForGraphicsContext3D();
 
diff --git a/content/renderer/render_widget_owner_delegate.h b/content/renderer/render_widget_owner_delegate.h
index 309324ae..4c76ddd 100644
--- a/content/renderer/render_widget_owner_delegate.h
+++ b/content/renderer/render_widget_owner_delegate.h
@@ -40,6 +40,15 @@
   virtual bool RenderWidgetWillHandleMouseEvent(
       const blink::WebMouseEvent& event) = 0;
 
+  // Painting notifications. RenderWidgetDidCommitAndDrawCompositorFrame happens
+  // when that has completed, and subsequent rendering won't affect the painted
+  // content. DidFlushPaint happens once we've received the ACK that the screen
+  // has been updated. For a given paint operation, these overrides will always
+  // be called in the order RenderWidgetDidCommitAndDrawCompositorFrame,
+  // RenderWidgetDidFlushPaint.
+  virtual void RenderWidgetDidCommitAndDrawCompositorFrame() = 0;
+  virtual void RenderWidgetDidFlushPaint() = 0;
+
  protected:
   virtual ~RenderWidgetOwnerDelegate() {}
 };
diff --git a/content/shell/browser/layout_test/blink_test_controller.cc b/content/shell/browser/layout_test/blink_test_controller.cc
index 3793d4c..554159f 100644
--- a/content/shell/browser/layout_test/blink_test_controller.cc
+++ b/content/shell/browser/layout_test/blink_test_controller.cc
@@ -374,7 +374,7 @@
                          gfx::Size());
 }
 
-void BlinkTestController::TestFinishedInSecondaryWindow() {
+void BlinkTestController::TestFinishedInSecondaryRenderer() {
   RenderViewHost* render_view_host =
       main_window_->web_contents()->GetRenderViewHost();
   render_view_host->Send(
diff --git a/content/shell/browser/layout_test/blink_test_controller.h b/content/shell/browser/layout_test/blink_test_controller.h
index d170e6f..6ff85f7 100644
--- a/content/shell/browser/layout_test/blink_test_controller.h
+++ b/content/shell/browser/layout_test/blink_test_controller.h
@@ -140,7 +140,7 @@
   void RendererUnresponsive();
   void OverrideWebkitPrefs(WebPreferences* prefs);
   void OpenURL(const GURL& url);
-  void TestFinishedInSecondaryWindow();
+  void TestFinishedInSecondaryRenderer();
   bool IsMainWindow(WebContents* web_contents) const;
   scoped_ptr<BluetoothChooser> RunBluetoothChooser(
       RenderFrameHost* frame,
diff --git a/content/shell/browser/layout_test/notify_done_forwarder.cc b/content/shell/browser/layout_test/notify_done_forwarder.cc
index 2a77f94..b9213938 100644
--- a/content/shell/browser/layout_test/notify_done_forwarder.cc
+++ b/content/shell/browser/layout_test/notify_done_forwarder.cc
@@ -19,15 +19,15 @@
 bool NotifyDoneForwarder::OnMessageReceived(const IPC::Message& message) {
   bool handled = true;
   IPC_BEGIN_MESSAGE_MAP(NotifyDoneForwarder, message)
-    IPC_MESSAGE_HANDLER(ShellViewHostMsg_TestFinishedInSecondaryWindow,
-                        OnTestFinishedInSecondaryWindow)
+    IPC_MESSAGE_HANDLER(ShellViewHostMsg_TestFinishedInSecondaryRenderer,
+                        OnTestFinishedInSecondaryRenderer)
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
   return handled;
 }
 
-void NotifyDoneForwarder::OnTestFinishedInSecondaryWindow() {
-  BlinkTestController::Get()->TestFinishedInSecondaryWindow();
+void NotifyDoneForwarder::OnTestFinishedInSecondaryRenderer() {
+  BlinkTestController::Get()->TestFinishedInSecondaryRenderer();
 }
 
 }  // namespace content
diff --git a/content/shell/browser/layout_test/notify_done_forwarder.h b/content/shell/browser/layout_test/notify_done_forwarder.h
index fd1b0c1..c512c247 100644
--- a/content/shell/browser/layout_test/notify_done_forwarder.h
+++ b/content/shell/browser/layout_test/notify_done_forwarder.h
@@ -24,7 +24,7 @@
 
   explicit NotifyDoneForwarder(WebContents* web_contents);
 
-  void OnTestFinishedInSecondaryWindow();
+  void OnTestFinishedInSecondaryRenderer();
 
   DISALLOW_COPY_AND_ASSIGN(NotifyDoneForwarder);
 };
diff --git a/content/shell/common/shell_messages.h b/content/shell/common/shell_messages.h
index 7a0b1f93..41fad062 100644
--- a/content/shell/common/shell_messages.h
+++ b/content/shell/common/shell_messages.h
@@ -48,8 +48,8 @@
 IPC_MESSAGE_ROUTED1(ShellViewMsg_SetTestConfiguration,
                     content::ShellTestConfiguration)
 
-// Tells the main window that a secondary window in a different process invoked
-// notifyDone().
+// Tells the main window that a secondary renderer in a different process thinks
+// the test is finished.
 IPC_MESSAGE_ROUTED0(ShellViewMsg_NotifyDone)
 
 // Pushes a snapshot of the current session history from the browser process.
@@ -100,7 +100,7 @@
 
 IPC_MESSAGE_ROUTED0(ShellViewHostMsg_ResetDone)
 
-IPC_MESSAGE_ROUTED0(ShellViewHostMsg_TestFinishedInSecondaryWindow)
+IPC_MESSAGE_ROUTED0(ShellViewHostMsg_TestFinishedInSecondaryRenderer)
 
 // WebTestDelegate related.
 IPC_MESSAGE_ROUTED1(ShellViewHostMsg_OverridePreferences,
diff --git a/content/shell/renderer/layout_test/blink_test_runner.cc b/content/shell/renderer/layout_test/blink_test_runner.cc
index 633757842..73f4fccb 100644
--- a/content/shell/renderer/layout_test/blink_test_runner.cc
+++ b/content/shell/renderer/layout_test/blink_test_runner.cc
@@ -611,8 +611,8 @@
 }
 
 void BlinkTestRunner::TestFinished() {
-  if (!is_main_window_) {
-    Send(new ShellViewHostMsg_TestFinishedInSecondaryWindow(routing_id()));
+  if (!is_main_window_ || !render_view()->GetMainRenderFrame()) {
+    Send(new ShellViewHostMsg_TestFinishedInSecondaryRenderer(routing_id()));
     return;
   }
   test_runner::WebTestInterfaces* interfaces =
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index 55e264e..90582330 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -101,7 +101,6 @@
       "//ipc/mojo",
       "//media",
       "//mojo/edk/test:test_support",
-      "//mojo/environment:chromium",
       "//mojo/shell/public/cpp:cpp_for_chromium",
       "//storage/browser",
       "//storage/common",
@@ -436,7 +435,6 @@
     "//media/base:test_support",
     "//mojo/edk/system",
     "//mojo/edk/test:test_support",
-    "//mojo/environment:chromium",
     "//mojo/public/cpp/bindings",
     "//mojo/public/js",
     "//mojo/shell/public/cpp:cpp_for_chromium",
@@ -610,7 +608,6 @@
     "//device/battery:mojo_bindings",
     "//device/bluetooth",
     "//mojo/edk/test:test_support",
-    "//mojo/environment:chromium",
     "//mojo/public/cpp/bindings",
     "//net:extras",
     "//net:test_support",
diff --git a/device/BUILD.gn b/device/BUILD.gn
index 4b52e52..a65caaf 100644
--- a/device/BUILD.gn
+++ b/device/BUILD.gn
@@ -58,7 +58,6 @@
     "//device/nfc",
     "//mojo/common",
     "//mojo/edk/system",
-    "//mojo/environment:chromium",
     "//mojo/public/cpp/bindings",
     "//net",
     "//testing/gmock",
diff --git a/device/battery/BUILD.gn b/device/battery/BUILD.gn
index 5bf49ce..9876bc6 100644
--- a/device/battery/BUILD.gn
+++ b/device/battery/BUILD.gn
@@ -32,7 +32,6 @@
       "//base",
       "//base/third_party/dynamic_annotations",
       "//mojo/edk/system",
-      "//mojo/environment:chromium",
       "//mojo/public/cpp/bindings",
     ]
 
diff --git a/device/battery/battery.gyp b/device/battery/battery.gyp
index 32f7adf6..6028f33 100644
--- a/device/battery/battery.gyp
+++ b/device/battery/battery.gyp
@@ -89,7 +89,6 @@
           'dependencies': [
             '../../base/base.gyp:base',
             '../../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
-            '../../mojo/mojo_base.gyp:mojo_environment_chromium',
             '../../mojo/mojo_edk.gyp:mojo_system_impl',
             '../../mojo/mojo_public.gyp:mojo_cpp_bindings',
             'device_battery_mojo_bindings',
diff --git a/device/device_tests.gyp b/device/device_tests.gyp
index c4ad2d8..7a22fb32 100644
--- a/device/device_tests.gyp
+++ b/device/device_tests.gyp
@@ -13,7 +13,6 @@
       'dependencies': [
         '../base/base.gyp:test_support_base',
         '../mojo/mojo_base.gyp:mojo_url_type_converters',
-        '../mojo/mojo_base.gyp:mojo_environment_chromium',
         '../mojo/mojo_edk.gyp:mojo_system_impl',
         '../mojo/mojo_public.gyp:mojo_cpp_bindings',
         '../testing/gmock.gyp:gmock',
diff --git a/device/serial/data_sink_unittest.cc b/device/serial/data_sink_unittest.cc
index a5872f5..54067dc 100644
--- a/device/serial/data_sink_unittest.cc
+++ b/device/serial/data_sink_unittest.cc
@@ -15,7 +15,6 @@
 #include "device/serial/data_sink_receiver.h"
 #include "device/serial/data_stream.mojom.h"
 #include "mojo/public/cpp/bindings/interface_ptr.h"
-#include "mojo/public/cpp/environment/async_waiter.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace device {
diff --git a/device/serial/data_source_unittest.cc b/device/serial/data_source_unittest.cc
index 5f30a6c..7dacbed 100644
--- a/device/serial/data_source_unittest.cc
+++ b/device/serial/data_source_unittest.cc
@@ -15,7 +15,6 @@
 #include "device/serial/data_source_sender.h"
 #include "device/serial/data_stream.mojom.h"
 #include "mojo/public/cpp/bindings/interface_ptr.h"
-#include "mojo/public/cpp/environment/async_waiter.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace device {
diff --git a/device/vibration/BUILD.gn b/device/vibration/BUILD.gn
index d783940..443e2dd 100644
--- a/device/vibration/BUILD.gn
+++ b/device/vibration/BUILD.gn
@@ -21,7 +21,6 @@
     "//base",
     "//base/third_party/dynamic_annotations",
     "//mojo/edk/system",
-    "//mojo/environment:chromium",
     "//mojo/public/cpp/bindings",
   ]
 
diff --git a/device/vibration/vibration.gyp b/device/vibration/vibration.gyp
index acef5d5..d31072d 100644
--- a/device/vibration/vibration.gyp
+++ b/device/vibration/vibration.gyp
@@ -25,7 +25,6 @@
       'dependencies': [
         '../../base/base.gyp:base',
         '../../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
-        '../../mojo/mojo_base.gyp:mojo_environment_chromium',
         '../../mojo/mojo_edk.gyp:mojo_system_impl',
         '../../mojo/mojo_public.gyp:mojo_cpp_bindings',
         'device_vibration_mojo_bindings',
diff --git a/extensions/BUILD.gn b/extensions/BUILD.gn
index 5741f96..9e7e2fe 100644
--- a/extensions/BUILD.gn
+++ b/extensions/BUILD.gn
@@ -184,7 +184,6 @@
     "//extensions/utility",
     "//mojo/edk/js",
     "//mojo/edk/system",
-    "//mojo/environment:chromium",
     "//mojo/public/cpp/bindings",
     "//mojo/shell/public/interfaces",
     "//testing/gmock",
@@ -244,7 +243,6 @@
     "//device/usb:mocks",
     "//mojo/edk/js",
     "//mojo/edk/system",
-    "//mojo/environment:chromium",
     "//mojo/public/cpp/bindings",
     "//testing/gmock",
     "//testing/gtest",
diff --git a/extensions/common/permissions/settings_override_permission.cc b/extensions/common/permissions/settings_override_permission.cc
index 43765d20..69318d829 100644
--- a/extensions/common/permissions/settings_override_permission.cc
+++ b/extensions/common/permissions/settings_override_permission.cc
@@ -48,14 +48,7 @@
     const base::Value* value,
     std::string* /*error*/,
     std::vector<std::string>* unhandled_permissions) {
-  // Ugly hack: |value| being null should be an error. But before M46 beta, we
-  // didn't store the parameter for settings override permissions in prefs.
-  // See crbug.com/533086.
-  // TODO(treib,devlin): Remove this for M48, when hopefully all users will have
-  // updated prefs.
-  // This should read:
-  // return value && value->GetAsString(&setting_value_);
-  return !value || value->GetAsString(&setting_value_);
+  return value && value->GetAsString(&setting_value_);
 }
 
 scoped_ptr<base::Value> SettingsOverrideAPIPermission::ToValue() const {
diff --git a/extensions/extensions_tests.gyp b/extensions/extensions_tests.gyp
index 87ef374..11a27ca 100644
--- a/extensions/extensions_tests.gyp
+++ b/extensions/extensions_tests.gyp
@@ -27,7 +27,6 @@
         '../device/serial/serial.gyp:device_serial',
         '../device/serial/serial.gyp:device_serial_test_util',
         '../mojo/mojo_base.gyp:mojo_application_bindings',
-        '../mojo/mojo_base.gyp:mojo_environment_chromium',
         '../mojo/mojo_edk.gyp:mojo_js_lib',
         '../mojo/mojo_edk.gyp:mojo_system_impl',
         '../mojo/mojo_public.gyp:mojo_cpp_bindings',
diff --git a/extensions/shell/BUILD.gn b/extensions/shell/BUILD.gn
index c2f57e9..fca3ec3e 100644
--- a/extensions/shell/BUILD.gn
+++ b/extensions/shell/BUILD.gn
@@ -55,7 +55,6 @@
     "//extensions/shell/common/api:api_registration",
     "//extensions/utility",
     "//mojo/edk/system",
-    "//mojo/environment:chromium",
     "//skia",
     "//third_party/WebKit/public:blink",
     "//ui/base",
diff --git a/extensions/shell/app_shell.gyp b/extensions/shell/app_shell.gyp
index 9d085db..fb8f054 100644
--- a/extensions/shell/app_shell.gyp
+++ b/extensions/shell/app_shell.gyp
@@ -46,7 +46,6 @@
         '<(DEPTH)/extensions/extensions_resources.gyp:extensions_resources',
         '<(DEPTH)/extensions/shell/browser/api/api_registration.gyp:shell_api_registration',
         '<(DEPTH)/extensions/shell/common/api/api.gyp:shell_api',
-        '<(DEPTH)/mojo/mojo_base.gyp:mojo_environment_chromium',
         '<(DEPTH)/mojo/mojo_edk.gyp:mojo_system_impl',
         '<(DEPTH)/skia/skia.gyp:skia',
         '<(DEPTH)/third_party/WebKit/public/blink.gyp:blink',
diff --git a/ios/chrome/browser/browser_state/chrome_browser_state_impl_io_data.h b/ios/chrome/browser/browser_state/chrome_browser_state_impl_io_data.h
index 77f75bc..8da2ba4 100644
--- a/ios/chrome/browser/browser_state/chrome_browser_state_impl_io_data.h
+++ b/ios/chrome/browser/browser_state/chrome_browser_state_impl_io_data.h
@@ -116,9 +116,9 @@
       scoped_ptr<IOSChromeNetworkDelegate> chrome_network_delegate,
       ProfileParams* profile_params,
       ProtocolHandlerMap* protocol_handlers) const override;
-  net::URLRequestContext* InitializeAppRequestContext(
+  AppRequestContext* InitializeAppRequestContext(
       net::URLRequestContext* main_context) const override;
-  net::URLRequestContext* AcquireIsolatedAppRequestContext(
+  AppRequestContext* AcquireIsolatedAppRequestContext(
       net::URLRequestContext* main_context) const override;
 
   // Deletes all network related data since |time|. It deletes transport
diff --git a/ios/chrome/browser/browser_state/chrome_browser_state_impl_io_data.mm b/ios/chrome/browser/browser_state/chrome_browser_state_impl_io_data.mm
index 91aedf83..a530e22 100644
--- a/ios/chrome/browser/browser_state/chrome_browser_state_impl_io_data.mm
+++ b/ios/chrome/browser/browser_state/chrome_browser_state_impl_io_data.mm
@@ -410,7 +410,7 @@
   lazy_params_.reset();
 }
 
-net::URLRequestContext*
+ChromeBrowserStateIOData::AppRequestContext*
 ChromeBrowserStateImplIOData::InitializeAppRequestContext(
     net::URLRequestContext* main_context) const {
   // Copy most state from the main context.
@@ -447,11 +447,11 @@
   return context;
 }
 
-net::URLRequestContext*
+ChromeBrowserStateIOData::AppRequestContext*
 ChromeBrowserStateImplIOData::AcquireIsolatedAppRequestContext(
     net::URLRequestContext* main_context) const {
   // We create per-app contexts on demand, unlike the others above.
-  net::URLRequestContext* app_request_context =
+  AppRequestContext* app_request_context =
       InitializeAppRequestContext(main_context);
   DCHECK(app_request_context);
   return app_request_context;
diff --git a/ios/chrome/browser/browser_state/chrome_browser_state_io_data.cc b/ios/chrome/browser/browser_state/chrome_browser_state_io_data.cc
index f29cd00..d5819c1 100644
--- a/ios/chrome/browser/browser_state/chrome_browser_state_io_data.cc
+++ b/ios/chrome/browser/browser_state/chrome_browser_state_io_data.cc
@@ -257,7 +257,7 @@
     net::URLRequestContext* main_context,
     const base::FilePath& partition_path) const {
   DCHECK(initialized_);
-  net::URLRequestContext* context = nullptr;
+  AppRequestContext* context = nullptr;
   if (ContainsKey(app_request_context_map_, partition_path)) {
     context = app_request_context_map_[partition_path];
   } else {
@@ -268,6 +268,14 @@
   return context;
 }
 
+void ChromeBrowserStateIOData::SetCookieStoreForPartitionPath(
+    scoped_ptr<net::CookieStore> cookie_store,
+    const base::FilePath& partition_path) {
+  DCHECK(ContainsKey(app_request_context_map_, partition_path));
+  app_request_context_map_[partition_path]->SetCookieStore(
+      std::move(cookie_store));
+}
+
 content_settings::CookieSettings* ChromeBrowserStateIOData::GetCookieSettings()
     const {
   DCHECK(initialized_);
diff --git a/ios/chrome/browser/browser_state/chrome_browser_state_io_data.h b/ios/chrome/browser/browser_state/chrome_browser_state_io_data.h
index 038f288..7e806d07 100644
--- a/ios/chrome/browser/browser_state/chrome_browser_state_io_data.h
+++ b/ios/chrome/browser/browser_state/chrome_browser_state_io_data.h
@@ -91,6 +91,11 @@
       net::URLRequestContext* main_context,
       const base::FilePath& partition_path) const;
 
+  // Sets the cookie store associated with a partition path.
+  // The path must exist. If there is already a cookie store, it is deleted.
+  void SetCookieStoreForPartitionPath(scoped_ptr<net::CookieStore> cookie_store,
+                                      const base::FilePath& partition_path);
+
   // These are useful when the Chrome layer is called from the content layer
   // with a content::ResourceContext, and they want access to Chrome data for
   // that browser state.
@@ -136,9 +141,9 @@
         scoped_ptr<net::HttpTransactionFactory> http_factory);
     void SetJobFactory(scoped_ptr<net::URLRequestJobFactory> job_factory);
 
-   private:
     ~AppRequestContext() override;
 
+   private:
     scoped_ptr<net::CookieStore> cookie_store_;
     scoped_ptr<net::HttpTransactionFactory> http_factory_;
     scoped_ptr<net::URLRequestJobFactory> job_factory_;
@@ -220,8 +225,7 @@
       scoped_ptr<net::HttpCache::BackendFactory> backend) const;
 
  private:
-  typedef std::map<base::FilePath, net::URLRequestContext*>
-      URLRequestContextMap;
+  typedef std::map<base::FilePath, AppRequestContext*> URLRequestContextMap;
 
   // --------------------------------------------
   // Virtual interface for subtypes to implement:
@@ -236,12 +240,12 @@
 
   // Does an on-demand initialization of a RequestContext for the given
   // isolated app.
-  virtual net::URLRequestContext* InitializeAppRequestContext(
+  virtual AppRequestContext* InitializeAppRequestContext(
       net::URLRequestContext* main_context) const = 0;
 
   // These functions are used to transfer ownership of the lazily initialized
   // context from ChromeBrowserStateIOData to the URLRequestContextGetter.
-  virtual net::URLRequestContext* AcquireIsolatedAppRequestContext(
+  virtual AppRequestContext* AcquireIsolatedAppRequestContext(
       net::URLRequestContext* main_context) const = 0;
 
   // The order *DOES* matter for the majority of these member variables, so
diff --git a/ios/chrome/browser/browser_state/off_the_record_chrome_browser_state_io_data.h b/ios/chrome/browser/browser_state/off_the_record_chrome_browser_state_io_data.h
index 65995f0..4848d55 100644
--- a/ios/chrome/browser/browser_state/off_the_record_chrome_browser_state_io_data.h
+++ b/ios/chrome/browser/browser_state/off_the_record_chrome_browser_state_io_data.h
@@ -95,9 +95,9 @@
       scoped_ptr<IOSChromeNetworkDelegate> chrome_network_delegate,
       ProfileParams* profile_params,
       ProtocolHandlerMap* protocol_handlers) const override;
-  net::URLRequestContext* InitializeAppRequestContext(
+  AppRequestContext* InitializeAppRequestContext(
       net::URLRequestContext* main_context) const override;
-  net::URLRequestContext* AcquireIsolatedAppRequestContext(
+  AppRequestContext* AcquireIsolatedAppRequestContext(
       net::URLRequestContext* main_context) const override;
 
   mutable scoped_ptr<IOSChromeNetworkDelegate> network_delegate_;
diff --git a/ios/chrome/browser/browser_state/off_the_record_chrome_browser_state_io_data.mm b/ios/chrome/browser/browser_state/off_the_record_chrome_browser_state_io_data.mm
index 26b3d2b..8156acd 100644
--- a/ios/chrome/browser/browser_state/off_the_record_chrome_browser_state_io_data.mm
+++ b/ios/chrome/browser/browser_state/off_the_record_chrome_browser_state_io_data.mm
@@ -226,14 +226,14 @@
   main_context->set_sdch_manager(sdch_manager_.get());
 }
 
-net::URLRequestContext*
+ChromeBrowserStateIOData::AppRequestContext*
 OffTheRecordChromeBrowserStateIOData::InitializeAppRequestContext(
     net::URLRequestContext* main_context) const {
   NOTREACHED();
   return nullptr;
 }
 
-net::URLRequestContext*
+ChromeBrowserStateIOData::AppRequestContext*
 OffTheRecordChromeBrowserStateIOData::AcquireIsolatedAppRequestContext(
     net::URLRequestContext* main_context) const {
   NOTREACHED();
diff --git a/ios/chrome/browser/experimental_flags.h b/ios/chrome/browser/experimental_flags.h
index ee80fcc7..a9a2285 100644
--- a/ios/chrome/browser/experimental_flags.h
+++ b/ios/chrome/browser/experimental_flags.h
@@ -37,6 +37,11 @@
 // Whether the reading list is enabled.
 bool IsReadingListEnabled();
 
+// Whether the file sent by the share extension sould be deleted after being
+// processed. If true, files will be reprocessed everytime the application is
+// put in foreground.
+bool IsReadingListKeepItemsEnabled();
+
 }  // namespace experimental_flags
 
 #endif  // IOS_CHROME_BROWSER_EXPERIMENTAL_FLAGS_H_
diff --git a/ios/chrome/browser/experimental_flags.mm b/ios/chrome/browser/experimental_flags.mm
index 52a2801..8f65c5e 100644
--- a/ios/chrome/browser/experimental_flags.mm
+++ b/ios/chrome/browser/experimental_flags.mm
@@ -27,6 +27,7 @@
 NSString* const kHeuristicsForPasswordGeneration =
     @"HeuristicsForPasswordGeneration";
 NSString* const kEnableReadingList = @"EnableReadingList";
+NSString* const kEnableReadingListKeepItems = @"EnableReadingListKeepItems";
 }  // namespace
 
 namespace experimental_flags {
@@ -106,4 +107,9 @@
   return [[NSUserDefaults standardUserDefaults] boolForKey:kEnableReadingList];
 }
 
+bool IsReadingListKeepItemsEnabled() {
+  return [[NSUserDefaults standardUserDefaults]
+      boolForKey:kEnableReadingListKeepItems];
+}
+
 }  // namespace experimental_flags
diff --git a/ios/chrome/browser/reading_list/reading_list_model.h b/ios/chrome/browser/reading_list/reading_list_model.h
index dceb64d..d731909 100644
--- a/ios/chrome/browser/reading_list/reading_list_model.h
+++ b/ios/chrome/browser/reading_list/reading_list_model.h
@@ -25,10 +25,8 @@
 // (Usually the main thread). The observers callbacks are also sent on the main
 // thread.
 class ReadingListModel {
- protected:
-  class ScopedReadingListBatchUpdate;
-
  public:
+  class ScopedReadingListBatchUpdate;
   // Returns true if the model finished loading. Until this returns true the
   // reading list is not ready for use.
   virtual bool loaded() const = 0;
@@ -78,16 +76,6 @@
   void AddObserver(ReadingListModelObserver* observer);
   void RemoveObserver(ReadingListModelObserver* observer);
 
- protected:
-  ReadingListModel();
-  virtual ~ReadingListModel();
-  // The observers.
-  base::ObserverList<ReadingListModelObserver> observers_;
-
-  // Tells model that batch updates have completed. Called from
-  // ReadingListBatchUpdateToken dtor.
-  void EndBatchUpdates();
-
   // Helper class that is used to scope batch updates.
   class ScopedReadingListBatchUpdate {
    public:
@@ -102,6 +90,17 @@
     DISALLOW_COPY_AND_ASSIGN(ScopedReadingListBatchUpdate);
   };
 
+ protected:
+  ReadingListModel();
+  virtual ~ReadingListModel();
+
+  // The observers.
+  base::ObserverList<ReadingListModelObserver> observers_;
+
+  // Tells model that batch updates have completed. Called from
+  // ReadingListBatchUpdateToken dtor.
+  void EndBatchUpdates();
+
  private:
   unsigned int current_batch_updates_count_;
 
diff --git a/ios/chrome/browser/share_extension/share_extension_item_receiver.h b/ios/chrome/browser/share_extension/share_extension_item_receiver.h
new file mode 100644
index 0000000..748f57f
--- /dev/null
+++ b/ios/chrome/browser/share_extension/share_extension_item_receiver.h
@@ -0,0 +1,30 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_UI_SHARE_EXTENSION_SHARE_EXTENSION_ITEM_RECEIVER_H_
+#define IOS_CHROME_BROWSER_UI_SHARE_EXTENSION_SHARE_EXTENSION_ITEM_RECEIVER_H_
+
+#import <Foundation/Foundation.h>
+
+class ReadingListModel;
+
+// This class observes the Application group folder
+// |app_group::ShareExtensionItemsFolder()| and process the files it contains
+// when a new file is created or when application is put in foreground.
+@interface ShareExtensionItemReceiver : NSObject
+
++ (instancetype)sharedInstance;
+
+// Sets the reading list model to use. |shutdown| must be called before another
+// |model| is set.
+// The receiver will start observe the share extension folder and send items to
+// |model|.
+- (void)setReadingListModel:(ReadingListModel*)model;
+
+// Stops observers and pending operations.
+- (void)shutdown;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_SHARE_EXTENSION_SHARE_EXTENSION_ITEM_RECEIVER_H_
diff --git a/ios/chrome/browser/share_extension/share_extension_item_receiver.mm b/ios/chrome/browser/share_extension/share_extension_item_receiver.mm
new file mode 100644
index 0000000..563f8925
--- /dev/null
+++ b/ios/chrome/browser/share_extension/share_extension_item_receiver.mm
@@ -0,0 +1,323 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/share_extension/share_extension_item_receiver.h"
+
+#import <UIKit/UIKit.h>
+
+#include "base/ios/block_types.h"
+#include "base/mac/bind_objc_block.h"
+#include "base/mac/foundation_util.h"
+#include "base/mac/scoped_nsobject.h"
+#include "base/metrics/histogram.h"
+#include "base/metrics/user_metrics_action.h"
+#include "base/strings/sys_string_conversions.h"
+#include "ios/chrome/browser/experimental_flags.h"
+#include "ios/chrome/browser/reading_list/reading_list_model.h"
+#include "ios/chrome/browser/reading_list/reading_list_model_observer.h"
+#include "ios/chrome/common/app_group/app_group_constants.h"
+#include "ios/web/public/web_thread.h"
+#import "net/base/mac/url_conversions.h"
+#include "url/gurl.h"
+
+namespace {
+// Enum used to send metrics on item reception.
+// If you change this enum, update histograms.xml.
+enum ShareExtensionItemReceived {
+  INVALID_ENTRY = 0,
+  CANCELLED_ENTRY,
+  READINGLIST_ENTRY,
+  SHARE_EXTENSION_ITEM_RECEIVED_COUNT
+};
+
+void LogHistogramReceivedItem(ShareExtensionItemReceived type) {
+  UMA_HISTOGRAM_ENUMERATION("IOS.ShareExtension.ReceivedEntry", type,
+                            SHARE_EXTENSION_ITEM_RECEIVED_COUNT);
+}
+
+}  // namespace
+
+@interface ShareExtensionItemReceiver ()<NSFilePresenter> {
+  BOOL _isObservingFolder;
+  BOOL _folderCreated;
+  ReadingListModel* _readingListModel;  // Not owned.
+}
+
+// Checks if the reading list folder is already created and if not, create it.
+- (void)createReadingListFolder;
+
+// Processes the data sent by the share extension. Data should be a NSDictionary
+// serialized by +|NSKeyedArchiver archivedDataWithRootObject:|.
+// |completion| is called if |data| has been fully processed.
+- (BOOL)receivedData:(NSData*)data withCompletion:(ProceduralBlock)completion;
+
+// Reads the file pointed by |url| and calls |receivedData:| on the content.
+// If the file is processed, delete it.
+// Must be called on the FILE thread.
+// |completion| is only called if the file handling is completed without error.
+- (void)handleFileAtURL:(NSURL*)url withCompletion:(ProceduralBlock)completion;
+
+// Deletes the file pointed by |url| then call |completion|.
+- (void)deleteFileAtURL:(NSURL*)url withCompletion:(ProceduralBlock)completion;
+
+// Called on UIApplicationDidBecomeActiveNotification notification. Processes
+// files that are already in the folder and starts observing the
+// app_group::ShareExtensionItemsFolder() folder for new files.
+- (void)applicationDidBecomeActive;
+
+// Called on UIApplicationWillResignActiveNotification. Stops observing the
+// app_group::ShareExtensionItemsFolder() folder for new files.
+- (void)applicationWillResignActive;
+
+// Called whenever a file is modified in app_group::ShareExtensionItemsFolder().
+- (void)presentedSubitemDidChangeAtURL:(NSURL*)url;
+
+@end
+
+@implementation ShareExtensionItemReceiver
+
++ (ShareExtensionItemReceiver*)sharedInstance {
+  DCHECK_CURRENTLY_ON(web::WebThread::UI);
+  static ShareExtensionItemReceiver* instance =
+      [[ShareExtensionItemReceiver alloc] init];
+  return instance;
+}
+
+- (void)setReadingListModel:(ReadingListModel*)model {
+  DCHECK_CURRENTLY_ON(web::WebThread::UI);
+  DCHECK(!_readingListModel);
+  _readingListModel = model;
+
+  web::WebThread::PostTask(web::WebThread::FILE, FROM_HERE,
+                           base::BindBlock(^() {
+                             [self createReadingListFolder];
+                           }));
+  [[NSNotificationCenter defaultCenter]
+      addObserver:self
+         selector:@selector(applicationDidBecomeActive)
+             name:UIApplicationDidBecomeActiveNotification
+           object:nil];
+  [[NSNotificationCenter defaultCenter]
+      addObserver:self
+         selector:@selector(applicationWillResignActive)
+             name:UIApplicationWillResignActiveNotification
+           object:nil];
+}
+
+- (void)shutdown {
+  DCHECK_CURRENTLY_ON(web::WebThread::UI);
+  [[NSNotificationCenter defaultCenter] removeObserver:self];
+  if (_isObservingFolder) {
+    [NSFileCoordinator removeFilePresenter:self];
+  }
+  _readingListModel = nil;
+}
+
+- (void)dealloc {
+  NOTREACHED();
+  [super dealloc];
+}
+
+- (void)createReadingListFolder {
+  DCHECK_CURRENTLY_ON(web::WebThread::FILE);
+  if (![[NSFileManager defaultManager]
+          fileExistsAtPath:[[self presentedItemURL] path]]) {
+    [[NSFileManager defaultManager]
+              createDirectoryAtPath:[[self presentedItemURL] path]
+        withIntermediateDirectories:NO
+                         attributes:nil
+                              error:nil];
+  }
+  web::WebThread::PostTask(
+      web::WebThread::UI, FROM_HERE, base::BindBlock(^() {
+        if ([[UIApplication sharedApplication] applicationState] ==
+            UIApplicationStateActive) {
+          _folderCreated = YES;
+          [self applicationDidBecomeActive];
+        }
+      }));
+}
+
+- (BOOL)receivedData:(NSData*)data withCompletion:(ProceduralBlock)completion {
+  id entryID = [NSKeyedUnarchiver unarchiveObjectWithData:data];
+  NSDictionary* entry = base::mac::ObjCCast<NSDictionary>(entryID);
+  if (!entry) {
+    if (completion) {
+      completion();
+    }
+    return NO;
+  }
+
+  NSNumber* cancelled = base::mac::ObjCCast<NSNumber>(
+      [entry objectForKey:app_group::kShareItemCancel]);
+  if (!cancelled) {
+    if (completion) {
+      completion();
+    }
+    return NO;
+  }
+  if ([cancelled boolValue]) {
+    LogHistogramReceivedItem(CANCELLED_ENTRY);
+    if (completion) {
+      completion();
+    }
+    return YES;
+  }
+
+  GURL entryURL =
+      net::GURLWithNSURL([entry objectForKey:app_group::kShareItemURL]);
+  std::string entryTitle =
+      base::SysNSStringToUTF8([entry objectForKey:app_group::kShareItemTitle]);
+  NSDate* entryDate = base::mac::ObjCCast<NSDate>(
+      [entry objectForKey:app_group::kShareItemDate]);
+  if (!entryURL.is_valid() || !entryDate) {
+    if (completion) {
+      completion();
+    }
+    return NO;
+  }
+
+  LogHistogramReceivedItem(READINGLIST_ENTRY);
+  UMA_HISTOGRAM_TIMES("IOS.ShareExtension.ReceivedEntryDelay",
+                      base::TimeDelta::FromSecondsD(
+                          [[NSDate date] timeIntervalSinceDate:entryDate]));
+
+  // Entry is valid. Add it to the reading list model.
+  web::WebThread::PostTask(web::WebThread::UI, FROM_HERE, base::BindBlock(^() {
+                             if (!_readingListModel) {
+                               // Reading list model may have been deleted after
+                               // the file processing
+                               // started.
+                               return;
+                             }
+                             _readingListModel->AddEntry(entryURL, entryTitle);
+                             if (completion) {
+                               web::WebThread::PostTask(web::WebThread::FILE,
+                                                        FROM_HERE,
+                                                        base::BindBlock(^() {
+                                                          completion();
+                                                        }));
+                             }
+                           }));
+  return YES;
+}
+
+- (void)handleFileAtURL:(NSURL*)url withCompletion:(ProceduralBlock)completion {
+  DCHECK_CURRENTLY_ON(web::WebThread::FILE);
+  if (![[NSFileManager defaultManager] fileExistsAtPath:[url path]]) {
+    // The handler is called on file modification, including deletion. Check
+    // that the file exists before continuing.
+    return;
+  }
+  ProceduralBlock successCompletion = ^{
+    DCHECK_CURRENTLY_ON(web::WebThread::FILE);
+    [self deleteFileAtURL:url withCompletion:completion];
+  };
+  NSError* error = nil;
+  base::scoped_nsobject<NSFileCoordinator> readingCoordinator(
+      [[NSFileCoordinator alloc] initWithFilePresenter:self]);
+  [readingCoordinator
+      coordinateReadingItemAtURL:url
+                         options:NSFileCoordinatorReadingWithoutChanges
+                           error:&error
+                      byAccessor:^(NSURL* newURL) {
+                        NSData* data = [[NSFileManager defaultManager]
+                            contentsAtPath:[newURL path]];
+                        if (![self receivedData:data
+                                 withCompletion:successCompletion]) {
+                          LogHistogramReceivedItem(INVALID_ENTRY);
+                        }
+                      }];
+}
+
+- (void)deleteFileAtURL:(NSURL*)url withCompletion:(ProceduralBlock)completion {
+  DCHECK_CURRENTLY_ON(web::WebThread::FILE);
+  if (!experimental_flags::IsReadingListKeepItemsEnabled()) {
+    base::scoped_nsobject<NSFileCoordinator> deletingCoordinator(
+        [[NSFileCoordinator alloc] initWithFilePresenter:self]);
+    NSError* error = nil;
+    [deletingCoordinator
+        coordinateWritingItemAtURL:url
+                           options:NSFileCoordinatorWritingForDeleting
+                             error:&error
+                        byAccessor:^(NSURL* newURL) {
+                          [[NSFileManager defaultManager] removeItemAtURL:newURL
+                                                                    error:nil];
+                        }];
+  }
+  if (completion) {
+    completion();
+  }
+}
+
+- (void)applicationDidBecomeActive {
+  if (!_folderCreated || _isObservingFolder) {
+    return;
+  }
+  _isObservingFolder = YES;
+  // Start observing for new files.
+  [NSFileCoordinator addFilePresenter:self];
+
+  // There may already be files. Process them.
+  web::WebThread::PostTask(
+      web::WebThread::FILE, FROM_HERE, base::BindBlock(^() {
+        NSArray<NSURL*>* files = [[NSFileManager defaultManager]
+              contentsOfDirectoryAtURL:[self presentedItemURL]
+            includingPropertiesForKeys:nil
+                               options:NSDirectoryEnumerationSkipsHiddenFiles
+                                 error:nil];
+        if ([files count] == 0) {
+          return;
+        }
+        web::WebThread::PostTask(
+            web::WebThread::UI, FROM_HERE, base::BindBlock(^() {
+              UMA_HISTOGRAM_COUNTS_100(
+                  "IOS.ShareExtension.ReceivedEntriesCount", [files count]);
+              for (NSURL* fileURL : files) {
+                __block std::unique_ptr<
+                    ReadingListModel::ScopedReadingListBatchUpdate>
+                    batchToken(_readingListModel->BeginBatchUpdates());
+                web::WebThread::PostTask(
+                    web::WebThread::FILE, FROM_HERE, base::BindBlock(^() {
+                      [self handleFileAtURL:fileURL
+                             withCompletion:^{
+                               web::WebThread::PostTask(web::WebThread::UI,
+                                                        FROM_HERE,
+                                                        base::BindBlock(^() {
+                                                          batchToken.reset();
+                                                        }));
+                             }];
+                    }));
+              }
+            }));
+      }));
+}
+
+- (void)applicationWillResignActive {
+  if (!_isObservingFolder) {
+    return;
+  }
+  _isObservingFolder = NO;
+  [NSFileCoordinator removeFilePresenter:self];
+}
+
+#pragma mark -
+#pragma mark NSFilePresenter methods
+
+- (void)presentedSubitemDidChangeAtURL:(NSURL*)url {
+  web::WebThread::PostTask(web::WebThread::FILE, FROM_HERE,
+                           base::BindBlock(^() {
+                             [self handleFileAtURL:url withCompletion:nil];
+                           }));
+}
+
+- (NSOperationQueue*)presentedItemOperationQueue {
+  return [NSOperationQueue mainQueue];
+}
+
+- (NSURL*)presentedItemURL {
+  return app_group::ShareExtensionItemsFolder();
+}
+
+@end
diff --git a/ios/chrome/browser/share_extension/share_extension_service.h b/ios/chrome/browser/share_extension/share_extension_service.h
new file mode 100644
index 0000000..bd5bda4
--- /dev/null
+++ b/ios/chrome/browser/share_extension/share_extension_service.h
@@ -0,0 +1,36 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_INTERNAL_CHROME_BROWSER_SHARE_EXTENSION_SHARE_EXTENSION_SERVICE_H_
+#define IOS_INTERNAL_CHROME_BROWSER_SHARE_EXTENSION_SHARE_EXTENSION_SERVICE_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "components/keyed_service/core/keyed_service.h"
+#include "ios/chrome/browser/reading_list/reading_list_model_observer.h"
+
+namespace ios {
+class ChromeBrowserState;
+}
+
+class ReadingListModel;
+
+// AuthenticationService is the Chrome interface to the iOS shared
+// authentication library.
+class ShareExtensionService : public KeyedService,
+                              public ReadingListModelObserver {
+ public:
+  explicit ShareExtensionService(ReadingListModel* reading_list_model);
+  ~ShareExtensionService() override;
+
+  void Initialize();
+  void Shutdown() override;
+  void ReadingListModelLoaded(const ReadingListModel* model) override;
+
+ private:
+  ReadingListModel* reading_list_model_;  // not owned.
+
+  DISALLOW_COPY_AND_ASSIGN(ShareExtensionService);
+};
+
+#endif  // IOS_INTERNAL_CHROME_BROWSER_SHARE_EXTENSION_SHARE_EXTENSION_SERVICE_H_
diff --git a/ios/chrome/browser/share_extension/share_extension_service.mm b/ios/chrome/browser/share_extension/share_extension_service.mm
new file mode 100644
index 0000000..d2940c3
--- /dev/null
+++ b/ios/chrome/browser/share_extension/share_extension_service.mm
@@ -0,0 +1,30 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/mac/scoped_nsobject.h"
+#include "ios/chrome/browser/reading_list/reading_list_model.h"
+#include "ios/chrome/browser/share_extension/share_extension_item_receiver.h"
+#include "ios/chrome/browser/share_extension/share_extension_service.h"
+
+ShareExtensionService::ShareExtensionService(ReadingListModel* model)
+    : reading_list_model_(model) {
+  DCHECK(model);
+}
+
+ShareExtensionService::~ShareExtensionService() {}
+
+void ShareExtensionService::Initialize() {
+  reading_list_model_->AddObserver(this);
+}
+
+void ShareExtensionService::Shutdown() {
+  [[ShareExtensionItemReceiver sharedInstance] shutdown];
+  reading_list_model_->RemoveObserver(this);
+}
+
+void ShareExtensionService::ReadingListModelLoaded(
+    const ReadingListModel* model) {
+  [[ShareExtensionItemReceiver sharedInstance]
+      setReadingListModel:reading_list_model_];
+}
diff --git a/ios/chrome/browser/share_extension/share_extension_service_factory.cc b/ios/chrome/browser/share_extension/share_extension_service_factory.cc
new file mode 100644
index 0000000..63f14c8e0
--- /dev/null
+++ b/ios/chrome/browser/share_extension/share_extension_service_factory.cc
@@ -0,0 +1,55 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ios/chrome/browser/share_extension/share_extension_service_factory.h"
+
+#include "base/memory/singleton.h"
+#include "components/keyed_service/ios/browser_state_dependency_manager.h"
+#include "ios/chrome/browser/browser_state/browser_state_otr_helper.h"
+#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
+#include "ios/chrome/browser/reading_list/reading_list_model_factory.h"
+#include "ios/chrome/browser/share_extension/share_extension_service.h"
+
+// static
+ShareExtensionService* ShareExtensionServiceFactory::GetForBrowserState(
+    ios::ChromeBrowserState* browser_state) {
+  return static_cast<ShareExtensionService*>(
+      GetInstance()->GetServiceForBrowserState(browser_state, true));
+}
+
+// static
+ShareExtensionService* ShareExtensionServiceFactory::GetForBrowserStateIfExists(
+    ios::ChromeBrowserState* browser_state) {
+  return static_cast<ShareExtensionService*>(
+      GetInstance()->GetServiceForBrowserState(browser_state, false));
+}
+
+// static
+ShareExtensionServiceFactory* ShareExtensionServiceFactory::GetInstance() {
+  return base::Singleton<ShareExtensionServiceFactory>::get();
+}
+
+ShareExtensionServiceFactory::ShareExtensionServiceFactory()
+    : BrowserStateKeyedServiceFactory(
+          "ShareExtensionService",
+          BrowserStateDependencyManager::GetInstance()) {
+  DependsOn(ReadingListModelFactory::GetInstance());
+}
+
+ShareExtensionServiceFactory::~ShareExtensionServiceFactory() {}
+
+scoped_ptr<KeyedService> ShareExtensionServiceFactory::BuildServiceInstanceFor(
+    web::BrowserState* context) const {
+  ios::ChromeBrowserState* chrome_browser_state =
+      ios::ChromeBrowserState::FromBrowserState(context);
+  scoped_ptr<ShareExtensionService> share_extension_service(
+      new ShareExtensionService(
+          ReadingListModelFactory::GetForBrowserState(chrome_browser_state)));
+  return std::move(share_extension_service);
+}
+
+web::BrowserState* ShareExtensionServiceFactory::GetBrowserStateToUse(
+    web::BrowserState* context) const {
+  return GetBrowserStateRedirectedInIncognito(context);
+}
diff --git a/ios/chrome/browser/share_extension/share_extension_service_factory.h b/ios/chrome/browser/share_extension/share_extension_service_factory.h
new file mode 100644
index 0000000..9dfa912
--- /dev/null
+++ b/ios/chrome/browser/share_extension/share_extension_service_factory.h
@@ -0,0 +1,46 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_SHARE_EXTENSION_SHARE_EXTENSION_SERVICE_FACTORY_H_
+#define IOS_CHROME_BROWSER_SHARE_EXTENSION_SHARE_EXTENSION_SERVICE_FACTORY_H_
+
+#include "components/keyed_service/ios/browser_state_keyed_service_factory.h"
+
+namespace base {
+template <typename T>
+struct DefaultSingletonTraits;
+}  // namespace base
+
+class ShareExtensionService;
+
+namespace ios {
+class ChromeBrowserState;
+}
+
+// Singleton that owns the ShareExtensionService and associates it with
+// ios::ChromeBrowserState.
+class ShareExtensionServiceFactory : public BrowserStateKeyedServiceFactory {
+ public:
+  static ShareExtensionService* GetForBrowserState(
+      ios::ChromeBrowserState* browser_state);
+  static ShareExtensionService* GetForBrowserStateIfExists(
+      ios::ChromeBrowserState* browser_state);
+  static ShareExtensionServiceFactory* GetInstance();
+
+ private:
+  friend struct base::DefaultSingletonTraits<ShareExtensionServiceFactory>;
+
+  ShareExtensionServiceFactory();
+  ~ShareExtensionServiceFactory() override;
+
+  // BrowserStateKeyedServiceFactory implementation.
+  scoped_ptr<KeyedService> BuildServiceInstanceFor(
+      web::BrowserState* context) const override;
+  web::BrowserState* GetBrowserStateToUse(
+      web::BrowserState* context) const override;
+
+  DISALLOW_COPY_AND_ASSIGN(ShareExtensionServiceFactory);
+};
+
+#endif  // IOS_CHROME_BROWSER_SHARE_EXTENSION_SHARE_EXTENSION_SERVICE_FACTORY_H_
diff --git a/ios/chrome/common/app_group/app_group_constants.h b/ios/chrome/common/app_group/app_group_constants.h
index fe1e18fd7..c9217df 100644
--- a/ios/chrome/common/app_group/app_group_constants.h
+++ b/ios/chrome/common/app_group/app_group_constants.h
@@ -61,6 +61,13 @@
 // metrics reporting.
 extern const char kUserMetricsEnabledDate[];
 
+// The four keys of the items sent by the share extension to Chrome (URL,
+// title, date, cancel).
+extern NSString* const kShareItemURL;
+extern NSString* const kShareItemTitle;
+extern NSString* const kShareItemDate;
+extern NSString* const kShareItemCancel;
+
 // The current epoch time, on the first run of chrome on this machine. It is set
 // once and must be attached to metrics reports forever thereafter.
 extern const char kInstallDate[];
@@ -72,6 +79,10 @@
 // Gets the application group
 NSString* ApplicationGroup();
 
+// Gets the share extension folder URL.
+// If the folder does not exist, create it.
+NSURL* ShareExtensionItemsFolder();
+
 // Returns an autoreleased pointer to the shared user defaults if an
 // application group is defined. If not (i.e. on simulator, or if entitlements
 // do not allow it) returns [NSUserDefaults standardUserDefaults].
diff --git a/ios/chrome/common/app_group/app_group_constants.mm b/ios/chrome/common/app_group/app_group_constants.mm
index 48e46b1..f66bf31 100644
--- a/ios/chrome/common/app_group/app_group_constants.mm
+++ b/ios/chrome/common/app_group/app_group_constants.mm
@@ -36,6 +36,11 @@
 const char kInstallDate[] = "InstallDate";
 const char kBrandCode[] = "BrandCode";
 
+NSString* const kShareItemURL = @"URL";
+NSString* const kShareItemTitle = @"Title";
+NSString* const kShareItemDate = @"Date";
+NSString* const kShareItemCancel = @"Cancel";
+
 NSString* ApplicationGroup() {
   NSBundle* bundle = [NSBundle mainBundle];
   NSString* group = [bundle objectForInfoDictionaryKey:@"KSApplicationGroup"];
@@ -70,4 +75,12 @@
   return [NSUserDefaults standardUserDefaults];
 }
 
+NSURL* ShareExtensionItemsFolder() {
+  NSURL* groupURL = [[NSFileManager defaultManager]
+      containerURLForSecurityApplicationGroupIdentifier:ApplicationGroup()];
+  NSURL* readingListURL =
+      [groupURL URLByAppendingPathComponent:@"ShareExtensionItems"];
+  return readingListURL;
+}
+
 }  // namespace app_group
diff --git a/ios/chrome/ios_chrome.gyp b/ios/chrome/ios_chrome.gyp
index 5b2fb99..d6dd668 100644
--- a/ios/chrome/ios_chrome.gyp
+++ b/ios/chrome/ios_chrome.gyp
@@ -466,6 +466,12 @@
         'browser/sessions/ios_chrome_tab_restore_service_client.mm',
         'browser/sessions/ios_chrome_tab_restore_service_factory.cc',
         'browser/sessions/ios_chrome_tab_restore_service_factory.h',
+        'browser/share_extension/share_extension_item_receiver.h',
+        'browser/share_extension/share_extension_item_receiver.mm',
+        'browser/share_extension/share_extension_service.h',
+        'browser/share_extension/share_extension_service.mm',
+        'browser/share_extension/share_extension_service_factory.cc',
+        'browser/share_extension/share_extension_service_factory.h',
         'browser/signin/about_signin_internals_factory.cc',
         'browser/signin/about_signin_internals_factory.h',
         'browser/signin/account_consistency_service_factory.h',
diff --git a/ios/net/cookies/cookie_store_ios.h b/ios/net/cookies/cookie_store_ios.h
index 914804d..29feb38b 100644
--- a/ios/net/cookies/cookie_store_ios.h
+++ b/ios/net/cookies/cookie_store_ios.h
@@ -12,6 +12,7 @@
 
 #include "base/callback.h"
 #include "base/cancelable_callback.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/macros.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
@@ -202,7 +203,7 @@
                                const DeleteCallback& callback);
 
   scoped_ptr<net::CookieMonster> cookie_monster_;
-  NSHTTPCookieStorage* system_store_;
+  base::scoped_nsobject<NSHTTPCookieStorage> system_store_;
   scoped_ptr<CookieCreationTimeManager> creation_time_manager_;
   bool metrics_enabled_;
   base::TimeDelta flush_delay_;
diff --git a/ios/net/cookies/cookie_store_ios.mm b/ios/net/cookies/cookie_store_ios.mm
index 2d3ebda..0d5f0017 100644
--- a/ios/net/cookies/cookie_store_ios.mm
+++ b/ios/net/cookies/cookie_store_ios.mm
@@ -293,7 +293,7 @@
     net::CookieMonster::PersistentCookieStore* persistent_store,
     NSHTTPCookieStorage* system_store)
     : cookie_monster_(new net::CookieMonster(persistent_store, nullptr)),
-      system_store_(system_store),
+      system_store_([system_store retain]),
       creation_time_manager_(new CookieCreationTimeManager),
       metrics_enabled_(false),
       flush_delay_(base::TimeDelta::FromSeconds(10)),
diff --git a/ios/web/web_state/js/resources/plugin_placeholder.js b/ios/web/web_state/js/resources/plugin_placeholder.js
index 473ccea..c8fcbab 100644
--- a/ios/web/web_state/js/resources/plugin_placeholder.js
+++ b/ios/web/web_state/js/resources/plugin_placeholder.js
@@ -42,8 +42,8 @@
 
   /**
    * Returns the first <embed> child of the given node, if any.
-   * @param {HTMLElement} node The node to check.
-   * @return {HTMLElement} The first <embed> child, or null.
+   * @param {Node} node The node to check.
+   * @return {Node} The first <embed> child, or null.
    * @private
    */
   __gCrWeb['plugin'].getEmbedChild_ = function(node) {
diff --git a/ipc/mojo/BUILD.gn b/ipc/mojo/BUILD.gn
index 4966b90..9804845 100644
--- a/ipc/mojo/BUILD.gn
+++ b/ipc/mojo/BUILD.gn
@@ -37,8 +37,6 @@
     "//base/third_party/dynamic_annotations",
     "//ipc",
     "//mojo/edk/system",
-    "//mojo/environment:chromium",
-    "//mojo/public/c/environment:environment",
     "//mojo/public/cpp/bindings",
   ]
 }
@@ -63,7 +61,6 @@
     "//ipc:test_support",
     "//mojo/edk/system",
     "//mojo/edk/test:test_support",
-    "//mojo/environment:chromium",
     "//testing/gtest",
     "//url",
   ]
@@ -86,7 +83,6 @@
     "//mojo/edk/system",
     "//mojo/edk/test:test_support",
     "//mojo/edk/test:test_support_impl",
-    "//mojo/environment:chromium",
     "//url",
   ]
 
diff --git a/ipc/mojo/ipc_message_pipe_reader.h b/ipc/mojo/ipc_message_pipe_reader.h
index 7120fc60..38ca6a8a 100644
--- a/ipc/mojo/ipc_message_pipe_reader.h
+++ b/ipc/mojo/ipc_message_pipe_reader.h
@@ -17,7 +17,6 @@
 #include "base/threading/thread_checker.h"
 #include "ipc/ipc_message.h"
 #include "ipc/mojo/ipc.mojom.h"
-#include "mojo/public/c/environment/async_waiter.h"
 #include "mojo/public/cpp/bindings/associated_binding.h"
 #include "mojo/public/cpp/system/core.h"
 
diff --git a/ipc/mojo/ipc_mojo.gyp b/ipc/mojo/ipc_mojo.gyp
index c471d37..cb22889 100644
--- a/ipc/mojo/ipc_mojo.gyp
+++ b/ipc/mojo/ipc_mojo.gyp
@@ -22,7 +22,6 @@
         '../ipc.gyp:ipc',
         '../../base/base.gyp:base',
         '../../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
-        '../../mojo/mojo_base.gyp:mojo_environment_chromium',
         '../../mojo/mojo_edk.gyp:mojo_system_impl',
         '../../mojo/mojo_public.gyp:mojo_cpp_bindings',
       ],
@@ -60,7 +59,6 @@
         '../../base/base.gyp:base',
         '../../base/base.gyp:base_i18n',
         '../../base/base.gyp:test_support_base',
-        '../../mojo/mojo_base.gyp:mojo_environment_chromium',
         '../../mojo/mojo_edk.gyp:mojo_common_test_support',
         '../../mojo/mojo_edk.gyp:mojo_system_impl',
         '../../mojo/mojo_public.gyp:mojo_cpp_bindings',
@@ -92,7 +90,6 @@
         '../../base/base.gyp:base_i18n',
         '../../base/base.gyp:test_support_base',
         '../../base/base.gyp:test_support_perf',
-        '../../mojo/mojo_base.gyp:mojo_environment_chromium',
         '../../mojo/mojo_edk.gyp:mojo_common_test_support',
         '../../mojo/mojo_edk.gyp:mojo_system_impl',
         '../../mojo/mojo_public.gyp:mojo_cpp_bindings',
diff --git a/mash/wm/window_manager_impl.cc b/mash/wm/window_manager_impl.cc
deleted file mode 100644
index 9d46e6b0..0000000
--- a/mash/wm/window_manager_impl.cc
+++ /dev/null
@@ -1,181 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "mash/wm/window_manager_impl.h"
-
-#include <stdint.h>
-#include <utility>
-
-#include "components/mus/common/types.h"
-#include "components/mus/public/cpp/window.h"
-#include "components/mus/public/cpp/window_property.h"
-#include "components/mus/public/cpp/window_tree_connection.h"
-#include "components/mus/public/interfaces/input_events.mojom.h"
-#include "components/mus/public/interfaces/mus_constants.mojom.h"
-#include "components/mus/public/interfaces/window_manager.mojom.h"
-#include "mash/wm/non_client_frame_controller.h"
-#include "mash/wm/property_util.h"
-#include "mash/wm/public/interfaces/container.mojom.h"
-#include "mash/wm/window_manager_application.h"
-#include "mojo/converters/geometry/geometry_type_converters.h"
-
-namespace mash {
-namespace wm {
-
-WindowManagerImpl::WindowManagerImpl()
-    : state_(nullptr), window_manager_client_(nullptr), binding_(this) {}
-
-WindowManagerImpl::~WindowManagerImpl() {
-  if (!state_)
-    return;
-  for (auto container : state_->root()->children()) {
-    container->RemoveObserver(this);
-    for (auto child : container->children())
-      child->RemoveObserver(this);
-  }
-}
-
-void WindowManagerImpl::Initialize(WindowManagerApplication* state,
-                                   mash::shell::mojom::ShellPtr shell) {
-  DCHECK(state);
-  DCHECK(!state_);
-  state_ = state;
-  // The children of the root are considered containers.
-  for (auto container : state_->root()->children()) {
-    container->AddObserver(this);
-    for (auto child : container->children())
-      child->AddObserver(this);
-  }
-
-  // The insets are roughly what is needed by CustomFrameView. The expectation
-  // is at some point we'll write our own NonClientFrameView and get the insets
-  // from it.
-  mus::mojom::FrameDecorationValuesPtr frame_decoration_values =
-      mus::mojom::FrameDecorationValues::New();
-  const gfx::Insets client_area_insets =
-      NonClientFrameController::GetPreferredClientAreaInsets();
-  frame_decoration_values->normal_client_area_insets =
-      mojo::Insets::From(client_area_insets);
-  frame_decoration_values->maximized_client_area_insets =
-      mojo::Insets::From(client_area_insets);
-  frame_decoration_values->max_title_bar_button_width =
-      NonClientFrameController::GetMaxTitleBarButtonWidth();
-  window_manager_client_->SetFrameDecorationValues(
-      std::move(frame_decoration_values));
-
-  shell->AddScreenlockStateListener(binding_.CreateInterfacePtrAndBind());
-}
-
-gfx::Rect WindowManagerImpl::CalculateDefaultBounds(mus::Window* window) const {
-  DCHECK(state_);
-  int width, height;
-  const gfx::Size pref = GetWindowPreferredSize(window);
-  const mus::Window* root = state_->root();
-  if (pref.IsEmpty()) {
-    width = root->bounds().width() - 240;
-    height = root->bounds().height() - 240;
-  } else {
-    // TODO(sky): likely want to constrain more than root size.
-    const gfx::Size max_size = GetMaximizedWindowBounds().size();
-    width = std::max(0, std::min(max_size.width(), pref.width()));
-    height = std::max(0, std::min(max_size.height(), pref.height()));
-  }
-  return gfx::Rect(40 + (state_->window_count() % 4) * 40,
-                   40 + (state_->window_count() % 4) * 40, width, height);
-}
-
-gfx::Rect WindowManagerImpl::GetMaximizedWindowBounds() const {
-  DCHECK(state_);
-  return gfx::Rect(state_->root()->bounds().size());
-}
-
-mus::Window* WindowManagerImpl::NewTopLevelWindow(
-    std::map<std::string, std::vector<uint8_t>>* properties,
-    mus::mojom::WindowTreeClientPtr client) {
-  DCHECK(state_);
-  mus::Window* root = state_->root();
-  DCHECK(root);
-
-  const bool provide_non_client_frame =
-      GetWindowType(*properties) == mus::mojom::WindowType::WINDOW;
-  if (provide_non_client_frame)
-    (*properties)[mus::mojom::kWaitForUnderlay_Property].clear();
-
-  // TODO(sky): constrain and validate properties before passing to server.
-  mus::Window* window = root->connection()->NewWindow(properties);
-  window->SetBounds(CalculateDefaultBounds(window));
-
-  mojom::Container container = GetRequestedContainer(window);
-  state_->GetWindowForContainer(container)->AddChild(window);
-
-  if (client)
-    window->Embed(std::move(client));
-
-  if (provide_non_client_frame) {
-    // NonClientFrameController deletes itself when |window| is destroyed.
-    new NonClientFrameController(state_->app()->shell(), window,
-                                 state_->window_tree_host());
-  }
-
-  state_->IncrementWindowCount();
-
-  return window;
-}
-
-void WindowManagerImpl::OnTreeChanging(const TreeChangeParams& params) {
-  DCHECK(state_);
-  if (state_->WindowIsContainer(params.old_parent))
-    params.target->RemoveObserver(this);
-  else if (state_->WindowIsContainer(params.new_parent))
-    params.target->AddObserver(this);
-}
-
-void WindowManagerImpl::OnWindowEmbeddedAppDisconnected(mus::Window* window) {
-  window->Destroy();
-}
-
-void WindowManagerImpl::OpenWindow(
-    mus::mojom::WindowTreeClientPtr client,
-    mojo::Map<mojo::String, mojo::Array<uint8_t>> transport_properties) {
-  mus::Window::SharedProperties properties =
-      transport_properties.To<mus::Window::SharedProperties>();
-  NewTopLevelWindow(&properties, std::move(client));
-}
-
-void WindowManagerImpl::SetWindowManagerClient(
-    mus::WindowManagerClient* client) {
-  window_manager_client_ = client;
-}
-
-bool WindowManagerImpl::OnWmSetBounds(mus::Window* window, gfx::Rect* bounds) {
-  // By returning true the bounds of |window| is updated.
-  return true;
-}
-
-bool WindowManagerImpl::OnWmSetProperty(
-    mus::Window* window,
-    const std::string& name,
-    scoped_ptr<std::vector<uint8_t>>* new_data) {
-  // TODO(sky): constrain this to set of keys we know about, and allowed
-  // values.
-  return name == mus::mojom::WindowManager::kShowState_Property ||
-         name == mus::mojom::WindowManager::kPreferredSize_Property ||
-         name == mus::mojom::WindowManager::kResizeBehavior_Property ||
-         name == mus::mojom::WindowManager::kWindowTitle_Property;
-}
-
-mus::Window* WindowManagerImpl::OnWmCreateTopLevelWindow(
-    std::map<std::string, std::vector<uint8_t>>* properties) {
-  return NewTopLevelWindow(properties, nullptr);
-}
-
-void WindowManagerImpl::ScreenlockStateChanged(bool locked) {
-  // Hide USER_PRIVATE windows when the screen is locked.
-  mus::Window* window =
-      state_->GetWindowForContainer(mash::wm::mojom::Container::USER_PRIVATE);
-  window->SetVisible(!locked);
-}
-
-}  // namespace wm
-}  // namespace mash
diff --git a/mash/wm/window_manager_impl.h b/mash/wm/window_manager_impl.h
deleted file mode 100644
index fd1c4c6c..0000000
--- a/mash/wm/window_manager_impl.h
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef MASH_WM_WINDOW_MANAGER_IMPL_H_
-#define MASH_WM_WINDOW_MANAGER_IMPL_H_
-
-#include <stdint.h>
-
-#include "base/macros.h"
-#include "components/mus/common/types.h"
-#include "components/mus/public/cpp/window_manager_delegate.h"
-#include "components/mus/public/cpp/window_observer.h"
-#include "components/mus/public/interfaces/window_manager.mojom.h"
-#include "mash/shell/public/interfaces/shell.mojom.h"
-#include "mojo/public/cpp/bindings/binding.h"
-
-namespace mash {
-namespace wm {
-
-class WindowManagerApplication;
-
-using WindowManagerErrorCodeCallback =
-    const mojo::Callback<void(mus::mojom::WindowManagerErrorCode)>;
-
-class WindowManagerImpl : public mus::mojom::WindowManagerDeprecated,
-                          public mus::WindowObserver,
-                          public mus::WindowManagerDelegate,
-                          public mash::shell::mojom::ScreenlockStateListener {
- public:
-  WindowManagerImpl();
-  ~WindowManagerImpl() override;
-
-  void Initialize(WindowManagerApplication* state,
-                  mash::shell::mojom::ShellPtr shell);
-
- private:
-  gfx::Rect CalculateDefaultBounds(mus::Window* window) const;
-  gfx::Rect GetMaximizedWindowBounds() const;
-
-  mus::Window* NewTopLevelWindow(
-      std::map<std::string, std::vector<uint8_t>>* properties,
-      mus::mojom::WindowTreeClientPtr client);
-
-  // mus::WindowObserver:
-  void OnTreeChanging(const TreeChangeParams& params) override;
-  void OnWindowEmbeddedAppDisconnected(mus::Window* window) override;
-
-  // mus::mojom::WindowManager:
-  void OpenWindow(mus::mojom::WindowTreeClientPtr client,
-                  mojo::Map<mojo::String, mojo::Array<uint8_t>>
-                      transport_properties) override;
-
-  // WindowManagerDelegate:
-  void SetWindowManagerClient(mus::WindowManagerClient* client) override;
-  bool OnWmSetBounds(mus::Window* window, gfx::Rect* bounds) override;
-  bool OnWmSetProperty(mus::Window* window,
-                       const std::string& name,
-                       scoped_ptr<std::vector<uint8_t>>* new_data) override;
-  mus::Window* OnWmCreateTopLevelWindow(
-      std::map<std::string, std::vector<uint8_t>>* properties) override;
-
-  // mash::shell::mojom::ScreenlockStateListener:
-  void ScreenlockStateChanged(bool locked) override;
-
-  WindowManagerApplication* state_;
-  mus::WindowManagerClient* window_manager_client_;
-
-  mojo::Binding<mash::shell::mojom::ScreenlockStateListener> binding_;
-
-  DISALLOW_COPY_AND_ASSIGN(WindowManagerImpl);
-};
-
-}  // namespace wm
-}  // namespace mash
-
-#endif  // MASH_WM_WINDOW_MANAGER_IMPL_H_
diff --git a/media/mojo/common/BUILD.gn b/media/mojo/common/BUILD.gn
index eed3ae3..1d0fa812 100644
--- a/media/mojo/common/BUILD.gn
+++ b/media/mojo/common/BUILD.gn
@@ -21,7 +21,6 @@
     "//media/mojo/interfaces",
     "//mojo/common",
     "//mojo/converters/geometry",
-    "//mojo/environment:chromium",
     "//mojo/public/c/system:for_component",
     "//ui/gfx/geometry",
     "//ui/mojo/geometry:interfaces",
@@ -43,7 +42,6 @@
     "//media/mojo/interfaces",
     "//mojo/edk/system",
     "//mojo/edk/test:run_all_unittests",
-    "//mojo/environment:chromium",
     "//testing/gmock",
     "//testing/gtest",
   ]
diff --git a/media/mojo/interfaces/demuxer_stream.mojom b/media/mojo/interfaces/demuxer_stream.mojom
index 5b880b74..039888d 100644
--- a/media/mojo/interfaces/demuxer_stream.mojom
+++ b/media/mojo/interfaces/demuxer_stream.mojom
@@ -53,4 +53,8 @@
              DecoderBuffer? buffer,
              AudioDecoderConfig? audio_config,
              VideoDecoderConfig? video_config);
+
+  // Enables converting bitstream to a format that is expected by the decoder.
+  // For example, H.264/AAC bitstream based packets into H.264 Annex B format.
+  EnableBitstreamConverter();
 };
diff --git a/media/mojo/interfaces/mojo_bindings.gyp b/media/mojo/interfaces/mojo_bindings.gyp
index c4d0679..6a57a53 100644
--- a/media/mojo/interfaces/mojo_bindings.gyp
+++ b/media/mojo/interfaces/mojo_bindings.gyp
@@ -18,7 +18,6 @@
       'dependencies': [
         'platform_verification_mojo_bindings',
         '../../../mojo/mojo_base.gyp:mojo_application_bindings',
-        '../../../mojo/mojo_base.gyp:mojo_environment_chromium',
         '../../../mojo/mojo_public.gyp:mojo_cpp_bindings',
       ],
       'sources': [
@@ -41,7 +40,6 @@
       'dependencies': [
         'provision_fetcher_mojo_bindings',
         '../../../mojo/mojo_base.gyp:mojo_application_bindings',
-        '../../../mojo/mojo_base.gyp:mojo_environment_chromium',
         '../../../mojo/mojo_public.gyp:mojo_cpp_bindings',
       ],
       'sources': [
diff --git a/media/mojo/services/BUILD.gn b/media/mojo/services/BUILD.gn
index a2e6f53..d0e4f9d7 100644
--- a/media/mojo/services/BUILD.gn
+++ b/media/mojo/services/BUILD.gn
@@ -75,7 +75,6 @@
     "//media/mojo/common",
     "//media/mojo/interfaces",
     "//mojo/common",
-    "//mojo/environment:chromium",
     "//mojo/public/c/system:for_component",
     "//mojo/shell/public/interfaces",
   ]
@@ -88,7 +87,6 @@
     "//media/mojo/common",
     "//media/mojo/interfaces",
     "//mojo/common",
-    "//mojo/environment:chromium",
     "//mojo/public/c/system:for_component",
     "//mojo/shell/public/interfaces",
   ]
diff --git a/media/mojo/services/mojo_demuxer_stream_adapter.cc b/media/mojo/services/mojo_demuxer_stream_adapter.cc
index 006f2f8..4b50594 100644
--- a/media/mojo/services/mojo_demuxer_stream_adapter.cc
+++ b/media/mojo/services/mojo_demuxer_stream_adapter.cc
@@ -58,7 +58,7 @@
 }
 
 void MojoDemuxerStreamAdapter::EnableBitstreamConverter() {
-  NOTIMPLEMENTED();
+  demuxer_stream_->EnableBitstreamConverter();
 }
 
 bool MojoDemuxerStreamAdapter::SupportsConfigChanges() {
diff --git a/media/mojo/services/mojo_demuxer_stream_impl.cc b/media/mojo/services/mojo_demuxer_stream_impl.cc
index f7af949..b564cb6 100644
--- a/media/mojo/services/mojo_demuxer_stream_impl.cc
+++ b/media/mojo/services/mojo_demuxer_stream_impl.cc
@@ -75,6 +75,10 @@
                            weak_factory_.GetWeakPtr(), callback));
 }
 
+void MojoDemuxerStreamImpl::EnableBitstreamConverter() {
+  stream_->EnableBitstreamConverter();
+}
+
 void MojoDemuxerStreamImpl::OnBufferReady(
     const ReadCallback& callback,
     media::DemuxerStream::Status status,
diff --git a/media/mojo/services/mojo_demuxer_stream_impl.h b/media/mojo/services/mojo_demuxer_stream_impl.h
index 5049eed..fa54226 100644
--- a/media/mojo/services/mojo_demuxer_stream_impl.h
+++ b/media/mojo/services/mojo_demuxer_stream_impl.h
@@ -30,6 +30,7 @@
   // interfaces::DemuxerStream.
   void Initialize(const InitializeCallback& callback) override;
   void Read(const ReadCallback& callback) override;
+  void EnableBitstreamConverter() override;
 
  private:
   void OnBufferReady(const ReadCallback& callback,
diff --git a/mojo/BUILD.gn b/mojo/BUILD.gn
index 7c2b9d2..779cb894 100644
--- a/mojo/BUILD.gn
+++ b/mojo/BUILD.gn
@@ -39,7 +39,6 @@
     "//mojo/edk/system:mojo_system_unittests",
     "//mojo/edk/test:mojo_public_bindings_perftests",
     "//mojo/edk/test:mojo_public_bindings_unittests",
-    "//mojo/edk/test:mojo_public_environment_unittests",
     "//mojo/edk/test:mojo_public_system_perftests",
     "//mojo/edk/test:mojo_public_system_unittests",
     "//mojo/edk/test:mojo_public_utility_unittests",
diff --git a/mojo/android/BUILD.gn b/mojo/android/BUILD.gn
index 63a13446..020ef6d 100644
--- a/mojo/android/BUILD.gn
+++ b/mojo/android/BUILD.gn
@@ -46,7 +46,6 @@
     ":system_java_jni_headers",
     "//base",
     "//mojo/edk/system",
-    "//mojo/environment:chromium",
     "//mojo/message_pump",
   ]
 }
@@ -125,7 +124,6 @@
     "//mojo/edk/system",
     "//mojo/message_pump",
     "//mojo/public/cpp/bindings/tests:mojo_public_bindings_test_utils",
-    "//mojo/public/cpp/environment",
     "//mojo/public/cpp/test_support:test_utils",
   ]
   defines = [ "UNIT_TEST" ]
diff --git a/mojo/android/javatests/mojo_test_case.cc b/mojo/android/javatests/mojo_test_case.cc
index 631cf976..176e9bc0 100644
--- a/mojo/android/javatests/mojo_test_case.cc
+++ b/mojo/android/javatests/mojo_test_case.cc
@@ -14,7 +14,6 @@
 #include "base/test/test_support_android.h"
 #include "jni/MojoTestCase_jni.h"
 #include "mojo/message_pump/message_pump_mojo.h"
-#include "mojo/public/cpp/environment/environment.h"
 
 namespace {
 
diff --git a/mojo/common/BUILD.gn b/mojo/common/BUILD.gn
index 6a12118..bffb612 100644
--- a/mojo/common/BUILD.gn
+++ b/mojo/common/BUILD.gn
@@ -36,11 +36,9 @@
   deps = [
     "//base",
     "//base/third_party/dynamic_annotations",
-    "//mojo/environment:chromium",
     "//mojo/message_pump",
     "//mojo/public/c/system:for_component",
     "//mojo/public/cpp/bindings",
-    "//mojo/public/cpp/environment",
   ]
 }
 
@@ -69,7 +67,6 @@
     "//base/test:test_support",
     "//mojo/edk/test:run_all_unittests",
     "//mojo/edk/test:test_support",
-    "//mojo/environment:chromium",
     "//mojo/message_pump",
     "//mojo/public/cpp/bindings",
     "//mojo/public/cpp/test_support:test_utils",
@@ -97,7 +94,6 @@
     ":common",
     "//base",
     "//mojo/edk/test:run_all_perftests",
-    "//mojo/environment:chromium",
     "//mojo/message_pump",
     "//mojo/public/cpp/test_support:test_utils",
     "//testing/gtest",
diff --git a/mojo/converters/blink/BUILD.gn b/mojo/converters/blink/BUILD.gn
index f5486f05..7f6b412 100644
--- a/mojo/converters/blink/BUILD.gn
+++ b/mojo/converters/blink/BUILD.gn
@@ -16,7 +16,6 @@
   deps = [
     "//base",
     "//components/mus/public/interfaces",
-    "//mojo/environment:chromium",
     "//mojo/public/c/system:for_component",
     "//third_party/WebKit/public:blink",
     "//ui/events",
diff --git a/mojo/converters/geometry/BUILD.gn b/mojo/converters/geometry/BUILD.gn
index efe39c1..ce047c3 100644
--- a/mojo/converters/geometry/BUILD.gn
+++ b/mojo/converters/geometry/BUILD.gn
@@ -11,7 +11,6 @@
     "//ui/gfx/geometry",
   ]
   deps = [
-    "//mojo/environment:chromium",
     "//mojo/public/c/system:for_component",
     "//ui/mojo/geometry:interfaces",
   ]
diff --git a/mojo/converters/ime/BUILD.gn b/mojo/converters/ime/BUILD.gn
index d3c1d865..3914ee3 100644
--- a/mojo/converters/ime/BUILD.gn
+++ b/mojo/converters/ime/BUILD.gn
@@ -12,7 +12,6 @@
   ]
   deps = [
     "//base",
-    "//mojo/environment:chromium",
     "//mojo/public/c/system:for_component",
     "//ui/mojo/ime:interfaces",
     "//ui/platform_window",
diff --git a/mojo/converters/input_events/BUILD.gn b/mojo/converters/input_events/BUILD.gn
index fb59cb7..b724bbe9 100644
--- a/mojo/converters/input_events/BUILD.gn
+++ b/mojo/converters/input_events/BUILD.gn
@@ -17,7 +17,6 @@
     "//base",
     "//components/mus/public/interfaces",
     "//mojo/converters/geometry",
-    "//mojo/environment:chromium",
     "//mojo/public/c/system:for_component",
     "//ui/events",
     "//ui/events:dom_keycode_converter",
diff --git a/mojo/converters/surfaces/BUILD.gn b/mojo/converters/surfaces/BUILD.gn
index c95fdba..6609e8e 100644
--- a/mojo/converters/surfaces/BUILD.gn
+++ b/mojo/converters/surfaces/BUILD.gn
@@ -30,7 +30,6 @@
     "//cc/surfaces:surface_id",
     "//components/mus/public/interfaces",
     "//gpu",
-    "//mojo/environment:chromium",
     "//mojo/public/c/system:for_component",
     "//skia",
     "//ui/gfx/geometry",
diff --git a/mojo/converters/surfaces/tests/BUILD.gn b/mojo/converters/surfaces/tests/BUILD.gn
index edfe3bab..4cb915d 100644
--- a/mojo/converters/surfaces/tests/BUILD.gn
+++ b/mojo/converters/surfaces/tests/BUILD.gn
@@ -17,7 +17,6 @@
     "//mojo/converters/surfaces",
     "//mojo/converters/transform",
     "//mojo/edk/test:run_all_unittests",
-    "//mojo/environment:chromium",
     "//skia",
     "//testing/gtest",
     "//ui/gfx",
diff --git a/mojo/converters/transform/BUILD.gn b/mojo/converters/transform/BUILD.gn
index d3e29a1..34da111f 100644
--- a/mojo/converters/transform/BUILD.gn
+++ b/mojo/converters/transform/BUILD.gn
@@ -9,7 +9,6 @@
     "//ui/gfx",
   ]
   deps = [
-    "//mojo/environment:chromium",
     "//mojo/public/c/system:for_component",
     "//skia",
     "//ui/mojo/geometry:interfaces",
diff --git a/mojo/edk/js/test/BUILD.gn b/mojo/edk/js/test/BUILD.gn
index 758edb4e..0ac9945 100644
--- a/mojo/edk/js/test/BUILD.gn
+++ b/mojo/edk/js/test/BUILD.gn
@@ -13,8 +13,6 @@
     "//mojo/edk/js",
     "//mojo/edk/test:run_all_unittests",
     "//mojo/edk/test:test_support",
-    "//mojo/environment:chromium",
-    "//mojo/public/cpp/environment",
     "//mojo/public/cpp/system",
     "//mojo/public/cpp/utility",
     "//mojo/public/interfaces/bindings/tests:test_interfaces",
@@ -36,7 +34,6 @@
     "//mojo/edk/js/tests:js_to_cpp_tests",
     "//mojo/edk/test:run_all_unittests",
     "//mojo/edk/test:test_support",
-    "//mojo/environment:chromium",
     "//mojo/public/cpp/bindings",
     "//mojo/public/interfaces/bindings/tests:test_interfaces",
   ]
diff --git a/mojo/edk/js/tests/BUILD.gn b/mojo/edk/js/tests/BUILD.gn
index 4bbd1386..5761bcb3 100644
--- a/mojo/edk/js/tests/BUILD.gn
+++ b/mojo/edk/js/tests/BUILD.gn
@@ -30,6 +30,4 @@
   sources = [
     "js_to_cpp.mojom",
   ]
-
-  with_environment = false
 }
diff --git a/mojo/edk/system/BUILD.gn b/mojo/edk/system/BUILD.gn
index b9cac17..1bd597f3 100644
--- a/mojo/edk/system/BUILD.gn
+++ b/mojo/edk/system/BUILD.gn
@@ -168,7 +168,6 @@
     "//mojo/edk/system",
     "//mojo/edk/test:run_all_unittests",
     "//mojo/edk/test:test_support",
-    "//mojo/public/cpp/environment:standalone",
     "//testing/gtest",
   ]
 
@@ -187,7 +186,6 @@
     "//mojo/edk/system",
     "//mojo/edk/test:run_all_perftests",
     "//mojo/edk/test:test_support",
-    "//mojo/public/cpp/environment:standalone",
     "//testing/gtest",
   ]
 }
diff --git a/mojo/edk/test/BUILD.gn b/mojo/edk/test/BUILD.gn
index d81ff02..171d087 100644
--- a/mojo/edk/test/BUILD.gn
+++ b/mojo/edk/test/BUILD.gn
@@ -92,7 +92,6 @@
   testonly = true
   deps = [
     ":mojo_public_bindings_unittests",
-    ":mojo_public_environment_unittests",
     ":mojo_public_system_perftests",
     ":mojo_public_system_unittests",
     ":mojo_public_utility_unittests",
@@ -115,13 +114,6 @@
   ]
 }
 
-test("mojo_public_environment_unittests") {
-  deps = [
-    ":run_all_unittests",
-    "//mojo/public/cpp/environment/tests",
-  ]
-}
-
 test("mojo_public_system_perftests") {
   deps = [
     ":run_all_perftests",
diff --git a/mojo/environment/BUILD.gn b/mojo/environment/BUILD.gn
deleted file mode 100644
index d794af7..0000000
--- a/mojo/environment/BUILD.gn
+++ /dev/null
@@ -1,59 +0,0 @@
-# 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.
-
-# GYP version: mojo_base.gyp:mojo_environment_chromium
-source_set("chromium") {
-  output_name = "mojo_environment_chromium"
-
-  sources = [
-    "environment.cc",
-
-    # TODO(vtl): This is kind of ugly. (See TODO in logging.h.)
-    "//mojo/public/cpp/environment/async_waiter.h",
-    "//mojo/public/cpp/environment/lib/async_waiter.cc",
-    "//mojo/public/cpp/environment/lib/logging.cc",
-    "//mojo/public/cpp/environment/lib/scoped_task_tracking.cc",
-    "//mojo/public/cpp/environment/lib/scoped_task_tracking.h",
-    "//mojo/public/cpp/environment/logging.h",
-    "//mojo/public/cpp/environment/task_tracker.h",
-  ]
-
-  public_deps = [
-    ":chromium_impl",
-  ]
-
-  deps = [
-    "//mojo/public/c/environment",
-    "//mojo/public/cpp/bindings:callback",
-    "//mojo/public/cpp/environment",
-    "//mojo/public/cpp/system",
-  ]
-}
-
-# GYP version: mojo_base.gyp:mojo_environment_chromium_impl
-component("chromium_impl") {
-  output_name = "mojo_environment_impl"
-  visibility = [ "//mojo/*" ]
-
-  sources = [
-    "default_async_waiter_impl.cc",
-    "default_async_waiter_impl.h",
-    "default_logger_impl.cc",
-    "default_logger_impl.h",
-    "default_run_loop_impl.cc",
-    "default_run_loop_impl.h",
-    "default_task_tracker_impl.cc",
-    "default_task_tracker_impl.h",
-  ]
-
-  defines = [ "MOJO_ENVIRONMENT_IMPL_IMPLEMENTATION" ]
-
-  deps = [
-    "//base",
-    "//base/third_party/dynamic_annotations",
-    "//mojo/message_pump",
-    "//mojo/public/c/system:for_component",
-    "//mojo/public/cpp/environment:environment",
-  ]
-}
diff --git a/mojo/environment/default_async_waiter_impl.cc b/mojo/environment/default_async_waiter_impl.cc
deleted file mode 100644
index a27aa93d..0000000
--- a/mojo/environment/default_async_waiter_impl.cc
+++ /dev/null
@@ -1,51 +0,0 @@
-// 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/environment/default_async_waiter_impl.h"
-
-#include "base/bind.h"
-#include "mojo/message_pump/handle_watcher.h"
-
-namespace mojo {
-namespace internal {
-namespace {
-
-void OnHandleReady(common::HandleWatcher* watcher,
-                   MojoAsyncWaitCallback callback,
-                   void* closure,
-                   MojoResult result) {
-  delete watcher;
-  callback(closure, result);
-}
-
-MojoAsyncWaitID AsyncWait(MojoHandle handle,
-                          MojoHandleSignals signals,
-                          MojoDeadline deadline,
-                          MojoAsyncWaitCallback callback,
-                          void* closure) {
-  CHECK(handle != MOJO_HANDLE_INVALID);
-  // This instance will be deleted when done or cancelled.
-  common::HandleWatcher* watcher = new common::HandleWatcher();
-  watcher->Start(Handle(handle), signals, deadline,
-                 base::Bind(&OnHandleReady, watcher, callback, closure));
-  return reinterpret_cast<MojoAsyncWaitID>(watcher);
-}
-
-void CancelWait(MojoAsyncWaitID wait_id) {
-  delete reinterpret_cast<common::HandleWatcher*>(wait_id);
-}
-
-const MojoAsyncWaiter kDefaultAsyncWaiter = {
-  AsyncWait,
-  CancelWait
-};
-
-}  // namespace
-
-const MojoAsyncWaiter* GetDefaultAsyncWaiterImpl() {
-  return &kDefaultAsyncWaiter;
-}
-
-}  // namespace internal
-}  // namespace mojo
diff --git a/mojo/environment/default_async_waiter_impl.h b/mojo/environment/default_async_waiter_impl.h
deleted file mode 100644
index 5140e35..0000000
--- a/mojo/environment/default_async_waiter_impl.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// 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_ENVIRONMENT_DEFAULT_ASYNC_WAITER_IMPL_H_
-#define MOJO_ENVIRONMENT_DEFAULT_ASYNC_WAITER_IMPL_H_
-
-#include "mojo/environment/mojo_environment_impl_export.h"
-#include "mojo/public/c/environment/async_waiter.h"
-
-namespace mojo {
-namespace internal {
-
-MOJO_ENVIRONMENT_IMPL_EXPORT const MojoAsyncWaiter* GetDefaultAsyncWaiterImpl();
-
-}  // namespace internal
-}  // namespace mojo
-
-#endif  // MOJO_ENVIRONMENT_DEFAULT_ASYNC_WAITER_IMPL_H_
diff --git a/mojo/environment/default_logger_impl.cc b/mojo/environment/default_logger_impl.cc
deleted file mode 100644
index e1fda43b..0000000
--- a/mojo/environment/default_logger_impl.cc
+++ /dev/null
@@ -1,76 +0,0 @@
-// 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/environment/default_logger_impl.h"
-
-#include <stdint.h>
-
-#include "base/logging.h"
-#include "base/macros.h"
-
-namespace mojo {
-namespace internal {
-namespace {
-
-// We rely on log levels being the same numerically:
-static_assert(logging::LOG_VERBOSE == MOJO_LOG_LEVEL_VERBOSE,
-              "verbose log level value mismatch");
-static_assert(logging::LOG_INFO == MOJO_LOG_LEVEL_INFO,
-              "info log level value mismatch");
-static_assert(logging::LOG_WARNING == MOJO_LOG_LEVEL_WARNING,
-              "warning log level value mismatch");
-static_assert(logging::LOG_ERROR == MOJO_LOG_LEVEL_ERROR,
-              "error log level value mismatch");
-static_assert(logging::LOG_FATAL == MOJO_LOG_LEVEL_FATAL,
-              "fatal log level value mismatch");
-
-int MojoToChromiumLogLevel(MojoLogLevel log_level) {
-  // See the compile asserts above.
-  return static_cast<int>(log_level);
-}
-
-MojoLogLevel ChromiumToMojoLogLevel(int chromium_log_level) {
-  // See the compile asserts above.
-  return static_cast<MojoLogLevel>(chromium_log_level);
-}
-
-void LogMessage(MojoLogLevel log_level,
-                const char* source_file,
-                uint32_t source_line,
-                const char* message) {
-  int chromium_log_level = MojoToChromiumLogLevel(log_level);
-  int chromium_min_log_level = logging::GetMinLogLevel();
-  // "Fatal" errors aren't suppressable.
-  DCHECK_LE(chromium_min_log_level, logging::LOG_FATAL);
-  if (chromium_log_level < chromium_min_log_level)
-    return;
-
-  // TODO(vtl): Possibly, we should try to pull out the file and line number
-  // from |message|.
-  logging::LogMessage(__FILE__, __LINE__, chromium_log_level).stream()
-      << message;
-}
-
-MojoLogLevel GetMinimumLogLevel() {
-  return ChromiumToMojoLogLevel(logging::GetMinLogLevel());
-}
-
-void SetMinimumLogLevel(MojoLogLevel log_level) {
-  logging::SetMinLogLevel(MojoToChromiumLogLevel(log_level));
-}
-
-const MojoLogger kDefaultLogger = {
-  LogMessage,
-  GetMinimumLogLevel,
-  SetMinimumLogLevel
-};
-
-}  // namespace
-
-const MojoLogger* GetDefaultLoggerImpl() {
-  return &kDefaultLogger;
-}
-
-}  // namespace internal
-}  // namespace mojo
diff --git a/mojo/environment/default_logger_impl.h b/mojo/environment/default_logger_impl.h
deleted file mode 100644
index c87a727..0000000
--- a/mojo/environment/default_logger_impl.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// 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_ENVIRONMENT_DEFAULT_LOGGER_IMPL_H_
-#define MOJO_ENVIRONMENT_DEFAULT_LOGGER_IMPL_H_
-
-#include "mojo/environment/mojo_environment_impl_export.h"
-#include "mojo/public/c/environment/logger.h"
-
-namespace mojo {
-namespace internal {
-
-MOJO_ENVIRONMENT_IMPL_EXPORT const MojoLogger* GetDefaultLoggerImpl();
-
-}  // namespace internal
-}  // namespace mojo
-
-#endif  // MOJO_ENVIRONMENT_DEFAULT_LOGGER_IMPL_H_
diff --git a/mojo/environment/default_run_loop_impl.cc b/mojo/environment/default_run_loop_impl.cc
deleted file mode 100644
index 4fa9ffd..0000000
--- a/mojo/environment/default_run_loop_impl.cc
+++ /dev/null
@@ -1,27 +0,0 @@
-// 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/environment/default_run_loop_impl.h"
-
-#include "base/logging.h"
-#include "base/message_loop/message_loop.h"
-
-namespace mojo {
-namespace internal {
-
-void InstantiateDefaultRunLoopImpl() {
-  CHECK(!base::MessageLoop::current());
-  // Not leaked: accessible from |base::MessageLoop::current()|.
-  base::MessageLoop* message_loop = new base::MessageLoop();
-  CHECK_EQ(message_loop, base::MessageLoop::current());
-}
-
-void DestroyDefaultRunLoopImpl() {
-  CHECK(base::MessageLoop::current());
-  delete base::MessageLoop::current();
-  CHECK(!base::MessageLoop::current());
-}
-
-}  // namespace internal
-}  // namespace mojo
diff --git a/mojo/environment/default_run_loop_impl.h b/mojo/environment/default_run_loop_impl.h
deleted file mode 100644
index ca868bf..0000000
--- a/mojo/environment/default_run_loop_impl.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// 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_ENVIRONMENT_DEFAULT_RUN_LOOP_IMPL_H_
-#define MOJO_ENVIRONMENT_DEFAULT_RUN_LOOP_IMPL_H_
-
-#include "mojo/environment/mojo_environment_impl_export.h"
-
-namespace mojo {
-namespace internal {
-
-MOJO_ENVIRONMENT_IMPL_EXPORT void InstantiateDefaultRunLoopImpl();
-MOJO_ENVIRONMENT_IMPL_EXPORT void DestroyDefaultRunLoopImpl();
-
-}  // namespace internal
-}  // namespace mojo
-
-#endif  // MOJO_ENVIRONMENT_DEFAULT_RUN_LOOP_IMPL_H_
diff --git a/mojo/environment/default_task_tracker_impl.cc b/mojo/environment/default_task_tracker_impl.cc
deleted file mode 100644
index a53f1b9..0000000
--- a/mojo/environment/default_task_tracker_impl.cc
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2015 The Chromium Authors. 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/environment/default_task_tracker_impl.h"
-
-namespace mojo {
-namespace internal {
-namespace {
-
-TaskTrackingId StartTracking(const char* function_name,
-                             const char* file_name,
-                             int line_number,
-                             const void* program_counter) {
-  return TaskTrackingId(0);
-}
-
-void EndTracking(const TaskTrackingId id) {
-}
-
-void SetEnabled(bool enabled) {
-}
-
-const TaskTracker kDefaultTaskTracker = {&StartTracking,
-                                         &EndTracking,
-                                         &SetEnabled};
-
-}  // namespace
-
-const TaskTracker* GetDefaultTaskTracker() {
-  return &kDefaultTaskTracker;
-}
-
-}  // namespace internal
-}  // namespace mojo
diff --git a/mojo/environment/default_task_tracker_impl.h b/mojo/environment/default_task_tracker_impl.h
deleted file mode 100644
index 34d7f049d..0000000
--- a/mojo/environment/default_task_tracker_impl.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2015 The Chromium Authors. 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_ENVIRONMENT_DEFAULT_TASK_TRACKER_IMPL_H_
-#define MOJO_ENVIRONMENT_DEFAULT_TASK_TRACKER_IMPL_H_
-
-#include "mojo/environment/mojo_environment_impl_export.h"
-#include "mojo/public/cpp/environment/task_tracker.h"
-
-namespace mojo {
-namespace internal {
-
-MOJO_ENVIRONMENT_IMPL_EXPORT const TaskTracker* GetDefaultTaskTracker();
-
-}  // namespace internal
-}  // namespace mojo
-
-#endif  // MOJO_ENVIRONMENT_DEFAULT_TASK_TRACKER_IMPL_H_
diff --git a/mojo/environment/environment.cc b/mojo/environment/environment.cc
deleted file mode 100644
index 7b342e09..0000000
--- a/mojo/environment/environment.cc
+++ /dev/null
@@ -1,55 +0,0 @@
-// 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/public/cpp/environment/environment.h"
-
-#include "mojo/environment/default_async_waiter_impl.h"
-#include "mojo/environment/default_logger_impl.h"
-#include "mojo/environment/default_run_loop_impl.h"
-#include "mojo/environment/default_task_tracker_impl.h"
-
-namespace mojo {
-
-// These methods are intentionally not implemented so that there is a link
-// error if someone uses them in a Chromium-environment.
-#if 0
-Environment::Environment() {
-}
-
-Environment::Environment(const MojoAsyncWaiter* default_async_waiter,
-                         const MojoLogger* default_logger) {
-}
-
-Environment::~Environment() {
-}
-#endif
-
-// static
-const MojoAsyncWaiter* Environment::GetDefaultAsyncWaiter() {
-  return internal::GetDefaultAsyncWaiterImpl();
-}
-
-// static
-const MojoLogger* Environment::GetDefaultLogger() {
-  return internal::GetDefaultLoggerImpl();
-}
-
-// static
-const TaskTracker* Environment::GetDefaultTaskTracker() {
-  return internal::GetDefaultTaskTracker();
-}
-
-// static
-void Environment::InstantiateDefaultRunLoop() {
-  internal::InstantiateDefaultRunLoopImpl();
-}
-
-// static
-void Environment::DestroyDefaultRunLoop() {
-  internal::DestroyDefaultRunLoopImpl();
-}
-
-
-
-}  // namespace mojo
diff --git a/mojo/environment/mojo_environment_impl_export.h b/mojo/environment/mojo_environment_impl_export.h
deleted file mode 100644
index 0255425..0000000
--- a/mojo/environment/mojo_environment_impl_export.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// 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_ENVIRONMENT_MOJO_ENVIRONMENT_IMPL_EXPORT_H_
-#define MOJO_ENVIRONMENT_MOJO_ENVIRONMENT_IMPL_EXPORT_H_
-
-#if defined(COMPONENT_BUILD)
-
-#if defined(WIN32)
-
-#if defined(MOJO_ENVIRONMENT_IMPL_IMPLEMENTATION)
-#define MOJO_ENVIRONMENT_IMPL_EXPORT __declspec(dllexport)
-#else
-#define MOJO_ENVIRONMENT_IMPL_EXPORT __declspec(dllimport)
-#endif
-
-#else  // !defined(WIN32)
-
-#if defined(MOJO_ENVIRONMENT_IMPL_IMPLEMENTATION)
-#define MOJO_ENVIRONMENT_IMPL_EXPORT __attribute__((visibility("default")))
-#else
-#define MOJO_ENVIRONMENT_IMPL_EXPORT
-#endif
-
-#endif  // defined(WIN32)
-
-#else  // !defined(COMPONENT_BUILD)
-#define MOJO_ENVIRONMENT_IMPL_EXPORT
-#endif
-
-#endif  // MOJO_ENVIRONMENT_MOJO_ENVIRONMENT_IMPL_EXPORT_H_
diff --git a/mojo/gles2/BUILD.gn b/mojo/gles2/BUILD.gn
index 0bfbfec..0fb54c17 100644
--- a/mojo/gles2/BUILD.gn
+++ b/mojo/gles2/BUILD.gn
@@ -49,7 +49,6 @@
     "//gpu/command_buffer/client:gles2_implementation",
     "//gpu/command_buffer/client:gles2_interface",
     "//gpu/command_buffer/common",
-    "//mojo/environment:chromium",
     "//mojo/platform_handle:for_component",
     "//mojo/public/c/system:for_component",
     "//mojo/public/cpp/bindings",
diff --git a/mojo/mojo_base.gyp b/mojo/mojo_base.gyp
index 36c38cca..be20479a 100644
--- a/mojo/mojo_base.gyp
+++ b/mojo/mojo_base.gyp
@@ -86,7 +86,6 @@
       'dependencies': [
         '../ui/mojo/geometry/mojo_bindings.gyp:mojo_geometry_bindings',
         '../ui/gfx/gfx.gyp:gfx_geometry',
-        'mojo_environment_chromium',
         '<(mojo_system_for_component)',
       ],
       'sources': [
@@ -109,7 +108,6 @@
         'mojo_edk.gyp:mojo_system_impl',
         'mojo_edk.gyp:mojo_common_test_support',
         'mojo_edk.gyp:mojo_run_all_unittests',
-        'mojo_environment_chromium',
         'mojo_public.gyp:mojo_cpp_bindings',
         'mojo_public.gyp:mojo_message_pump_lib',
         'mojo_public.gyp:mojo_public_test_utils',
@@ -122,59 +120,6 @@
       ],
     },
     {
-      # GN version: //mojo/environment:chromium
-      'target_name': 'mojo_environment_chromium',
-      'type': 'static_library',
-      'dependencies': [
-        'mojo_environment_chromium_impl',
-        'mojo_public.gyp:mojo_cpp_bindings',
-      ],
-      'sources': [
-        # TODO(vtl): This is kind of ugly. (See TODO in logging.h.)
-        "../mojo/public/cpp/environment/async_waiter.h",
-        "../mojo/public/cpp/environment/lib/async_waiter.cc",
-        "../mojo/public/cpp/environment/lib/logging.cc",
-        "../mojo/public/cpp/environment/lib/scoped_task_tracking.cc",
-        "../mojo/public/cpp/environment/lib/scoped_task_tracking.cc",
-        "../mojo/public/cpp/environment/logging.h",
-        "../mojo/public/cpp/environment/task_tracker.h",
-        'environment/environment.cc',
-      ],
-      'include_dirs': [
-        '..',
-      ],
-      'export_dependent_settings': [
-        'mojo_environment_chromium_impl',
-      ],
-    },
-    {
-      # GN version: //mojo/environment:chromium_impl
-      'target_name': 'mojo_environment_chromium_impl',
-      'type': '<(component)',
-      'defines': [
-        'MOJO_ENVIRONMENT_IMPL_IMPLEMENTATION',
-      ],
-      'dependencies': [
-        '../base/base.gyp:base',
-        '../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
-        'mojo_public.gyp:mojo_message_pump_lib',
-        '<(mojo_system_for_component)',
-      ],
-      'sources': [
-        'environment/default_async_waiter_impl.cc',
-        'environment/default_async_waiter_impl.h',
-        'environment/default_logger_impl.cc',
-        'environment/default_logger_impl.h',
-        'environment/default_run_loop_impl.cc',
-        'environment/default_run_loop_impl.h',
-        'environment/default_task_tracker_impl.cc',
-        'environment/default_task_tracker_impl.h',
-      ],
-      'include_dirs': [
-        '..',
-      ],
-    },
-    {
       'target_name': 'mojo_application_bindings_mojom',
       'type': 'none',
       'variables': {
@@ -268,7 +213,6 @@
         'mojo_application_base',
         'mojo_edk.gyp:mojo_run_all_unittests',
         'mojo_public.gyp:mojo_utility',
-        'mojo_public.gyp:mojo_environment_standalone',
       ],
       'sources': [
         'shell/public/cpp/tests/interface_registry_unittest.cc',
@@ -342,7 +286,6 @@
             '../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
             'mojo_common_lib',
             'mojo_edk.gyp:mojo_system_impl',
-            'mojo_environment_chromium',
             'mojo_jni_headers',
             'mojo_public.gyp:mojo_message_pump_lib',
           ],
diff --git a/mojo/mojo_edk_tests.gyp b/mojo/mojo_edk_tests.gyp
index e2f92129..82c1d04 100644
--- a/mojo/mojo_edk_tests.gyp
+++ b/mojo/mojo_edk_tests.gyp
@@ -19,7 +19,6 @@
         'mojo_message_pipe_perftests',
         'mojo_public_bindings_perftests',
         'mojo_public_bindings_unittests',
-        'mojo_public_environment_unittests',
         'mojo_public_system_perftests',
         'mojo_public_system_unittests',
         'mojo_public_utility_unittests',
@@ -47,7 +46,6 @@
       'type': 'executable',
       'dependencies': [
         '../testing/gtest.gyp:gtest',
-        'mojo_base.gyp:mojo_environment_chromium',
         'mojo_edk.gyp:mojo_run_all_unittests',
         'mojo_public.gyp:mojo_cpp_bindings',
         'mojo_public.gyp:mojo_message_pump_lib',
@@ -113,7 +111,6 @@
         'mojo_base.gyp:mojo_common_lib',
         'mojo_edk.gyp:mojo_run_all_perftests',
         'mojo_public.gyp:mojo_cpp_bindings',
-        'mojo_public.gyp:mojo_environment_standalone',
         'mojo_public.gyp:mojo_message_pump_lib',
         'mojo_public.gyp:mojo_public_bindings_test_utils',
         'mojo_public.gyp:mojo_public_test_interfaces',
@@ -126,25 +123,6 @@
       ],
     },
     {
-      # GN version: //mojo/edk/test:mojo_public_environment_unittests
-      'target_name': 'mojo_public_environment_unittests',
-      'type': 'executable',
-      'dependencies': [
-        '../testing/gtest.gyp:gtest',
-        'mojo_edk.gyp:mojo_run_all_unittests',
-        'mojo_public.gyp:mojo_cpp_bindings',
-        'mojo_public.gyp:mojo_environment_standalone',
-        'mojo_public.gyp:mojo_public_test_utils',
-        'mojo_public.gyp:mojo_utility',
-      ],
-      'sources': [
-        'public/cpp/environment/tests/async_wait_unittest.cc',
-        'public/cpp/environment/tests/async_waiter_unittest.cc',
-        'public/cpp/environment/tests/logger_unittest.cc',
-        'public/cpp/environment/tests/logging_unittest.cc',
-      ],
-    },
-    {
       # GN version: //mojo/public/cpp/system/tests:mojo_public_system_unittests
       # and         //mojo/public/c/system/tests
       'target_name': 'mojo_public_system_unittests',
@@ -269,7 +247,6 @@
         'mojo_edk.gyp:mojo_common_test_support',
         'mojo_edk.gyp:mojo_run_all_unittests',
         'mojo_edk.gyp:mojo_js_lib',
-        'mojo_public.gyp:mojo_environment_standalone',
         'mojo_public.gyp:mojo_public_test_interfaces',
         'mojo_public.gyp:mojo_utility',
       ],
@@ -289,7 +266,6 @@
         'mojo_edk.gyp:mojo_js_lib',
         'mojo_edk.gyp:mojo_run_all_unittests',
         'mojo_js_to_cpp_bindings',
-        'mojo_public.gyp:mojo_environment_standalone',
         'mojo_public.gyp:mojo_public_test_interfaces',
         'mojo_public.gyp:mojo_utility',
       ],
@@ -326,19 +302,6 @@
           ],
         },
         {
-          'target_name': 'mojo_public_environment_unittests_run',
-          'type': 'none',
-          'dependencies': [
-            'mojo_public_environment_unittests',
-          ],
-          'includes': [
-            '../build/isolate.gypi',
-          ],
-          'sources': [
-            'mojo_public_environment_unittests.isolate',
-          ],
-        },
-        {
           'target_name': 'mojo_public_system_unittests_run',
           'type': 'none',
           'dependencies': [
diff --git a/mojo/mojo_public.gyp b/mojo/mojo_public.gyp
index b9c5b8b4..e72ce0b 100644
--- a/mojo/mojo_public.gyp
+++ b/mojo/mojo_public.gyp
@@ -232,33 +232,6 @@
       ],
     },
     {
-      # GN version: //mojo/public/cpp/environment:standalone
-      'target_name': 'mojo_environment_standalone',
-      'type': 'static_library',
-      'sources': [
-        'public/c/environment/async_waiter.h',
-        'public/c/environment/logger.h',
-        'public/cpp/environment/async_waiter.h',
-        'public/cpp/environment/environment.h',
-        'public/cpp/environment/lib/async_waiter.cc',
-        'public/cpp/environment/lib/default_async_waiter.cc',
-        'public/cpp/environment/lib/default_async_waiter.h',
-        'public/cpp/environment/lib/default_logger.cc',
-        'public/cpp/environment/lib/default_logger.h',
-        'public/cpp/environment/lib/default_task_tracker.cc',
-        'public/cpp/environment/lib/default_task_tracker.h',
-        'public/cpp/environment/lib/environment.cc',
-        'public/cpp/environment/lib/logging.cc',
-        'public/cpp/environment/lib/scoped_task_tracking.cc',
-        'public/cpp/environment/lib/scoped_task_tracking.h',
-        'public/cpp/environment/logging.h',
-        'public/cpp/environment/task_tracker.h',
-      ],
-      'include_dirs': [
-        '..',
-      ],
-    },
-    {
       # GN version: //mojo/public/cpp/utility
       'target_name': 'mojo_utility',
       'type': 'static_library',
diff --git a/mojo/mojo_public_environment_unittests.isolate b/mojo/mojo_public_environment_unittests.isolate
deleted file mode 100644
index d4922718..0000000
--- a/mojo/mojo_public_environment_unittests.isolate
+++ /dev/null
@@ -1,44 +0,0 @@
-# Copyright 2015 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-{
-  'includes': [
-    '../base/base.isolate',
-  ],
-  'conditions': [
-    ['OS=="win" or OS=="mac" or OS=="linux"', {
-      'variables': {
-        'command': [
-          '../testing/test_env.py',
-          '<(PRODUCT_DIR)/mojo_public_environment_unittests<(EXECUTABLE_SUFFIX)',
-          '--brave-new-test-launcher',
-          '--test-launcher-bot-mode',
-        ],
-        'files': [
-          '../testing/test_env.py',
-        ],
-      },
-    }],
-    ['OS=="win"', {
-      'variables': {
-        'files': [
-          '<(PRODUCT_DIR)/mojo_public_test_support.dll',
-        ],
-      },
-    }],
-    ['OS=="linux"', {
-      'variables': {
-        'files': [
-          '<(PRODUCT_DIR)/lib/libmojo_public_test_support.so',
-        ],
-      },
-    }],
-    ['OS=="mac"', {
-      'variables': {
-        'files': [
-          '<(PRODUCT_DIR)/libmojo_public_test_support.dylib',
-        ],
-      },
-    }],
-  ],
-}
diff --git a/mojo/mojo_shell.gyp b/mojo/mojo_shell.gyp
index 192c8ac5..7ed1d6ec 100644
--- a/mojo/mojo_shell.gyp
+++ b/mojo/mojo_shell.gyp
@@ -31,7 +31,6 @@
       '<(DEPTH)/mojo/mojo_base.gyp:mojo_application_base',
       '<(DEPTH)/mojo/mojo_base.gyp:mojo_application_bindings',
       '<(DEPTH)/mojo/mojo_base.gyp:mojo_common_lib',
-      '<(DEPTH)/mojo/mojo_base.gyp:mojo_environment_chromium',
       '<(DEPTH)/mojo/mojo_base.gyp:mojo_url_type_converters',
       '<(DEPTH)/net/net.gyp:net',
       '<(DEPTH)/url/url.gyp:url_lib',
@@ -48,7 +47,6 @@
       '<(DEPTH)/base/base.gyp:base',
       '<(DEPTH)/mojo/mojo_base.gyp:mojo_application_base',
       '<(DEPTH)/mojo/mojo_base.gyp:mojo_common_lib',
-      '<(DEPTH)/mojo/mojo_base.gyp:mojo_environment_chromium',
       '<(DEPTH)/mojo/mojo_base.gyp:mojo_url_type_converters',
       '<(DEPTH)/mojo/mojo_edk.gyp:mojo_run_all_unittests',
       '<(DEPTH)/mojo/mojo_public.gyp:mojo_cpp_bindings',
diff --git a/mojo/public/BUILD.gn b/mojo/public/BUILD.gn
index f87fb94..cbe8c7e 100644
--- a/mojo/public/BUILD.gn
+++ b/mojo/public/BUILD.gn
@@ -8,7 +8,6 @@
   deps = [
     ":sdk",
     "cpp/bindings",
-    "cpp/environment:standalone",
     "cpp/utility",
     "interfaces/bindings/tests:test_interfaces",
   ]
@@ -25,7 +24,6 @@
   deps = [
     "c/system",
     "cpp/bindings",
-    "cpp/environment:standalone",
     "cpp/utility",
     "interfaces/bindings",
     "js",
diff --git a/mojo/public/c/README.md b/mojo/public/c/README.md
index 8e11545..c02dac625 100644
--- a/mojo/public/c/README.md
+++ b/mojo/public/c/README.md
@@ -3,18 +3,11 @@
 
 This directory contains C language bindings for the Mojo Public API.
 
-Environment
------------
-
-The environment/ subdirectory defines some common things that, while not part of
-the system API, may be required for GLES2 (for example). These are things that a
-Mojo application may be required to provide to the GLES2 (for example) library
-in order to use it. (However, the Mojo application may implement these things as
-it sees fit.)
-
 GLES2
 -----
 
+TODO(yzshen): move GLES2 to where it belongs (likely components/mus).
+
 The gles2/ subdirectory defines the GLES2 C API that's available to Mojo
 applications. To use GLES2, Mojo applications must link against a dynamic
 library (the exact mechanism being platform-dependent) and use the header files
diff --git a/mojo/public/c/environment/BUILD.gn b/mojo/public/c/environment/BUILD.gn
deleted file mode 100644
index 26e8256..0000000
--- a/mojo/public/c/environment/BUILD.gn
+++ /dev/null
@@ -1,14 +0,0 @@
-# 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.
-
-source_set("environment") {
-  sources = [
-    "async_waiter.h",
-    "logger.h",
-  ]
-
-  deps = [
-    "//mojo/public/c/system",
-  ]
-}
diff --git a/mojo/public/c/environment/async_waiter.h b/mojo/public/c/environment/async_waiter.h
deleted file mode 100644
index 1eb06317..0000000
--- a/mojo/public/c/environment/async_waiter.h
+++ /dev/null
@@ -1,30 +0,0 @@
-// 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_PUBLIC_C_ENVIRONMENT_ASYNC_WAITER_H_
-#define MOJO_PUBLIC_C_ENVIRONMENT_ASYNC_WAITER_H_
-
-#include "mojo/public/c/system/types.h"
-
-typedef uintptr_t MojoAsyncWaitID;
-
-typedef void (*MojoAsyncWaitCallback)(void* closure, MojoResult result);
-
-struct MojoAsyncWaiter {
-  // Asynchronously call MojoWait on a background thread, and pass the result
-  // of MojoWait to the given MojoAsyncWaitCallback on the current thread.
-  // Returns a non-zero MojoAsyncWaitID that can be used with CancelWait to
-  // stop waiting. This identifier becomes invalid once the callback runs.
-  MojoAsyncWaitID (*AsyncWait)(MojoHandle handle,
-                               MojoHandleSignals signals,
-                               MojoDeadline deadline,
-                               MojoAsyncWaitCallback callback,
-                               void* closure);
-
-  // Cancel an existing call to AsyncWait with the given MojoAsyncWaitID. The
-  // corresponding MojoAsyncWaitCallback will not be called in this case.
-  void (*CancelWait)(MojoAsyncWaitID wait_id);
-};
-
-#endif  // MOJO_PUBLIC_C_ENVIRONMENT_ASYNC_WAITER_H_
diff --git a/mojo/public/c/environment/logger.h b/mojo/public/c/environment/logger.h
deleted file mode 100644
index 2a9b617..0000000
--- a/mojo/public/c/environment/logger.h
+++ /dev/null
@@ -1,61 +0,0 @@
-// 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_PUBLIC_C_ENVIRONMENT_LOGGER_H_
-#define MOJO_PUBLIC_C_ENVIRONMENT_LOGGER_H_
-
-#include <stdint.h>
-
-// |MojoLogLevel|: Used to specify the type of log message. Values are ordered
-// by severity (i.e., higher numerical values are more severe).
-
-typedef int32_t MojoLogLevel;
-
-#ifdef __cplusplus
-const MojoLogLevel MOJO_LOG_LEVEL_VERBOSE = -1;
-const MojoLogLevel MOJO_LOG_LEVEL_INFO = 0;
-const MojoLogLevel MOJO_LOG_LEVEL_WARNING = 1;
-const MojoLogLevel MOJO_LOG_LEVEL_ERROR = 2;
-const MojoLogLevel MOJO_LOG_LEVEL_FATAL = 3;
-#else
-#define MOJO_LOG_LEVEL_VERBOSE ((MojoLogLevel) - 1)
-#define MOJO_LOG_LEVEL_INFO ((MojoLogLevel)0)
-#define MOJO_LOG_LEVEL_WARNING ((MojoLogLevel)1)
-#define MOJO_LOG_LEVEL_ERROR ((MojoLogLevel)2)
-#define MOJO_LOG_LEVEL_FATAL ((MojoLogLevel)3)
-#endif
-
-// Structure with basic logging functions (on top of which more friendly logging
-// macros may be built). The functions are thread-safe, except for
-// |SetMinimumLogLevel()| (see below).
-struct MojoLogger {
-  // Logs |message| (which must not be null) at level |log_level| if |log_level|
-  // is at least the current minimum log level. If |log_level| is
-  // |MOJO_LOG_LEVEL_FATAL| (or greater), aborts the application/process.
-  // |source_file| and |source_line| indicate the source file and (1-based) line
-  // number, respectively; they are optional: |source_file| may be null and
-  // |source_line| may be zero (if |source_file| is null, then |source_line| may
-  // be ignored).
-  void (*LogMessage)(MojoLogLevel log_level,
-                     const char* source_file,
-                     uint32_t source_line,
-                     const char* message);
-
-  // Gets the minimum log level (see above), which will always be at most
-  // |MOJO_LOG_LEVEL_FATAL|. (Though |LogMessage()| will automatically avoid
-  // logging messages below the minimum log level, this may be used to avoid
-  // extra work.)
-  MojoLogLevel (*GetMinimumLogLevel)(void);
-
-  // Sets the minimum log level (see above) to the lesser of |minimum_log_level|
-  // and |MOJO_LOG_LEVEL_FATAL|.
-  //
-  // Warning: This function may not be thread-safe, and should not be called
-  // concurrently with other |MojoLogger| functions. (In some environments --
-  // such as Chromium -- that share a logger across applications, this may mean
-  // that it is almost never safe to call this.)
-  void (*SetMinimumLogLevel)(MojoLogLevel minimum_log_level);
-};
-
-#endif  // MOJO_PUBLIC_C_ENVIRONMENT_LOGGER_H_
diff --git a/mojo/public/c/gles2/BUILD.gn b/mojo/public/c/gles2/BUILD.gn
index a009d00..538b3058 100644
--- a/mojo/public/c/gles2/BUILD.gn
+++ b/mojo/public/c/gles2/BUILD.gn
@@ -19,7 +19,6 @@
   public_configs = [ ":gles2_config" ]
 
   public_deps = [
-    "//mojo/public/c/environment",
     "//mojo/public/c/system",
   ]
 }
diff --git a/mojo/public/c/system/tests/BUILD.gn b/mojo/public/c/system/tests/BUILD.gn
index 9f55259..5d852adb 100644
--- a/mojo/public/c/system/tests/BUILD.gn
+++ b/mojo/public/c/system/tests/BUILD.gn
@@ -17,7 +17,6 @@
   ]
 
   deps = [
-    "//mojo/public/c/environment",
     "//mojo/public/c/system",
     "//testing/gtest",
   ]
@@ -31,8 +30,6 @@
   ]
 
   deps = [
-    "//mojo/public/c/environment",
-    "//mojo/public/cpp/environment:standalone",
     "//mojo/public/cpp/system",
     "//mojo/public/cpp/test_support:test_utils",
     "//mojo/public/cpp/utility",
diff --git a/mojo/public/c/system/tests/core_unittest_pure_c.c b/mojo/public/c/system/tests/core_unittest_pure_c.c
index 3c0d98eb..a01e14b 100644
--- a/mojo/public/c/system/tests/core_unittest_pure_c.c
+++ b/mojo/public/c/system/tests/core_unittest_pure_c.c
@@ -12,7 +12,6 @@
 
 // Include all the header files that are meant to be compilable as C. Start with
 // core.h, since it's the most important one.
-#include "mojo/public/c/environment/async_waiter.h"
 #include "mojo/public/c/system/core.h"
 #include "mojo/public/c/system/macros.h"
 
diff --git a/mojo/public/cpp/README.md b/mojo/public/cpp/README.md
index 4404c24..fbbf86cf 100644
--- a/mojo/public/cpp/README.md
+++ b/mojo/public/cpp/README.md
@@ -23,31 +23,6 @@
 which translates Mojo IDL (.mojom) files into idiomatic C++ (among other
 languages).
 
-This library depends on the Environment library.
-
-Environment
------------
-
-The environment/ subdirectory contains a support (static) library that
-represents shared state needed to support the Bindings and GLES2 libraries.
-
-This library depends on the Utility library.
-
-
-GLES2
------
-
-The gles2/ subdirectory contains C++ wrappers (and some additional helpers) of
-the API defined in mojo/public/c/gles2/ (which provides access to GLES2).
-
-These wrappers depend on the Environment library.
-
-Shell
------
-
-The shell/ subdirectory contains a support (static) library that aids in writing
-Mojo applications and interacting with the Shell service.
-
 System
 ------
 
@@ -65,6 +40,8 @@
 Utility
 -------
 
+TODO(yzshen): remove.
+
 The utility/ subdirectory contains a support (static) library that provides
 various basic functionality. Most notably, it provides an implementation of a
 RunLoop based on MojoWaitMany() that applications may use as the basis for
diff --git a/mojo/public/cpp/bindings/tests/BUILD.gn b/mojo/public/cpp/bindings/tests/BUILD.gn
index 5c661b4..fb058ce 100644
--- a/mojo/public/cpp/bindings/tests/BUILD.gn
+++ b/mojo/public/cpp/bindings/tests/BUILD.gn
@@ -52,7 +52,6 @@
 
   deps = [
     ":mojo_public_bindings_test_utils",
-    "//mojo/environment:chromium",
     "//mojo/message_pump",
     "//mojo/public/cpp/bindings",
     "//mojo/public/cpp/bindings:callback",
@@ -83,7 +82,6 @@
     "//mojo/message_pump",
     "//mojo/public/cpp/bindings",
     "//mojo/public/cpp/bindings:callback",
-    "//mojo/public/cpp/environment:standalone",
     "//mojo/public/cpp/system",
     "//mojo/public/cpp/test_support:test_utils",
     "//mojo/public/cpp/utility",
diff --git a/mojo/public/cpp/environment/BUILD.gn b/mojo/public/cpp/environment/BUILD.gn
deleted file mode 100644
index e2dfc91..0000000
--- a/mojo/public/cpp/environment/BUILD.gn
+++ /dev/null
@@ -1,47 +0,0 @@
-# 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.
-
-source_set("environment") {
-  sources = [
-    "async_waiter.h",
-    "environment.h",
-    "logging.h",
-    "task_tracker.h",
-  ]
-
-  public_deps = [
-    "//mojo/public/c/environment",
-  ]
-
-  deps = [
-    "//mojo/public/cpp/bindings:callback",
-    "//mojo/public/cpp/system",
-  ]
-}
-
-source_set("standalone") {
-  sources = [
-    "lib/async_waiter.cc",
-    "lib/default_async_waiter.cc",
-    "lib/default_async_waiter.h",
-    "lib/default_logger.cc",
-    "lib/default_logger.h",
-    "lib/default_task_tracker.cc",
-    "lib/default_task_tracker.h",
-    "lib/environment.cc",
-    "lib/logging.cc",
-    "lib/scoped_task_tracking.cc",
-    "lib/scoped_task_tracking.h",
-  ]
-
-  public_deps = [
-    ":environment",
-  ]
-
-  deps = [
-    "//mojo/public/c/environment",
-    "//mojo/public/cpp/system",
-    "//mojo/public/cpp/utility",
-  ]
-}
diff --git a/mojo/public/cpp/environment/async_waiter.h b/mojo/public/cpp/environment/async_waiter.h
deleted file mode 100644
index afb4ad15..0000000
--- a/mojo/public/cpp/environment/async_waiter.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// 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_PUBLIC_CPP_ENVIRONMENT_ASYNC_WAITER_H_
-#define MOJO_PUBLIC_CPP_ENVIRONMENT_ASYNC_WAITER_H_
-
-#include "mojo/public/c/environment/async_waiter.h"
-#include "mojo/public/cpp/bindings/callback.h"
-#include "mojo/public/cpp/environment/environment.h"
-#include "mojo/public/cpp/system/handle.h"
-
-namespace mojo {
-
-// A class that waits until a handle is ready and calls |callback| with the
-// result. If the AsyncWaiter is deleted before the handle is ready, the wait is
-// cancelled and the callback will not be called.
-class AsyncWaiter {
- public:
-  typedef mojo::Callback<void(MojoResult)> Callback;
-
-  AsyncWaiter(Handle handle,
-              MojoHandleSignals signals,
-              const Callback& callback);
-  ~AsyncWaiter();
-
- private:
-  static void WaitComplete(void* waiter, MojoResult result);
-  void WaitCompleteInternal(MojoResult result);
-
-  const MojoAsyncWaiter* waiter_;
-  MojoAsyncWaitID id_;
-  const Callback callback_;
-
-  DISALLOW_COPY_AND_ASSIGN(AsyncWaiter);
-};
-
-}  // namespace mojo
-
-#endif  // MOJO_PUBLIC_CPP_ENVIRONMENT_ASYNC_WAITER_H_
diff --git a/mojo/public/cpp/environment/environment.h b/mojo/public/cpp/environment/environment.h
deleted file mode 100644
index 4cfb963c..0000000
--- a/mojo/public/cpp/environment/environment.h
+++ /dev/null
@@ -1,53 +0,0 @@
-// 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_PUBLIC_CPP_ENVIRONMENT_ENVIRONMENT_H_
-#define MOJO_PUBLIC_CPP_ENVIRONMENT_ENVIRONMENT_H_
-
-#include "base/macros.h"
-
-struct MojoAsyncWaiter;
-struct MojoLogger;
-
-namespace mojo {
-
-struct TaskTracker;
-
-// Other parts of the Mojo C++ APIs use the *static* methods of this class.
-//
-// The "standalone" implementation of this class requires that this class (in
-// the lib/ subdirectory) be instantiated (and remain so) while using the Mojo
-// C++ APIs. I.e., the static methods depend on things set up by the constructor
-// and torn down by the destructor.
-//
-// Other implementations may not have this requirement.
-class Environment {
- public:
-  Environment();
-  // This constructor allows the standard implementations to be overridden (set
-  // a parameter to null to get the standard implementation).
-  Environment(const MojoAsyncWaiter* default_async_waiter,
-              const MojoLogger* default_logger,
-              const TaskTracker* default_task_tracker);
-  ~Environment();
-
-  static const MojoAsyncWaiter* GetDefaultAsyncWaiter();
-  static const MojoLogger* GetDefaultLogger();
-  static const TaskTracker* GetDefaultTaskTracker();
-
-  // These instantiate and destroy an environment-specific run loop for the
-  // current thread, allowing |GetDefaultAsyncWaiter()| to be used. (The run
-  // loop itself should be accessible via thread-local storage, using methods
-  // specific to the run loop implementation.) Creating and destroying nested
-  // run loops is not supported.
-  static void InstantiateDefaultRunLoop();
-  static void DestroyDefaultRunLoop();
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(Environment);
-};
-
-}  // namespace mojo
-
-#endif  // MOJO_PUBLIC_CPP_ENVIRONMENT_ENVIRONMENT_H_
diff --git a/mojo/public/cpp/environment/lib/async_waiter.cc b/mojo/public/cpp/environment/lib/async_waiter.cc
deleted file mode 100644
index 599a649..0000000
--- a/mojo/public/cpp/environment/lib/async_waiter.cc
+++ /dev/null
@@ -1,34 +0,0 @@
-// 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/public/cpp/environment/async_waiter.h"
-
-namespace mojo {
-
-AsyncWaiter::AsyncWaiter(Handle handle,
-                         MojoHandleSignals signals,
-                         const Callback& callback)
-    : waiter_(Environment::GetDefaultAsyncWaiter()),
-      id_(0),
-      callback_(callback) {
-  id_ = waiter_->AsyncWait(handle.value(), signals, MOJO_DEADLINE_INDEFINITE,
-                           &AsyncWaiter::WaitComplete, this);
-}
-
-AsyncWaiter::~AsyncWaiter() {
-  if (id_)
-    waiter_->CancelWait(id_);
-}
-
-// static
-void AsyncWaiter::WaitComplete(void* waiter, MojoResult result) {
-  static_cast<AsyncWaiter*>(waiter)->WaitCompleteInternal(result);
-}
-
-void AsyncWaiter::WaitCompleteInternal(MojoResult result) {
-  id_ = 0;
-  callback_.Run(result);
-}
-
-}  // namespace mojo
diff --git a/mojo/public/cpp/environment/lib/default_async_waiter.cc b/mojo/public/cpp/environment/lib/default_async_waiter.cc
deleted file mode 100644
index 9d9b07e..0000000
--- a/mojo/public/cpp/environment/lib/default_async_waiter.cc
+++ /dev/null
@@ -1,85 +0,0 @@
-// 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/public/cpp/environment/lib/default_async_waiter.h"
-
-#include <assert.h>
-
-#include "mojo/public/c/environment/async_waiter.h"
-#include "mojo/public/cpp/utility/run_loop.h"
-#include "mojo/public/cpp/utility/run_loop_handler.h"
-
-namespace mojo {
-
-namespace {
-
-// RunLoopHandler implementation used for a request to AsyncWait(). There are
-// two ways RunLoopHandlerImpl is deleted:
-// . when the handle is ready (or errored).
-// . when CancelWait() is invoked.
-class RunLoopHandlerImpl : public RunLoopHandler {
- public:
-  RunLoopHandlerImpl(const Handle& handle,
-                     MojoAsyncWaitCallback callback,
-                     void* closure)
-      : handle_(handle), callback_(callback), closure_(closure) {}
-
-  ~RunLoopHandlerImpl() override { RunLoop::current()->RemoveHandler(handle_); }
-
-  // RunLoopHandler:
-  void OnHandleReady(const Handle& handle) override {
-    NotifyCallback(MOJO_RESULT_OK);
-  }
-
-  void OnHandleError(const Handle& handle, MojoResult result) override {
-    NotifyCallback(result);
-  }
-
- private:
-  void NotifyCallback(MojoResult result) {
-    // Delete this to unregister the handle. That way if the callback
-    // reregisters everything is ok.
-    MojoAsyncWaitCallback callback = callback_;
-    void* closure = closure_;
-    delete this;
-
-    callback(closure, result);
-  }
-
-  const Handle handle_;
-  MojoAsyncWaitCallback callback_;
-  void* closure_;
-
-  DISALLOW_COPY_AND_ASSIGN(RunLoopHandlerImpl);
-};
-
-MojoAsyncWaitID AsyncWait(MojoHandle handle,
-                          MojoHandleSignals signals,
-                          MojoDeadline deadline,
-                          MojoAsyncWaitCallback callback,
-                          void* closure) {
-  RunLoop* run_loop = RunLoop::current();
-  assert(run_loop);
-
-  // |run_loop_handler| is destroyed either when the handle is ready or if
-  // CancelWait is invoked.
-  RunLoopHandlerImpl* run_loop_handler =
-      new RunLoopHandlerImpl(Handle(handle), callback, closure);
-  run_loop->AddHandler(run_loop_handler, Handle(handle), signals, deadline);
-  return reinterpret_cast<MojoAsyncWaitID>(run_loop_handler);
-}
-
-void CancelWait(MojoAsyncWaitID wait_id) {
-  delete reinterpret_cast<RunLoopHandlerImpl*>(wait_id);
-}
-
-}  // namespace
-
-namespace internal {
-
-const MojoAsyncWaiter kDefaultAsyncWaiter = {AsyncWait, CancelWait};
-
-}  // namespace internal
-
-}  // namespace mojo
diff --git a/mojo/public/cpp/environment/lib/default_async_waiter.h b/mojo/public/cpp/environment/lib/default_async_waiter.h
deleted file mode 100644
index 49ce233..0000000
--- a/mojo/public/cpp/environment/lib/default_async_waiter.h
+++ /dev/null
@@ -1,18 +0,0 @@
-// 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_PUBLIC_CPP_ENVIRONMENT_LIB_DEFAULT_ASYNC_WAITER_H_
-#define MOJO_PUBLIC_CPP_ENVIRONMENT_LIB_DEFAULT_ASYNC_WAITER_H_
-
-struct MojoAsyncWaiter;
-
-namespace mojo {
-namespace internal {
-
-extern const MojoAsyncWaiter kDefaultAsyncWaiter;
-
-}  // namespace internal
-}  // namespace mojo
-
-#endif  // MOJO_PUBLIC_CPP_ENVIRONMENT_LIB_DEFAULT_ASYNC_WAITER_H_
diff --git a/mojo/public/cpp/environment/lib/default_logger.cc b/mojo/public/cpp/environment/lib/default_logger.cc
deleted file mode 100644
index 62a7318a..0000000
--- a/mojo/public/cpp/environment/lib/default_logger.cc
+++ /dev/null
@@ -1,78 +0,0 @@
-// 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/public/cpp/environment/lib/default_logger.h"
-
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>  // For |abort()|.
-
-#include <algorithm>
-
-#include "mojo/public/c/environment/logger.h"
-
-namespace mojo {
-
-namespace {
-
-MojoLogLevel g_minimum_log_level = MOJO_LOG_LEVEL_INFO;
-
-const char* GetLogLevelString(MojoLogLevel log_level) {
-  if (log_level <= MOJO_LOG_LEVEL_VERBOSE - 3)
-    return "VERBOSE4+";
-  switch (log_level) {
-    case MOJO_LOG_LEVEL_VERBOSE - 2:
-      return "VERBOSE3";
-    case MOJO_LOG_LEVEL_VERBOSE - 1:
-      return "VERBOSE2";
-    case MOJO_LOG_LEVEL_VERBOSE:
-      return "VERBOSE1";
-    case MOJO_LOG_LEVEL_INFO:
-      return "INFO";
-    case MOJO_LOG_LEVEL_WARNING:
-      return "WARNING";
-    case MOJO_LOG_LEVEL_ERROR:
-      return "ERROR";
-  }
-  // Consider everything higher to be fatal.
-  return "FATAL";
-}
-
-void LogMessage(MojoLogLevel log_level,
-                const char* source_file,
-                uint32_t source_line,
-                const char* message) {
-  if (log_level < g_minimum_log_level)
-    return;
-
-  // TODO(vtl): Add timestamp also?
-  if (source_file) {
-    fprintf(stderr, "%s: %s(%u): %s\n", GetLogLevelString(log_level),
-            source_file, static_cast<unsigned>(source_line), message);
-  } else {
-    fprintf(stderr, "%s: %s\n", GetLogLevelString(log_level), message);
-  }
-  if (log_level >= MOJO_LOG_LEVEL_FATAL)
-    abort();
-}
-
-MojoLogLevel GetMinimumLogLevel() {
-  return g_minimum_log_level;
-}
-
-void SetMinimumLogLevel(MojoLogLevel minimum_log_level) {
-  g_minimum_log_level = std::min(minimum_log_level, MOJO_LOG_LEVEL_FATAL);
-}
-
-}  // namespace
-
-namespace internal {
-
-const MojoLogger kDefaultLogger = {LogMessage,
-                                   GetMinimumLogLevel,
-                                   SetMinimumLogLevel};
-
-}  // namespace internal
-
-}  // namespace mojo
diff --git a/mojo/public/cpp/environment/lib/default_logger.h b/mojo/public/cpp/environment/lib/default_logger.h
deleted file mode 100644
index 4db32336..0000000
--- a/mojo/public/cpp/environment/lib/default_logger.h
+++ /dev/null
@@ -1,18 +0,0 @@
-// 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_PUBLIC_CPP_ENVIRONMENT_LIB_DEFAULT_LOGGER_H_
-#define MOJO_PUBLIC_CPP_ENVIRONMENT_LIB_DEFAULT_LOGGER_H_
-
-struct MojoLogger;
-
-namespace mojo {
-namespace internal {
-
-extern const MojoLogger kDefaultLogger;
-
-}  // namespace internal
-}  // namespace mojo
-
-#endif  // MOJO_PUBLIC_CPP_ENVIRONMENT_LIB_DEFAULT_LOGGER_H_
diff --git a/mojo/public/cpp/environment/lib/default_task_tracker.cc b/mojo/public/cpp/environment/lib/default_task_tracker.cc
deleted file mode 100644
index a99f1c7..0000000
--- a/mojo/public/cpp/environment/lib/default_task_tracker.cc
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2015 The Chromium Authors. 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/public/cpp/environment/lib/default_task_tracker.h"
-
-#include "mojo/public/cpp/environment/task_tracker.h"
-
-namespace mojo {
-
-namespace {
-
-//
-// The standalone task tracker does nothing.
-//
-
-TaskTrackingId StartTracking(const char* function_name,
-                             const char* file_name,
-                             int line_number,
-                             const void* program_counter) {
-  return TaskTrackingId(0);
-}
-
-void EndTracking(const TaskTrackingId id) {
-}
-
-void SetEnabled(bool enabled) {
-}
-
-}  // namespace
-
-namespace internal {
-
-const TaskTracker kDefaultTaskTracker = {&StartTracking,
-                                         &EndTracking,
-                                         &SetEnabled};
-
-}  // namespace internal
-
-}  // namespace mojo
diff --git a/mojo/public/cpp/environment/lib/default_task_tracker.h b/mojo/public/cpp/environment/lib/default_task_tracker.h
deleted file mode 100644
index 7a0c0647..0000000
--- a/mojo/public/cpp/environment/lib/default_task_tracker.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2015 The Chromium Authors. 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_PUBLIC_CPP_ENVIRONMENT_LIB_DEFAULT_TASK_TRACKER_H_
-#define MOJO_PUBLIC_CPP_ENVIRONMENT_LIB_DEFAULT_TASK_TRACKER_H_
-
-namespace mojo {
-
-struct TaskTracker;
-
-namespace internal {
-
-extern const TaskTracker kDefaultTaskTracker;
-
-}  // namespace internal
-}  // namespace mojo
-
-#endif  // MOJO_PUBLIC_CPP_ENVIRONMENT_LIB_DEFAULT_TASK_TRACKER_H_
diff --git a/mojo/public/cpp/environment/lib/environment.cc b/mojo/public/cpp/environment/lib/environment.cc
deleted file mode 100644
index 0b0addd..0000000
--- a/mojo/public/cpp/environment/lib/environment.cc
+++ /dev/null
@@ -1,93 +0,0 @@
-// 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/public/cpp/environment/environment.h"
-
-#include <assert.h>
-
-#include "mojo/public/c/environment/logger.h"
-#include "mojo/public/cpp/environment/lib/default_async_waiter.h"
-#include "mojo/public/cpp/environment/lib/default_logger.h"
-#include "mojo/public/cpp/environment/lib/default_task_tracker.h"
-#include "mojo/public/cpp/utility/run_loop.h"
-
-namespace mojo {
-
-namespace {
-
-const MojoAsyncWaiter* g_default_async_waiter = nullptr;
-const MojoLogger* g_default_logger = nullptr;
-const TaskTracker* g_default_task_tracker = nullptr;
-
-void Init(const MojoAsyncWaiter* default_async_waiter,
-          const MojoLogger* default_logger,
-          const TaskTracker* default_task_tracker) {
-  g_default_async_waiter = default_async_waiter
-                               ? default_async_waiter
-                               : &internal::kDefaultAsyncWaiter;
-  g_default_logger =
-      default_logger ? default_logger : &internal::kDefaultLogger;
-
-  g_default_task_tracker = default_task_tracker
-                               ? default_task_tracker
-                               : &internal::kDefaultTaskTracker;
-
-  RunLoop::SetUp();
-}
-
-}  // namespace
-
-Environment::Environment() {
-  Init(nullptr, nullptr, nullptr);
-}
-
-Environment::Environment(const MojoAsyncWaiter* default_async_waiter,
-                         const MojoLogger* default_logger,
-                         const TaskTracker* default_task_tracker) {
-  Init(default_async_waiter, default_logger, default_task_tracker);
-}
-
-Environment::~Environment() {
-  RunLoop::TearDown();
-
-  // TODO(vtl): Maybe we should allow nesting, and restore previous default
-  // async waiters and loggers?
-  g_default_async_waiter = nullptr;
-  g_default_logger = nullptr;
-}
-
-// static
-const MojoAsyncWaiter* Environment::GetDefaultAsyncWaiter() {
-  assert(g_default_async_waiter);  // Fails if not "inside" |Environment|.
-  return g_default_async_waiter;
-}
-
-// static
-const MojoLogger* Environment::GetDefaultLogger() {
-  assert(g_default_logger);  // Fails if not "inside" |Environment|.
-  return g_default_logger;
-}
-
-// static
-const TaskTracker* Environment::GetDefaultTaskTracker() {
-  return g_default_task_tracker;
-}
-
-// static
-void Environment::InstantiateDefaultRunLoop() {
-  assert(!RunLoop::current());
-  // Not leaked: accessible from |RunLoop::current()|.
-  RunLoop* run_loop = new RunLoop();
-  ALLOW_UNUSED_LOCAL(run_loop);
-  assert(run_loop == RunLoop::current());
-}
-
-// static
-void Environment::DestroyDefaultRunLoop() {
-  assert(RunLoop::current());
-  delete RunLoop::current();
-  assert(!RunLoop::current());
-}
-
-}  // namespace mojo
diff --git a/mojo/public/cpp/environment/lib/logging.cc b/mojo/public/cpp/environment/lib/logging.cc
deleted file mode 100644
index 921e9e7..0000000
--- a/mojo/public/cpp/environment/lib/logging.cc
+++ /dev/null
@@ -1,47 +0,0 @@
-// 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/public/cpp/environment/logging.h"
-
-#include <stdint.h>
-
-#include "mojo/public/cpp/environment/environment.h"
-
-namespace mojo {
-namespace internal {
-
-namespace {
-
-// Gets a pointer to the filename portion of |s|. Assumes that the filename
-// follows the last slash or backslash in |s|, or is |s| if no slash or
-// backslash is present.
-//
-// E.g., a pointer to "foo.cc" is returned for the following inputs: "foo.cc",
-// "./foo.cc", ".\foo.cc", "/absolute/path/to/foo.cc",
-// "relative/path/to/foo.cc", "C:\absolute\path\to\foo.cc", etc.
-const char* GetFilename(const char* s) {
-  const char* rv = s;
-  while (*s) {
-    if (*s == '/' || *s == '\\')
-      rv = s + 1;
-    s++;
-  }
-  return rv;
-}
-
-}  // namespace
-
-// TODO(vtl): Maybe we should preserve the full path and strip it out at a
-// different level instead?
-LogMessage::LogMessage(MojoLogLevel log_level, const char* file, int line)
-    : log_level_(log_level), file_(GetFilename(file)), line_(line) {
-}
-
-LogMessage::~LogMessage() {
-  Environment::GetDefaultLogger()->LogMessage(
-      log_level_, file_, static_cast<uint32_t>(line_), stream_.str().c_str());
-}
-
-}  // namespace internal
-}  // namespace mojo
diff --git a/mojo/public/cpp/environment/lib/scoped_task_tracking.cc b/mojo/public/cpp/environment/lib/scoped_task_tracking.cc
deleted file mode 100644
index 9e253d5..0000000
--- a/mojo/public/cpp/environment/lib/scoped_task_tracking.cc
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2015 The Chromium Authors. 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/public/cpp/environment/lib/scoped_task_tracking.h"
-
-#include "mojo/public/cpp/environment/environment.h"
-
-namespace mojo {
-namespace internal {
-
-ScopedTaskTracking::ScopedTaskTracking(const char* function_name,
-                                       const char* file_name,
-                                       int line,
-                                       const void* program_counter)
-    : id_(Environment::GetDefaultTaskTracker()->StartTracking(
-          function_name,
-          file_name,
-          line,
-          program_counter)) {
-}
-
-ScopedTaskTracking::ScopedTaskTracking(const char* function_name,
-                                       const char* file_name,
-                                       int line)
-    : id_(Environment::GetDefaultTaskTracker()->StartTracking(function_name,
-                                                              file_name,
-                                                              line,
-                                                              nullptr)) {
-}
-
-ScopedTaskTracking::~ScopedTaskTracking() {
-  Environment::GetDefaultTaskTracker()->EndTracking(id_);
-}
-
-}  // namespace internal
-}  // namespace mojo
diff --git a/mojo/public/cpp/environment/lib/scoped_task_tracking.h b/mojo/public/cpp/environment/lib/scoped_task_tracking.h
deleted file mode 100644
index 4a8fb4f..0000000
--- a/mojo/public/cpp/environment/lib/scoped_task_tracking.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2015 The Chromium Authors. 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_PUBLIC_CPP_ENVIRONMENT_LIB_SCOPED_TASK_TRACKING_H_
-#define MOJO_PUBLIC_CPP_ENVIRONMENT_LIB_SCOPED_TASK_TRACKING_H_
-
-#include "base/macros.h"
-#include "mojo/public/cpp/environment/task_tracker.h"
-
-namespace mojo {
-namespace internal {
-
-// An RAII wrapper for |TaskTrackingId|.
-class ScopedTaskTracking {
- public:
-  ScopedTaskTracking(const char* function_name,
-                     const char* file_name,
-                     int line,
-                     const void* program_counter);
-  ScopedTaskTracking(const char* function_name,
-                     const char* file_name,
-                     int line);
-  ~ScopedTaskTracking();
-
- private:
-  TaskTrackingId id_;
-  DISALLOW_COPY_AND_ASSIGN(ScopedTaskTracking);
-};
-
-}  // namespace internal
-}  // namespace mojo
-
-#endif  // MOJO_PUBLIC_CPP_ENVIRONMENT_LIB_SCOPED_TASK_TRACKING_H_
diff --git a/mojo/public/cpp/environment/logging.h b/mojo/public/cpp/environment/logging.h
deleted file mode 100644
index 834ba6b1..0000000
--- a/mojo/public/cpp/environment/logging.h
+++ /dev/null
@@ -1,97 +0,0 @@
-// 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.
-
-// Logging macros, similar to Chromium's base/logging.h, except with |MOJO_|
-// prefixes and missing some features (notably |CHECK_EQ()|, etc.).
-
-// TODO(vtl): It's weird that this is in the environment directory, since its
-// implementation (in environment/lib) is meant to be used by any implementation
-// of the environment.
-
-#ifndef MOJO_PUBLIC_CPP_ENVIRONMENT_LOGGING_H_
-#define MOJO_PUBLIC_CPP_ENVIRONMENT_LOGGING_H_
-
-#include <sstream>
-
-#include "base/macros.h"
-#include "mojo/public/c/environment/logger.h"
-#include "mojo/public/cpp/environment/environment.h"
-#include "mojo/public/cpp/system/macros.h"
-
-#if defined(OS_WIN)
-// To avoid a compile failure on Windows because it defines ERROR, which is also
-// used by the logs. Similar to change in base/logging.h.
-#undef ERROR
-#endif
-
-#define MOJO_LOG_STREAM(level)                                             \
-  ::mojo::internal::LogMessage(MOJO_LOG_LEVEL_##level, __FILE__, __LINE__) \
-      .stream()
-
-#define MOJO_LAZY_LOG_STREAM(level, condition) \
-  !(condition) ? (void)0                       \
-               : ::mojo::internal::VoidifyOstream() & MOJO_LOG_STREAM(level)
-
-#define MOJO_SHOULD_LOG(level) \
-  (MOJO_LOG_LEVEL_##level >=   \
-   ::mojo::Environment::GetDefaultLogger()->GetMinimumLogLevel())
-
-#define MOJO_LOG(level) MOJO_LAZY_LOG_STREAM(level, MOJO_SHOULD_LOG(level))
-
-#define MOJO_LOG_IF(level, condition) \
-  MOJO_LAZY_LOG_STREAM(level, MOJO_SHOULD_LOG(level) && (condition))
-
-#define MOJO_CHECK(condition)                                                  \
-  MOJO_LAZY_LOG_STREAM(FATAL, !(condition)) << "Check failed: " #condition "." \
-                                                                           " "
-
-// Note: For non-debug builds, |MOJO_DLOG_IF()| *eliminates* (i.e., doesn't
-// compile) the condition, whereas |MOJO_DCHECK()| "neuters" the condition
-// (i.e., compiles, but doesn't evaluate).
-#ifdef NDEBUG
-#define MOJO_DLOG(level) MOJO_LAZY_LOG_STREAM(level, false)
-#define MOJO_DLOG_IF(level, condition) MOJO_LAZY_LOG_STREAM(level, false)
-#else
-#define MOJO_DLOG(level) MOJO_LOG(level)
-#define MOJO_DLOG_IF(level, condition) MOJO_LOG_IF(level, condition)
-#endif  // NDEBUG
-
-#if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
-#define MOJO_DCHECK(condition) \
-  MOJO_LAZY_LOG_STREAM(FATAL, false ? !(condition) : false)
-#else
-#define MOJO_DCHECK(condition) MOJO_CHECK(condition)
-#endif  // NDEBUG && !defined(DCHECK_ALWAYS_ON)
-
-#define MOJO_NOTREACHED() MOJO_DCHECK(false)
-
-namespace mojo {
-namespace internal {
-
-class LogMessage {
- public:
-  LogMessage(MojoLogLevel log_level, const char* file, int line);
-  ~LogMessage();
-
-  std::ostream& stream() { return stream_; }
-
- private:
-  const MojoLogLevel log_level_;
-  const char* const file_;
-  const int line_;
-  std::ostringstream stream_;
-
-  DISALLOW_COPY_AND_ASSIGN(LogMessage);
-};
-
-// Used to ignore a stream.
-struct VoidifyOstream {
-  // Use & since it has precedence lower than << but higher than ?:.
-  void operator&(std::ostream&) {}
-};
-
-}  // namespace internal
-}  // namespace mojo
-
-#endif  // MOJO_PUBLIC_CPP_ENVIRONMENT_LOGGING_H_
diff --git a/mojo/public/cpp/environment/task_tracker.h b/mojo/public/cpp/environment/task_tracker.h
deleted file mode 100644
index d6d3020d..0000000
--- a/mojo/public/cpp/environment/task_tracker.h
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2015 The Chromium Authors. 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_PUBLIC_CPP_ENVIRONMENT_TASK_TRACKER_H_
-#define MOJO_PUBLIC_CPP_ENVIRONMENT_TASK_TRACKER_H_
-
-#include <stdint.h>
-
-namespace mojo {
-
-typedef intptr_t TaskTrackingId;
-
-// Interface for wiring task-level profiling. This API is mainly used by the
-// generated interface implementation.
-struct TaskTracker {
-  // Start tracking. The returned id must be reclaimed through |EndTracking()|.
-  TaskTrackingId (*StartTracking)(const char* function_name,
-                                  const char* file_name,
-                                  int line_number,
-                                  const void* program_counter);
-  // Finish tracking. The |id| is one that is returned from |StartTracking()|.
-  void (*EndTracking)(const TaskTrackingId id);
-  // Enable or disable tracking. It is disabled by default.
-  void (*SetEnabled)(bool enabled);
-};
-
-}  // namespace mojo
-
-#endif  // MOJO_PUBLIC_CPP_ENVIRONMENT_TASK_TRACKER_H_
diff --git a/mojo/public/cpp/environment/tests/BUILD.gn b/mojo/public/cpp/environment/tests/BUILD.gn
deleted file mode 100644
index 717c657..0000000
--- a/mojo/public/cpp/environment/tests/BUILD.gn
+++ /dev/null
@@ -1,24 +0,0 @@
-# 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.
-
-source_set("tests") {
-  testonly = true
-
-  sources = [
-    "async_wait_unittest.cc",
-    "async_waiter_unittest.cc",
-    "logger_unittest.cc",
-    "logging_unittest.cc",
-  ]
-
-  deps = [
-    "//mojo/public/c/environment",
-    "//mojo/public/cpp/bindings:callback",
-    "//mojo/public/cpp/environment:standalone",
-    "//mojo/public/cpp/system",
-    "//mojo/public/cpp/test_support:test_utils",
-    "//mojo/public/cpp/utility",
-    "//testing/gtest",
-  ]
-}
diff --git a/mojo/public/cpp/environment/tests/async_wait_unittest.cc b/mojo/public/cpp/environment/tests/async_wait_unittest.cc
deleted file mode 100644
index 8f77e670..0000000
--- a/mojo/public/cpp/environment/tests/async_wait_unittest.cc
+++ /dev/null
@@ -1,114 +0,0 @@
-// 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 <string>
-
-#include "mojo/public/c/environment/async_waiter.h"
-#include "mojo/public/cpp/environment/environment.h"
-#include "mojo/public/cpp/system/core.h"
-#include "mojo/public/cpp/system/macros.h"
-#include "mojo/public/cpp/test_support/test_utils.h"
-#include "mojo/public/cpp/utility/run_loop.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace mojo {
-namespace {
-
-class TestAsyncWaitCallback {
- public:
-  TestAsyncWaitCallback() : result_count_(0), last_result_(MOJO_RESULT_OK) {}
-  ~TestAsyncWaitCallback() {}
-
-  int result_count() const { return result_count_; }
-
-  MojoResult last_result() const { return last_result_; }
-
-  // MojoAsyncWaitCallback:
-  static void OnHandleReady(void* closure, MojoResult result) {
-    TestAsyncWaitCallback* self = static_cast<TestAsyncWaitCallback*>(closure);
-    self->result_count_++;
-    self->last_result_ = result;
-  }
-
- private:
-  int result_count_;
-  MojoResult last_result_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestAsyncWaitCallback);
-};
-
-MojoAsyncWaitID CallAsyncWait(const Handle& handle,
-                              MojoHandleSignals signals,
-                              TestAsyncWaitCallback* callback) {
-  return Environment::GetDefaultAsyncWaiter()->AsyncWait(
-      handle.value(),
-      signals,
-      MOJO_DEADLINE_INDEFINITE,
-      &TestAsyncWaitCallback::OnHandleReady,
-      callback);
-}
-
-void CallCancelWait(MojoAsyncWaitID wait_id) {
-  Environment::GetDefaultAsyncWaiter()->CancelWait(wait_id);
-}
-
-class AsyncWaitTest : public testing::Test {
- public:
-  AsyncWaitTest() {}
-
- private:
-  Environment environment_;
-  RunLoop run_loop_;
-
-  DISALLOW_COPY_AND_ASSIGN(AsyncWaitTest);
-};
-
-// Verifies AsyncWaitCallback is notified when pipe is ready.
-TEST_F(AsyncWaitTest, CallbackNotified) {
-  TestAsyncWaitCallback callback;
-  MessagePipe test_pipe;
-  EXPECT_TRUE(test::WriteTextMessage(test_pipe.handle1.get(), std::string()));
-
-  CallAsyncWait(
-      test_pipe.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE, &callback);
-  RunLoop::current()->Run();
-  EXPECT_EQ(1, callback.result_count());
-  EXPECT_EQ(MOJO_RESULT_OK, callback.last_result());
-}
-
-// Verifies 2 AsyncWaitCallbacks are notified when there pipes are ready.
-TEST_F(AsyncWaitTest, TwoCallbacksNotified) {
-  TestAsyncWaitCallback callback1;
-  TestAsyncWaitCallback callback2;
-  MessagePipe test_pipe1;
-  MessagePipe test_pipe2;
-  EXPECT_TRUE(test::WriteTextMessage(test_pipe1.handle1.get(), std::string()));
-  EXPECT_TRUE(test::WriteTextMessage(test_pipe2.handle1.get(), std::string()));
-
-  CallAsyncWait(
-      test_pipe1.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE, &callback1);
-  CallAsyncWait(
-      test_pipe2.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE, &callback2);
-
-  RunLoop::current()->Run();
-  EXPECT_EQ(1, callback1.result_count());
-  EXPECT_EQ(MOJO_RESULT_OK, callback1.last_result());
-  EXPECT_EQ(1, callback2.result_count());
-  EXPECT_EQ(MOJO_RESULT_OK, callback2.last_result());
-}
-
-// Verifies cancel works.
-TEST_F(AsyncWaitTest, CancelCallback) {
-  TestAsyncWaitCallback callback;
-  MessagePipe test_pipe;
-  EXPECT_TRUE(test::WriteTextMessage(test_pipe.handle1.get(), std::string()));
-
-  CallCancelWait(CallAsyncWait(
-      test_pipe.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE, &callback));
-  RunLoop::current()->Run();
-  EXPECT_EQ(0, callback.result_count());
-}
-
-}  // namespace
-}  // namespace mojo
diff --git a/mojo/public/cpp/environment/tests/async_waiter_unittest.cc b/mojo/public/cpp/environment/tests/async_waiter_unittest.cc
deleted file mode 100644
index 3628788d..0000000
--- a/mojo/public/cpp/environment/tests/async_waiter_unittest.cc
+++ /dev/null
@@ -1,107 +0,0 @@
-// 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/public/cpp/bindings/callback.h"
-#include "mojo/public/cpp/environment/async_waiter.h"
-#include "mojo/public/cpp/test_support/test_utils.h"
-#include "mojo/public/cpp/utility/run_loop.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace mojo {
-namespace {
-
-class TestAsyncWaitCallback {
- public:
-  TestAsyncWaitCallback() : result_count_(0), last_result_(MOJO_RESULT_OK) {}
-  ~TestAsyncWaitCallback() {}
-
-  int result_count() const { return result_count_; }
-
-  MojoResult last_result() const { return last_result_; }
-
-  void OnHandleReady(MojoResult result) {
-    result_count_++;
-    last_result_ = result;
-  }
-
- private:
-  int result_count_;
-  MojoResult last_result_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestAsyncWaitCallback);
-};
-
-// Manual code to create a callback since we don't have mojo::Bind yet.
-class ManualCallback {
- public:
-  explicit ManualCallback(TestAsyncWaitCallback* callback)
-      : callback_(callback) {}
-
-  void Run(MojoResult result) const { callback_->OnHandleReady(result); }
-
- private:
-  TestAsyncWaitCallback* callback_;
-};
-
-class AsyncWaiterTest : public testing::Test {
- public:
-  AsyncWaiterTest() {}
-
- private:
-  Environment environment_;
-  RunLoop run_loop_;
-
-  DISALLOW_COPY_AND_ASSIGN(AsyncWaiterTest);
-};
-
-// Verifies AsyncWaitCallback is notified when pipe is ready.
-TEST_F(AsyncWaiterTest, CallbackNotified) {
-  TestAsyncWaitCallback callback;
-  MessagePipe test_pipe;
-  EXPECT_TRUE(test::WriteTextMessage(test_pipe.handle1.get(), std::string()));
-
-  AsyncWaiter waiter(test_pipe.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE,
-                     ManualCallback(&callback));
-  RunLoop::current()->Run();
-  EXPECT_EQ(1, callback.result_count());
-  EXPECT_EQ(MOJO_RESULT_OK, callback.last_result());
-}
-
-// Verifies 2 AsyncWaitCallbacks are notified when there pipes are ready.
-TEST_F(AsyncWaiterTest, TwoCallbacksNotified) {
-  TestAsyncWaitCallback callback1;
-  TestAsyncWaitCallback callback2;
-  MessagePipe test_pipe1;
-  MessagePipe test_pipe2;
-  EXPECT_TRUE(test::WriteTextMessage(test_pipe1.handle1.get(), std::string()));
-  EXPECT_TRUE(test::WriteTextMessage(test_pipe2.handle1.get(), std::string()));
-
-  AsyncWaiter waiter1(test_pipe1.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE,
-                      ManualCallback(&callback1));
-  AsyncWaiter waiter2(test_pipe2.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE,
-                      ManualCallback(&callback2));
-
-  RunLoop::current()->Run();
-  EXPECT_EQ(1, callback1.result_count());
-  EXPECT_EQ(MOJO_RESULT_OK, callback1.last_result());
-  EXPECT_EQ(1, callback2.result_count());
-  EXPECT_EQ(MOJO_RESULT_OK, callback2.last_result());
-}
-
-// Verifies cancel works.
-TEST_F(AsyncWaiterTest, CancelCallback) {
-  TestAsyncWaitCallback callback;
-  MessagePipe test_pipe;
-  EXPECT_TRUE(test::WriteTextMessage(test_pipe.handle1.get(), std::string()));
-
-  {
-    AsyncWaiter waiter(test_pipe.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE,
-                       ManualCallback(&callback));
-  }
-  RunLoop::current()->Run();
-  EXPECT_EQ(0, callback.result_count());
-}
-
-}  // namespace
-}  // namespace mojo
diff --git a/mojo/public/cpp/environment/tests/logger_unittest.cc b/mojo/public/cpp/environment/tests/logger_unittest.cc
deleted file mode 100644
index 8ca5538..0000000
--- a/mojo/public/cpp/environment/tests/logger_unittest.cc
+++ /dev/null
@@ -1,89 +0,0 @@
-// 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/public/c/environment/logger.h"
-#include "mojo/public/cpp/environment/environment.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace mojo {
-namespace {
-
-TEST(LoggerTest, Basic) {
-  const char kPath[] = "/fake/path/to/file.cc";
-
-  Environment environment;
-  const MojoLogger* const logger = Environment::GetDefaultLogger();
-
-  logger->LogMessage(MOJO_LOG_LEVEL_VERBOSE - 1, kPath, 123,
-                     "Logged at VERBOSE-1 level");
-  logger->LogMessage(MOJO_LOG_LEVEL_VERBOSE, kPath, 123,
-                     "Logged at VERBOSE level");
-  logger->LogMessage(MOJO_LOG_LEVEL_INFO, kPath, 123, "Logged at INFO level");
-  logger->LogMessage(MOJO_LOG_LEVEL_WARNING, kPath, 123,
-                     "Logged at WARNING level");
-  logger->LogMessage(MOJO_LOG_LEVEL_ERROR, kPath, 123, "Logged at ERROR level");
-
-  // This should kill us:
-  EXPECT_DEATH_IF_SUPPORTED({
-    logger->LogMessage(MOJO_LOG_LEVEL_FATAL, kPath, 123,
-                       "Logged at FATAL level");
-  }, "");
-}
-
-TEST(LoggerTest, LogLevels) {
-  const char kPath[] = "/fake/path/to/file.cc";
-
-  Environment environment;
-  const MojoLogger* const logger = Environment::GetDefaultLogger();
-
-  for (MojoLogLevel log_level = MOJO_LOG_LEVEL_VERBOSE - 1;
-       log_level <= MOJO_LOG_LEVEL_FATAL + 1;
-       log_level++) {
-    logger->SetMinimumLogLevel(log_level);
-
-    if (log_level <= MOJO_LOG_LEVEL_FATAL)
-      EXPECT_EQ(log_level, logger->GetMinimumLogLevel());
-    else
-      EXPECT_EQ(MOJO_LOG_LEVEL_FATAL, logger->GetMinimumLogLevel());
-
-    logger->LogMessage(MOJO_LOG_LEVEL_VERBOSE - 1, kPath, 123,
-                       "Logged at VERBOSE-1 level");
-    logger->LogMessage(MOJO_LOG_LEVEL_VERBOSE, kPath, 123,
-                       "Logged at VERBOSE level");
-    logger->LogMessage(MOJO_LOG_LEVEL_INFO, kPath, 123, "Logged at INFO level");
-    logger->LogMessage(MOJO_LOG_LEVEL_WARNING, kPath, 123,
-                       "Logged at WARNING level");
-    logger->LogMessage(MOJO_LOG_LEVEL_ERROR, kPath, 123,
-                       "Logged at ERROR level");
-
-    // This should kill us:
-    EXPECT_DEATH_IF_SUPPORTED({
-      logger->LogMessage(MOJO_LOG_LEVEL_FATAL, kPath, 123,
-                         "Logged at FATAL level");
-    }, "");
-  }
-}
-
-TEST(LoggerTest, NoFile) {
-  Environment environment;
-  const MojoLogger* const logger = Environment::GetDefaultLogger();
-
-  logger->LogMessage(MOJO_LOG_LEVEL_VERBOSE - 1, nullptr, 0,
-                     "Logged at VERBOSE-1 level");
-  logger->LogMessage(MOJO_LOG_LEVEL_VERBOSE, nullptr, 0,
-                     "Logged at VERBOSE level");
-  logger->LogMessage(MOJO_LOG_LEVEL_INFO, nullptr, 0, "Logged at INFO level");
-  logger->LogMessage(MOJO_LOG_LEVEL_WARNING, nullptr, 0,
-                     "Logged at WARNING level");
-  logger->LogMessage(MOJO_LOG_LEVEL_ERROR, nullptr, 0, "Logged at ERROR level");
-
-  // This should kill us:
-  EXPECT_DEATH_IF_SUPPORTED({
-    logger->LogMessage(MOJO_LOG_LEVEL_FATAL, nullptr, 0,
-                       "Logged at FATAL level");
-  }, "");
-}
-
-}  // namespace
-}  // namespace mojo
diff --git a/mojo/public/cpp/environment/tests/logging_unittest.cc b/mojo/public/cpp/environment/tests/logging_unittest.cc
deleted file mode 100644
index 8377252..0000000
--- a/mojo/public/cpp/environment/tests/logging_unittest.cc
+++ /dev/null
@@ -1,522 +0,0 @@
-// 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 <stdint.h>
-#include <stdlib.h>
-
-#include <sstream>
-#include <string>
-
-#include "mojo/public/cpp/environment/environment.h"
-#include "mojo/public/cpp/environment/logging.h"
-#include "mojo/public/cpp/system/macros.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace mojo {
-namespace {
-
-// The current logging system strips the path, so we need our filename.
-const char kOurFilename[] = "logging_unittest.cc";
-
-class PtrToMemberHelper {
- public:
-  int member;
-};
-
-bool DcheckTestHelper(bool* was_called) {
-  *was_called = true;
-  return false;
-}
-
-class LoggingTest : public testing::Test {
- public:
-  LoggingTest() : environment_(nullptr, &kMockLogger, nullptr) {
-    minimum_log_level_ = MOJO_LOG_LEVEL_INFO;
-    ResetMockLogger();
-  }
-  ~LoggingTest() override {}
-
- protected:
-  // Note: Does not reset |minimum_log_level_|.
-  static void ResetMockLogger() {
-    log_message_was_called_ = false;
-    last_log_level_ = MOJO_LOG_LEVEL_INFO;
-    last_source_file_.clear();
-    last_source_line_ = 0;
-    last_message_.clear();
-  }
-
-  // A function returning |bool| that shouldn't be called.
-  static bool NotCalledCondition() {
-    not_called_condition_was_called_ = true;
-    return false;
-  }
-
-  static bool log_message_was_called() { return log_message_was_called_; }
-  static MojoLogLevel last_log_level() { return last_log_level_; }
-  static const std::string& last_source_file() { return last_source_file_; }
-  static uint32_t last_source_line() { return last_source_line_; }
-  static const std::string& last_message() { return last_message_; }
-  static bool not_called_condition_was_called() {
-    return not_called_condition_was_called_;
-  }
-
- private:
-  // Note: We record calls even if |log_level| is below |minimum_log_level_|
-  // (since the macros should mostly avoid this, and we want to be able to check
-  // that they do).
-  static void MockLogMessage(MojoLogLevel log_level,
-                             const char* source_file,
-                             uint32_t source_line,
-                             const char* message) {
-    log_message_was_called_ = true;
-    last_log_level_ = log_level;
-    last_source_file_ = source_file;
-    last_source_line_ = source_line;
-    last_message_ = message;
-  }
-
-  static MojoLogLevel MockGetMinimumLogLevel() { return minimum_log_level_; }
-
-  static void MockSetMinimumLogLevel(MojoLogLevel minimum_log_level) {
-    minimum_log_level_ = minimum_log_level;
-  }
-
-  Environment environment_;
-
-  static const MojoLogger kMockLogger;
-  static MojoLogLevel minimum_log_level_;
-  static bool log_message_was_called_;
-  static MojoLogLevel last_log_level_;
-  static std::string last_source_file_;
-  static uint32_t last_source_line_;
-  static std::string last_message_;
-  static bool not_called_condition_was_called_;
-
-  DISALLOW_COPY_AND_ASSIGN(LoggingTest);
-};
-
-// static
-const MojoLogger LoggingTest::kMockLogger = {
-    &LoggingTest::MockLogMessage,
-    &LoggingTest::MockGetMinimumLogLevel,
-    &LoggingTest::MockSetMinimumLogLevel};
-
-// static
-MojoLogLevel LoggingTest::minimum_log_level_ = MOJO_LOG_LEVEL_INFO;
-
-// static
-bool LoggingTest::log_message_was_called_ = MOJO_LOG_LEVEL_INFO;
-
-// static
-MojoLogLevel LoggingTest::last_log_level_ = MOJO_LOG_LEVEL_INFO;
-
-// static
-std::string LoggingTest::last_source_file_;
-
-// static
-uint32_t LoggingTest::last_source_line_ = 0;
-
-// static
-std::string LoggingTest::last_message_;
-
-// static
-bool LoggingTest::not_called_condition_was_called_ = false;
-
-TEST_F(LoggingTest, InternalLogMessage) {
-  internal::LogMessage(MOJO_LOG_LEVEL_INFO, "foo.cc", 123).stream() << "hello "
-                                                                    << "world";
-  EXPECT_TRUE(log_message_was_called());
-  EXPECT_EQ(MOJO_LOG_LEVEL_INFO, last_log_level());
-  EXPECT_EQ("foo.cc", last_source_file());
-  EXPECT_EQ(123u, last_source_line());
-  EXPECT_EQ("hello world", last_message());
-
-  ResetMockLogger();
-
-  internal::LogMessage(MOJO_LOG_LEVEL_WARNING, "./path/to/foo.cc", 123).stream()
-      << "hello "
-      << "world";
-  EXPECT_TRUE(log_message_was_called());
-  EXPECT_EQ(MOJO_LOG_LEVEL_WARNING, last_log_level());
-  EXPECT_EQ("foo.cc", last_source_file());
-  EXPECT_EQ(123u, last_source_line());
-  EXPECT_EQ("hello world", last_message());
-
-  ResetMockLogger();
-
-  internal::LogMessage(MOJO_LOG_LEVEL_ERROR, "/path/to/foo.cc", 123).stream()
-      << "hello "
-      << "world";
-  EXPECT_TRUE(log_message_was_called());
-  EXPECT_EQ(MOJO_LOG_LEVEL_ERROR, last_log_level());
-  EXPECT_EQ("foo.cc", last_source_file());
-  EXPECT_EQ(123u, last_source_line());
-  EXPECT_EQ("hello world", last_message());
-
-  ResetMockLogger();
-
-  internal::LogMessage(MOJO_LOG_LEVEL_FATAL, "path/to/foo.cc", 123).stream()
-      << "hello "
-      << "world";
-  EXPECT_TRUE(log_message_was_called());
-  EXPECT_EQ(MOJO_LOG_LEVEL_FATAL, last_log_level());
-  EXPECT_EQ("foo.cc", last_source_file());
-  EXPECT_EQ(123u, last_source_line());
-  EXPECT_EQ("hello world", last_message());
-
-  ResetMockLogger();
-
-  internal::LogMessage(MOJO_LOG_LEVEL_VERBOSE, ".\\xy\\foo.cc", 123).stream()
-      << "hello "
-      << "world";
-  EXPECT_TRUE(log_message_was_called());
-  EXPECT_EQ(MOJO_LOG_LEVEL_VERBOSE, last_log_level());
-  EXPECT_EQ("foo.cc", last_source_file());
-  EXPECT_EQ(123u, last_source_line());
-  EXPECT_EQ("hello world", last_message());
-
-  ResetMockLogger();
-
-  internal::LogMessage(MOJO_LOG_LEVEL_VERBOSE - 1, "xy\\foo.cc", 123).stream()
-      << "hello "
-      << "world";
-  EXPECT_TRUE(log_message_was_called());
-  EXPECT_EQ(MOJO_LOG_LEVEL_VERBOSE - 1, last_log_level());
-  EXPECT_EQ("foo.cc", last_source_file());
-  EXPECT_EQ(123u, last_source_line());
-  EXPECT_EQ("hello world", last_message());
-
-  ResetMockLogger();
-
-  internal::LogMessage(MOJO_LOG_LEVEL_VERBOSE - 9, "C:\\xy\\foo.cc", 123)
-          .stream()
-      << "hello "
-      << "world";
-  EXPECT_TRUE(log_message_was_called());
-  EXPECT_EQ(MOJO_LOG_LEVEL_VERBOSE - 9, last_log_level());
-  EXPECT_EQ("foo.cc", last_source_file());
-  EXPECT_EQ(123u, last_source_line());
-  EXPECT_EQ("hello world", last_message());
-
-  ResetMockLogger();
-
-  internal::LogMessage(MOJO_LOG_LEVEL_INFO, __FILE__, 123).stream() << "hello "
-                                                                    << "world";
-  EXPECT_TRUE(log_message_was_called());
-  EXPECT_EQ(MOJO_LOG_LEVEL_INFO, last_log_level());
-  EXPECT_EQ(kOurFilename, last_source_file());
-  EXPECT_EQ(123u, last_source_line());
-  EXPECT_EQ("hello world", last_message());
-}
-
-TEST_F(LoggingTest, LogStream) {
-  MOJO_LOG_STREAM(INFO) << "hello";
-  EXPECT_TRUE(log_message_was_called());
-  EXPECT_EQ(MOJO_LOG_LEVEL_INFO, last_log_level());
-  EXPECT_EQ(kOurFilename, last_source_file());
-  EXPECT_EQ(static_cast<uint32_t>(__LINE__ - 4), last_source_line());
-  EXPECT_EQ("hello", last_message());
-
-  ResetMockLogger();
-
-  MOJO_LOG_STREAM(ERROR) << "hi " << 123;
-  EXPECT_TRUE(log_message_was_called());
-  EXPECT_EQ(MOJO_LOG_LEVEL_ERROR, last_log_level());
-  EXPECT_EQ(kOurFilename, last_source_file());
-  EXPECT_EQ(static_cast<uint32_t>(__LINE__ - 4), last_source_line());
-  EXPECT_EQ("hi 123", last_message());
-}
-
-TEST_F(LoggingTest, LazyLogStream) {
-  MOJO_LAZY_LOG_STREAM(INFO, true) << "hello";
-  EXPECT_TRUE(log_message_was_called());
-  EXPECT_EQ(MOJO_LOG_LEVEL_INFO, last_log_level());
-  EXPECT_EQ(kOurFilename, last_source_file());
-  EXPECT_EQ(static_cast<uint32_t>(__LINE__ - 4), last_source_line());
-  EXPECT_EQ("hello", last_message());
-
-  ResetMockLogger();
-
-  MOJO_LAZY_LOG_STREAM(ERROR, true) << "hi " << 123;
-  EXPECT_TRUE(log_message_was_called());
-  EXPECT_EQ(MOJO_LOG_LEVEL_ERROR, last_log_level());
-  EXPECT_EQ(kOurFilename, last_source_file());
-  EXPECT_EQ(static_cast<uint32_t>(__LINE__ - 4), last_source_line());
-  EXPECT_EQ("hi 123", last_message());
-
-  ResetMockLogger();
-
-  MOJO_LAZY_LOG_STREAM(INFO, false) << "hello";
-  EXPECT_FALSE(log_message_was_called());
-
-  ResetMockLogger();
-
-  MOJO_LAZY_LOG_STREAM(FATAL, false) << "hello";
-  EXPECT_FALSE(log_message_was_called());
-
-  ResetMockLogger();
-
-  PtrToMemberHelper helper;
-  helper.member = 1;
-  int PtrToMemberHelper::*member_ptr = &PtrToMemberHelper::member;
-
-  // This probably fails to compile if we forget to parenthesize the condition
-  // in the macro (.* has lower precedence than !, which can't apply to
-  // |helper|).
-  MOJO_LAZY_LOG_STREAM(ERROR, helper.*member_ptr == 1) << "hello";
-  EXPECT_TRUE(log_message_was_called());
-
-  ResetMockLogger();
-
-  MOJO_LAZY_LOG_STREAM(WARNING, helper.*member_ptr == 0) << "hello";
-  EXPECT_FALSE(log_message_was_called());
-}
-
-TEST_F(LoggingTest, ShouldLog) {
-  // We start at |MOJO_LOG_LEVEL_INFO|.
-  EXPECT_FALSE(MOJO_SHOULD_LOG(VERBOSE));
-  EXPECT_TRUE(MOJO_SHOULD_LOG(INFO));
-  EXPECT_TRUE(MOJO_SHOULD_LOG(WARNING));
-  EXPECT_TRUE(MOJO_SHOULD_LOG(ERROR));
-  EXPECT_TRUE(MOJO_SHOULD_LOG(FATAL));
-
-  Environment::GetDefaultLogger()->SetMinimumLogLevel(MOJO_LOG_LEVEL_ERROR);
-  EXPECT_FALSE(MOJO_SHOULD_LOG(VERBOSE));
-  EXPECT_FALSE(MOJO_SHOULD_LOG(INFO));
-  EXPECT_FALSE(MOJO_SHOULD_LOG(WARNING));
-  EXPECT_TRUE(MOJO_SHOULD_LOG(ERROR));
-  EXPECT_TRUE(MOJO_SHOULD_LOG(FATAL));
-
-  Environment::GetDefaultLogger()->SetMinimumLogLevel(MOJO_LOG_LEVEL_VERBOSE -
-                                                      1);
-  EXPECT_TRUE(MOJO_SHOULD_LOG(VERBOSE));
-  EXPECT_TRUE(MOJO_SHOULD_LOG(INFO));
-  EXPECT_TRUE(MOJO_SHOULD_LOG(WARNING));
-  EXPECT_TRUE(MOJO_SHOULD_LOG(ERROR));
-  EXPECT_TRUE(MOJO_SHOULD_LOG(FATAL));
-}
-
-TEST_F(LoggingTest, Log) {
-  // We start at |MOJO_LOG_LEVEL_INFO|.
-  MOJO_LOG(VERBOSE) << "hello";
-  EXPECT_FALSE(log_message_was_called());
-
-  ResetMockLogger();
-
-  MOJO_LOG(INFO) << "hello";
-  EXPECT_TRUE(log_message_was_called());
-  EXPECT_EQ(MOJO_LOG_LEVEL_INFO, last_log_level());
-  EXPECT_EQ(kOurFilename, last_source_file());
-  EXPECT_EQ(static_cast<uint32_t>(__LINE__ - 4), last_source_line());
-  EXPECT_EQ("hello", last_message());
-
-  ResetMockLogger();
-
-  MOJO_LOG(ERROR) << "hello";
-  EXPECT_TRUE(log_message_was_called());
-  EXPECT_EQ(MOJO_LOG_LEVEL_ERROR, last_log_level());
-  EXPECT_EQ(kOurFilename, last_source_file());
-  EXPECT_EQ(static_cast<uint32_t>(__LINE__ - 4), last_source_line());
-  EXPECT_EQ("hello", last_message());
-
-  ResetMockLogger();
-
-  Environment::GetDefaultLogger()->SetMinimumLogLevel(MOJO_LOG_LEVEL_ERROR);
-
-  MOJO_LOG(VERBOSE) << "hello";
-  EXPECT_FALSE(log_message_was_called());
-
-  ResetMockLogger();
-
-  MOJO_LOG(INFO) << "hello";
-  EXPECT_FALSE(log_message_was_called());
-
-  ResetMockLogger();
-
-  MOJO_LOG(ERROR) << "hello";
-  EXPECT_TRUE(log_message_was_called());
-  EXPECT_EQ(MOJO_LOG_LEVEL_ERROR, last_log_level());
-  EXPECT_EQ(kOurFilename, last_source_file());
-  EXPECT_EQ(static_cast<uint32_t>(__LINE__ - 4), last_source_line());
-  EXPECT_EQ("hello", last_message());
-}
-
-TEST_F(LoggingTest, LogIf) {
-  // We start at |MOJO_LOG_LEVEL_INFO|.
-  MOJO_LOG_IF(VERBOSE, true) << "hello";
-  EXPECT_FALSE(log_message_was_called());
-
-  ResetMockLogger();
-
-  MOJO_LOG_IF(VERBOSE, false) << "hello";
-  EXPECT_FALSE(log_message_was_called());
-
-  ResetMockLogger();
-  Environment::GetDefaultLogger()->SetMinimumLogLevel(MOJO_LOG_LEVEL_ERROR);
-
-  bool x = true;
-  // Also try to make sure that we parenthesize the condition properly.
-  MOJO_LOG_IF(INFO, false || x) << "hello";
-  EXPECT_FALSE(log_message_was_called());
-
-  ResetMockLogger();
-
-  MOJO_LOG_IF(INFO, 0 != 1) << "hello";
-  EXPECT_FALSE(log_message_was_called());
-
-  ResetMockLogger();
-
-  MOJO_LOG_IF(WARNING, 1 + 1 == 2) << "hello";
-  EXPECT_FALSE(log_message_was_called());
-
-  ResetMockLogger();
-
-  MOJO_LOG_IF(ERROR, 1 * 2 == 2) << "hello";
-  EXPECT_TRUE(log_message_was_called());
-  EXPECT_EQ(MOJO_LOG_LEVEL_ERROR, last_log_level());
-  EXPECT_EQ(kOurFilename, last_source_file());
-  EXPECT_EQ(static_cast<uint32_t>(__LINE__ - 4), last_source_line());
-  EXPECT_EQ("hello", last_message());
-
-  ResetMockLogger();
-
-  MOJO_LOG_IF(FATAL, 1 * 2 == 3) << "hello";
-  EXPECT_FALSE(log_message_was_called());
-
-  ResetMockLogger();
-
-  // |MOJO_LOG_IF()| shouldn't evaluate its condition if the level is below the
-  // minimum.
-  MOJO_LOG_IF(INFO, NotCalledCondition()) << "hello";
-  EXPECT_FALSE(not_called_condition_was_called());
-  EXPECT_FALSE(log_message_was_called());
-}
-
-TEST_F(LoggingTest, Check) {
-  MOJO_CHECK(true) << "hello";
-  EXPECT_FALSE(log_message_was_called());
-
-  ResetMockLogger();
-
-  PtrToMemberHelper helper;
-  helper.member = 0;
-  int PtrToMemberHelper::*member_ptr = &PtrToMemberHelper::member;
-
-  // Also try to make sure that we parenthesize the condition properly.
-  MOJO_CHECK(helper.*member_ptr == 1) << "hello";
-  EXPECT_TRUE(log_message_was_called());
-  EXPECT_EQ(MOJO_LOG_LEVEL_FATAL, last_log_level());
-  EXPECT_EQ(kOurFilename, last_source_file());
-  EXPECT_EQ(static_cast<uint32_t>(__LINE__ - 4), last_source_line());
-  EXPECT_EQ("Check failed: helper.*member_ptr == 1. hello", last_message());
-
-  ResetMockLogger();
-
-  // Also test a "naked" |MOJO_CHECK()|s.
-  MOJO_CHECK(1 + 2 == 3);
-  EXPECT_FALSE(log_message_was_called());
-}
-
-TEST_F(LoggingTest, Dlog) {
-  // We start at |MOJO_LOG_LEVEL_INFO|.
-  MOJO_DLOG(VERBOSE) << "hello";
-  EXPECT_FALSE(log_message_was_called());
-
-  ResetMockLogger();
-
-  MOJO_DLOG(INFO) << "hello";
-#ifdef NDEBUG
-  EXPECT_FALSE(log_message_was_called());
-#else
-  EXPECT_TRUE(log_message_was_called());
-  EXPECT_EQ(MOJO_LOG_LEVEL_INFO, last_log_level());
-  EXPECT_EQ(kOurFilename, last_source_file());
-  EXPECT_EQ(static_cast<uint32_t>(__LINE__ - 7), last_source_line());
-  EXPECT_EQ("hello", last_message());
-#endif
-}
-
-TEST_F(LoggingTest, DlogIf) {
-  // We start at |MOJO_LOG_LEVEL_INFO|. It shouldn't evaluate the condition in
-  // this case.
-  MOJO_DLOG_IF(VERBOSE, NotCalledCondition()) << "hello";
-  EXPECT_FALSE(not_called_condition_was_called());
-  EXPECT_FALSE(log_message_was_called());
-
-  ResetMockLogger();
-
-  MOJO_DLOG_IF(INFO, 1 == 0) << "hello";
-  EXPECT_FALSE(log_message_was_called());
-
-  ResetMockLogger();
-
-  MOJO_DLOG_IF(INFO, 1 == 1) << "hello";
-#ifdef NDEBUG
-  EXPECT_FALSE(log_message_was_called());
-#else
-  EXPECT_TRUE(log_message_was_called());
-  EXPECT_EQ(MOJO_LOG_LEVEL_INFO, last_log_level());
-  EXPECT_EQ(kOurFilename, last_source_file());
-  EXPECT_EQ(static_cast<uint32_t>(__LINE__ - 7), last_source_line());
-  EXPECT_EQ("hello", last_message());
-#endif
-
-  ResetMockLogger();
-
-// |MOJO_DLOG_IF()| shouldn't compile its condition for non-debug builds.
-#ifndef NDEBUG
-  bool debug_only = true;
-#endif
-  MOJO_DLOG_IF(WARNING, debug_only) << "hello";
-#ifdef NDEBUG
-  EXPECT_FALSE(log_message_was_called());
-#else
-  EXPECT_TRUE(log_message_was_called());
-  EXPECT_EQ(MOJO_LOG_LEVEL_WARNING, last_log_level());
-  EXPECT_EQ(kOurFilename, last_source_file());
-  EXPECT_EQ(static_cast<uint32_t>(__LINE__ - 7), last_source_line());
-  EXPECT_EQ("hello", last_message());
-#endif
-}
-
-TEST_F(LoggingTest, Dcheck) {
-  MOJO_DCHECK(true);
-  EXPECT_FALSE(log_message_was_called());
-
-  ResetMockLogger();
-
-  MOJO_DCHECK(true) << "hello";
-  EXPECT_FALSE(log_message_was_called());
-
-  ResetMockLogger();
-
-  // |MOJO_DCHECK()| should compile (but not evaluate) its condition even for
-  // non-debug builds. (Hopefully, we'll get an unused variable error if it
-  // fails to compile the condition.)
-  bool was_called = false;
-  MOJO_DCHECK(DcheckTestHelper(&was_called)) << "hello";
-#if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
-  EXPECT_FALSE(was_called);
-  EXPECT_FALSE(log_message_was_called());
-#else
-  EXPECT_TRUE(was_called);
-  EXPECT_TRUE(log_message_was_called());
-  EXPECT_EQ(MOJO_LOG_LEVEL_FATAL, last_log_level());
-  EXPECT_EQ(kOurFilename, last_source_file());
-  EXPECT_EQ(static_cast<uint32_t>(__LINE__ - 9), last_source_line());
-  EXPECT_EQ("Check failed: DcheckTestHelper(&was_called). hello",
-            last_message());
-#endif
-
-  ResetMockLogger();
-
-  // Also try to make sure that we parenthesize the condition properly.
-  bool x = true;
-  MOJO_DCHECK(false || x) << "hello";
-  EXPECT_FALSE(log_message_was_called());
-}
-
-}  // namespace
-}  // namespace mojo
diff --git a/mojo/public/cpp/system/tests/BUILD.gn b/mojo/public/cpp/system/tests/BUILD.gn
index e7c8f29..b6664af 100644
--- a/mojo/public/cpp/system/tests/BUILD.gn
+++ b/mojo/public/cpp/system/tests/BUILD.gn
@@ -14,7 +14,6 @@
   deps = [
     "//base",
     "//mojo/public/c/system/tests",
-    "//mojo/public/cpp/environment:standalone",
     "//mojo/public/cpp/system",
     "//mojo/public/cpp/test_support:test_utils",
     "//testing/gtest",
diff --git a/mojo/public/cpp/utility/tests/BUILD.gn b/mojo/public/cpp/utility/tests/BUILD.gn
index d324a57..b5a92196 100644
--- a/mojo/public/cpp/utility/tests/BUILD.gn
+++ b/mojo/public/cpp/utility/tests/BUILD.gn
@@ -10,7 +10,6 @@
   ]
 
   deps = [
-    "//mojo/public/cpp/environment:standalone",
     "//mojo/public/cpp/system",
     "//mojo/public/cpp/test_support:test_utils",
     "//mojo/public/cpp/utility",
diff --git a/mojo/public/interfaces/bindings/BUILD.gn b/mojo/public/interfaces/bindings/BUILD.gn
index f0f12f93..c7421b9 100644
--- a/mojo/public/interfaces/bindings/BUILD.gn
+++ b/mojo/public/interfaces/bindings/BUILD.gn
@@ -9,6 +9,4 @@
     "interface_control_messages.mojom",
     "pipe_control_messages.mojom",
   ]
-
-  with_environment = false
 }
diff --git a/mojo/public/interfaces/bindings/tests/BUILD.gn b/mojo/public/interfaces/bindings/tests/BUILD.gn
index 42f16c3..dddb522a 100644
--- a/mojo/public/interfaces/bindings/tests/BUILD.gn
+++ b/mojo/public/interfaces/bindings/tests/BUILD.gn
@@ -25,8 +25,6 @@
     "test_sync_methods.mojom",
     "validation_test_interfaces.mojom",
   ]
-
-  with_environment = false
 }
 
 mojom("test_struct_traits_interfaces") {
@@ -36,8 +34,6 @@
   ]
 
   typemaps = [ "struct_with_traits.typemap" ]
-
-  with_environment = false
 }
 
 mojom("test_interfaces_experimental") {
@@ -45,8 +41,6 @@
   sources = [
     "test_unions.mojom",
   ]
-
-  with_environment = false
 }
 
 mojom("test_associated_interfaces") {
@@ -57,8 +51,6 @@
     "test_associated_interfaces.mojom",
     "validation_test_associated_interfaces.mojom",
   ]
-
-  with_environment = false
 }
 
 mojom("versioning_test_service_interfaces") {
@@ -67,8 +59,6 @@
   sources = [
     "versioning_test_service.mojom",
   ]
-
-  with_environment = false
 }
 
 mojom("versioning_test_client_interfaces") {
@@ -77,8 +67,6 @@
   sources = [
     "versioning_test_client.mojom",
   ]
-
-  with_environment = false
 }
 
 mojom("test_interfaces_chromium") {
@@ -91,8 +79,6 @@
   variant = "chromium"
   typemaps = [ "chromium_test.typemap" ]
 
-  with_environment = false
-
   public_deps = [
     ":test_interfaces",
   ]
@@ -108,8 +94,6 @@
   variant = "blink"
   typemaps = [ "blink_test.typemap" ]
 
-  with_environment = false
-
   public_deps = [
     ":test_interfaces",
   ]
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl
index 447b6a4..b22f8530 100644
--- a/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl
+++ b/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl
@@ -33,7 +33,6 @@
 #include "mojo/public/cpp/bindings/lib/validate_params.h"
 #include "mojo/public/cpp/bindings/lib/validation_errors.h"
 #include "mojo/public/cpp/bindings/lib/validation_util.h"
-#include "mojo/public/cpp/environment/lib/scoped_task_tracking.h"
 #include "mojo/public/interfaces/bindings/interface_control_messages.mojom.h"
 
 {%- for namespace in namespaces_as_array %}
diff --git a/mojo/public/tools/bindings/mojom.gni b/mojo/public/tools/bindings/mojom.gni
index 6e2a62a..d8923dd 100644
--- a/mojo/public/tools/bindings/mojom.gni
+++ b/mojo/public/tools/bindings/mojom.gni
@@ -46,11 +46,6 @@
 #   import_dirs (optional)
 #       List of import directories that will get added when processing sources.
 #
-#   with_environment (optional)
-#       Set to |false| to omit an implicit bindings dependency on the Chromium
-#       Mojo environment implementation. Defaults to |true| and in general
-#       should only be overridden by mojom targets within the Mojo EDK.
-#
 #   typemaps (optional)
 #       A list of typemap files to apply during bindings generation.
 #
@@ -250,9 +245,6 @@
         full_name = get_label_info(d, "label_no_toolchain")
         deps += [ "${full_name}_${cpp_sources_suffix}" ]
       }
-      if (!defined(invoker.with_environment) || invoker.with_environment) {
-        deps += [ "//mojo/environment:chromium" ]
-      }
     }
   }
 
diff --git a/mojo/services/network/public/cpp/BUILD.gn b/mojo/services/network/public/cpp/BUILD.gn
index 6bb891b..8c2734e 100644
--- a/mojo/services/network/public/cpp/BUILD.gn
+++ b/mojo/services/network/public/cpp/BUILD.gn
@@ -16,7 +16,6 @@
   deps = [
     "../interfaces",
     "//base",
-    "//mojo/environment:chromium",
     "//mojo/message_pump",
     "//mojo/public/c/system",
     "//mojo/public/cpp/system",
diff --git a/mojo/shell/public/cpp/BUILD.gn b/mojo/shell/public/cpp/BUILD.gn
index e2cfbc8e..b1f0345 100644
--- a/mojo/shell/public/cpp/BUILD.gn
+++ b/mojo/shell/public/cpp/BUILD.gn
@@ -86,7 +86,6 @@
     "//base/test:test_support",
     "//mojo/logging",
     "//mojo/public/cpp/bindings",
-    "//mojo/public/cpp/environment",
     "//mojo/public/cpp/system",
     "//mojo/shell/public/interfaces:interfaces_cpp_sources",
   ]
@@ -111,7 +110,6 @@
     "//base/test:test_support",
     "//mojo/logging",
     "//mojo/public/cpp/bindings",
-    "//mojo/public/cpp/environment",
     "//mojo/public/cpp/system",
     "//mojo/shell/background:lib",
     "//mojo/shell/public/interfaces:interfaces_cpp_sources",
diff --git a/mojo/shell/public/cpp/connector.h b/mojo/shell/public/cpp/connector.h
index be6ba43..804eb03d 100644
--- a/mojo/shell/public/cpp/connector.h
+++ b/mojo/shell/public/cpp/connector.h
@@ -62,6 +62,12 @@
       connection->GetInterface(ptr);
   }
   template <typename Interface>
+  void ConnectToInterface(const Identity& target,
+                          InterfacePtr<Interface>* ptr) {
+    ConnectParams params(target);
+    return ConnectToInterface(&params, ptr);
+  }
+  template <typename Interface>
   void ConnectToInterface(const std::string& name,
                           InterfacePtr<Interface>* ptr) {
     ConnectParams params(name);
diff --git a/mojo/shell/public/cpp/lib/application_test_base.cc b/mojo/shell/public/cpp/lib/application_test_base.cc
index e2e5826..dcd7dc33 100644
--- a/mojo/shell/public/cpp/lib/application_test_base.cc
+++ b/mojo/shell/public/cpp/lib/application_test_base.cc
@@ -6,9 +6,9 @@
 
 #include "base/command_line.h"
 #include "base/logging.h"
+#include "base/message_loop/message_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "mojo/public/cpp/bindings/binding.h"
-#include "mojo/public/cpp/environment/environment.h"
 #include "mojo/public/cpp/system/message_pipe.h"
 #include "mojo/shell/public/cpp/application_test_base.h"
 #include "mojo/shell/public/cpp/shell_connection.h"
@@ -70,7 +70,7 @@
 MojoResult RunAllTests(MojoHandle shell_client_request_handle) {
   {
     // This loop is used for init, and then destroyed before running tests.
-    Environment::InstantiateDefaultRunLoop();
+    base::MessageLoop message_loop;
 
     // Grab the shell handle.
     ShellGrabber grabber(
@@ -97,8 +97,6 @@
     argv[argc] = nullptr;
 
     testing::InitGoogleTest(&argc, const_cast<char**>(&(argv[0])));
-
-    Environment::DestroyDefaultRunLoop();
   }
 
   int result = RUN_ALL_TESTS();
@@ -140,8 +138,12 @@
 void ApplicationTestBase::SetUp() {
   // A run loop is recommended for ShellConnection initialization and
   // communication.
-  if (ShouldCreateDefaultRunLoop())
-    Environment::InstantiateDefaultRunLoop();
+  if (ShouldCreateDefaultRunLoop()) {
+    CHECK(!base::MessageLoop::current());
+    // Not leaked: accessible from |base::MessageLoop::current()|.
+    base::MessageLoop* message_loop = new base::MessageLoop();
+    CHECK_EQ(message_loop, base::MessageLoop::current());
+  }
 
   CHECK(g_shell_client_request.is_pending());
   CHECK(g_connector);
@@ -156,8 +158,11 @@
 
   test_helper_.reset();
 
-  if (ShouldCreateDefaultRunLoop())
-    Environment::DestroyDefaultRunLoop();
+  if (ShouldCreateDefaultRunLoop()) {
+    CHECK(base::MessageLoop::current());
+    delete base::MessageLoop::current();
+    CHECK(!base::MessageLoop::current());
+  }
 }
 
 bool ApplicationTestBase::ShouldCreateDefaultRunLoop() {
diff --git a/mojo/shell/public/interfaces/shell.mojom b/mojo/shell/public/interfaces/shell.mojom
index 1076127..f29df88 100644
--- a/mojo/shell/public/interfaces/shell.mojom
+++ b/mojo/shell/public/interfaces/shell.mojom
@@ -67,7 +67,6 @@
   // creation.
   CreateInstance(ShellClientFactory factory,
                  Identity target,
-                 CapabilityFilter filter,
                  PIDReceiver& pid_receiver) => (ConnectResult result);
 
   // The listener is removed when the |listener| pipe is closed.
diff --git a/mojo/shell/shell.cc b/mojo/shell/shell.cc
index 4955c97..087c0be1 100644
--- a/mojo/shell/shell.cc
+++ b/mojo/shell/shell.cc
@@ -213,9 +213,31 @@
   // mojom::Shell implementation:
   void CreateInstance(mojom::ShellClientFactoryPtr factory,
                       mojom::IdentityPtr target,
-                      mojom::CapabilityFilterPtr filter,
                       mojom::PIDReceiverRequest pid_receiver,
                       const CreateInstanceCallback& callback) override {
+    // We need to bounce through the package manager to load the
+    // CapabilityFilter.
+    std::string name = target->name;
+    shell_->shell_resolver_->ResolveMojoName(name, base::Bind(
+        &mojo::shell::Shell::Instance::OnResolvedNameForCreateInstance,
+        weak_factory_.GetWeakPtr(), base::Passed(std::move(factory)),
+        base::Passed(std::move(target)), base::Passed(std::move(pid_receiver)),
+        callback));
+  }
+  void AddInstanceListener(mojom::InstanceListenerPtr listener) override {
+    // TODO(beng): this should only track the instances matching this user, and
+    // root.
+    shell_->AddInstanceListener(std::move(listener));
+  }
+
+  void OnResolvedNameForCreateInstance(mojom::ShellClientFactoryPtr factory,
+                                       mojom::IdentityPtr target,
+                                       mojom::PIDReceiverRequest pid_receiver,
+                                       const CreateInstanceCallback& callback,
+                                       const String& resolved_name,
+                                       const String& resolved_instance,
+                                       mojom::CapabilityFilterPtr filter,
+                                       const String& file_url) {
     if (!base::IsValidGUID(target->user_id))
       callback.Run(mojom::ConnectResult::INVALID_ARGUMENT);
 
@@ -228,7 +250,7 @@
 
     mojom::ShellClientRequest request;
     Instance* instance = shell_->CreateInstance(
-        target_id, filter->filter.To<CapabilityFilter>(), &request);
+      target_id, filter->filter.To<CapabilityFilter>(), &request);
     instance->pid_receiver_binding_.Bind(std::move(pid_receiver));
     instance->factory_ = std::move(factory);
     instance->factory_->CreateShellClient(std::move(request), target->name);
@@ -238,11 +260,6 @@
     // created instance is identified by |name| and may be subsequently reached
     // by client code using this identity.
   }
-  void AddInstanceListener(mojom::InstanceListenerPtr listener) override {
-    // TODO(beng): this should only track the instances matching this user, and
-    // root.
-    shell_->AddInstanceListener(std::move(listener));
-  }
 
   uint32_t GenerateUniqueID() const {
     static uint32_t id = mojom::kInvalidInstanceID;
@@ -529,8 +546,10 @@
                               mojom::CapabilityFilterPtr base_filter,
                               const String& file_url) {
   std::string instance_name = params->target().instance();
-  if (instance_name == GetNamePath(params->target().name()))
+  if (instance_name == GetNamePath(params->target().name()) &&
+      resolved_instance != GetNamePath(resolved_name)) {
     instance_name = resolved_instance;
+  }
   Identity target(params->target().name(), params->target().user_id(),
                   instance_name);
   params->set_target(target);
@@ -562,7 +581,7 @@
     // from the original request rather than for the package itself, which will
     // always be the same.
     CreateShellClient(
-        source, Identity(resolved_name, target.user_id(), resolved_instance),
+        source, Identity(resolved_name, target.user_id(), instance_name),
         target.name(), std::move(request));
   } else {
     bool start_sandboxed = false;
diff --git a/mojo/shell/tests/connect/connect_test.mojom b/mojo/shell/tests/connect/connect_test.mojom
index 3eeaa12..ba29865 100644
--- a/mojo/shell/tests/connect/connect_test.mojom
+++ b/mojo/shell/tests/connect/connect_test.mojom
@@ -6,6 +6,7 @@
 
 interface ConnectTestService {
   GetTitle() => (string title);
+  GetInstance() => (string instance);
 };
 
 // Interface implemented by a standalone (non-package) app.
@@ -14,8 +15,6 @@
   // the standalone app's CapabilityFilter, but whose enclosing package is not.
   // The connection should be blocked and title should be "uninitialized".
   ConnectToAllowedAppInBlockedPackage() => (string title);
-
-  GetInstance() => (string instance);
 };
 
 struct ConnectionState {
diff --git a/mojo/shell/tests/connect/connect_test_app.cc b/mojo/shell/tests/connect/connect_test_app.cc
index 205ddcf..86ae235 100644
--- a/mojo/shell/tests/connect/connect_test_app.cc
+++ b/mojo/shell/tests/connect/connect_test_app.cc
@@ -93,6 +93,9 @@
   void GetTitle(const GetTitleCallback& callback) override {
     callback.Run("APP");
   }
+  void GetInstance(const GetInstanceCallback& callback) override {
+    callback.Run(identity_.instance());
+  }
 
   // test::mojom::StandaloneApp:
   void ConnectToAllowedAppInBlockedPackage(
@@ -116,9 +119,6 @@
       run_loop.Run();
     }
   }
-  void GetInstance(const GetInstanceCallback& callback) override {
-    callback.Run(identity_.instance());
-  }
 
   // test::mojom::BlockedInterface:
   void GetTitleBlocked(const GetTitleBlockedCallback& callback) override {
diff --git a/mojo/shell/tests/connect/connect_test_package.cc b/mojo/shell/tests/connect/connect_test_package.cc
index 7956425..6f365e1c 100644
--- a/mojo/shell/tests/connect/connect_test_package.cc
+++ b/mojo/shell/tests/connect/connect_test_package.cc
@@ -52,8 +52,7 @@
   // mojo::ShellClient:
   void Initialize(Connector* connector, const Identity& identity,
                   uint32_t id) override {
-    name_ = identity.name();
-    userid_ = identity.user_id();
+    identity_ = identity;
     id_ = id;
     bindings_.set_connection_error_handler(
         base::Bind(&ProvidedShellClient::OnConnectionError,
@@ -69,9 +68,9 @@
     state->connection_remote_name = connection->GetRemoteIdentity().name();
     state->connection_remote_userid = connection->GetRemoteIdentity().user_id();
     state->connection_remote_id = remote_id;
-    state->initialize_local_name = name_;
+    state->initialize_local_name = identity_.name();
     state->initialize_id = id_;
-    state->initialize_userid = userid_;
+    state->initialize_userid = identity_.user_id();
     connection->GetInterface(&caller_);
     caller_->ConnectionAccepted(std::move(state));
 
@@ -94,6 +93,9 @@
   void GetTitle(const GetTitleCallback& callback) override {
     callback.Run(title_);
   }
+  void GetInstance(const GetInstanceCallback& callback) override {
+    callback.Run(identity_.instance());
+  }
 
   // test::mojom::BlockedInterface:
   void GetTitleBlocked(const GetTitleBlockedCallback& callback) override {
@@ -112,9 +114,8 @@
       base::MessageLoop::current()->QuitWhenIdle();
   }
 
-  std::string name_;
+  Identity identity_;
   uint32_t id_ = shell::mojom::kInvalidInstanceID;
-  std::string userid_ = mojom::kRootUserID;
   const std::string title_;
   mojom::ShellClientRequest request_;
   test::mojom::ExposedInterfacePtr caller_;
@@ -138,6 +139,7 @@
   // mojo::ShellClient:
   void Initialize(Connector* connector, const Identity& identity,
                   uint32_t id) override {
+    identity_ = identity;
     bindings_.set_connection_error_handler(
         base::Bind(&ConnectTestShellClient::OnConnectionError,
                    base::Unretained(this)));
@@ -179,12 +181,16 @@
   void GetTitle(const GetTitleCallback& callback) override {
     callback.Run("ROOT");
   }
+  void GetInstance(const GetInstanceCallback& callback) override {
+    callback.Run(identity_.instance());
+  }
 
   void OnConnectionError() {
     if (bindings_.empty())
       base::MessageLoop::current()->QuitWhenIdle();
   }
 
+  Identity identity_;
   std::vector<scoped_ptr<ShellClient>> delegates_;
   BindingSet<mojom::ShellClientFactory> shell_client_factory_bindings_;
   BindingSet<test::mojom::ConnectTestService> bindings_;
diff --git a/mojo/shell/tests/connect/connect_unittest.cc b/mojo/shell/tests/connect/connect_unittest.cc
index e28a635..38aee7a 100644
--- a/mojo/shell/tests/connect/connect_unittest.cc
+++ b/mojo/shell/tests/connect/connect_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/run_loop.h"
 #include "base/test/test_suite.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
+#include "mojo/shell/public/cpp/names.h"
 #include "mojo/shell/public/cpp/shell_test.h"
 #include "mojo/shell/public/interfaces/shell.mojom.h"
 #include "mojo/shell/tests/connect/connect_test.mojom.h"
@@ -136,20 +137,18 @@
   scoped_ptr<Connection> connection_a1 = ConnectTo(&params_a);
   scoped_ptr<Connection> connection_a2 = ConnectTo(&params_a);
   std::string instance_a1, instance_a2;
-  test::mojom::StandaloneAppPtr standalone_app_a1;
+  test::mojom::ConnectTestServicePtr service_a1;
   {
-    connection_a1->GetInterface(&standalone_app_a1);
+    connection_a1->GetInterface(&service_a1);
     base::RunLoop loop;
-    standalone_app_a1->GetInstance(
-        base::Bind(&ReceiveTitle, &instance_a1, &loop));
+    service_a1->GetInstance(base::Bind(&ReceiveTitle, &instance_a1, &loop));
     loop.Run();
   }
-  test::mojom::StandaloneAppPtr standalone_app_a2;
+  test::mojom::ConnectTestServicePtr service_a2;
   {
-    connection_a2->GetInterface(&standalone_app_a2);
+    connection_a2->GetInterface(&service_a2);
     base::RunLoop loop;
-    standalone_app_a2->GetInstance(
-        base::Bind(&ReceiveTitle, &instance_a2, &loop));
+    service_a2->GetInstance(base::Bind(&ReceiveTitle, &instance_a2, &loop));
     loop.Run();
   }
   EXPECT_EQ(instance_a1, instance_a2);
@@ -158,18 +157,43 @@
       Identity(kTestAppName, mojom::kInheritUserID, "B"));
   scoped_ptr<Connection> connection_b = ConnectTo(&params_b);
   std::string instance_b;
-  test::mojom::StandaloneAppPtr standalone_app_b;
+  test::mojom::ConnectTestServicePtr service_b;
   {
-    connection_b->GetInterface(&standalone_app_b);
+    connection_b->GetInterface(&service_b);
     base::RunLoop loop;
-    standalone_app_b->GetInstance(
-        base::Bind(&ReceiveTitle, &instance_b, &loop));
+    service_b->GetInstance(base::Bind(&ReceiveTitle, &instance_b, &loop));
     loop.Run();
   }
 
   EXPECT_NE(instance_a1, instance_b);
 }
 
+// When both the unresolved and resolved instance names are their default
+// values, the instance name from the unresolved name must be used.
+// (The case where the instance names differ is covered by
+// LifecycleTest.PackagedApp_CrashCrashesOtherProvidedApp).
+TEST_F(ConnectTest, PreferUnresolvedDefaultInstanceName) {
+  // Connect to an app with no manifest-supplied instance name provided by a
+  // package, the instance name must be derived from the application instance
+  // name, not the package.
+  scoped_ptr<Connection> connection = connector()->Connect(kTestAppName);
+  {
+    base::RunLoop loop;
+    connection->AddConnectionCompletedClosure(base::Bind(&QuitLoop, &loop));
+    loop.Run();
+  }
+
+  std::string instance;
+  {
+    test::mojom::ConnectTestServicePtr service;
+    connection->GetInterface(&service);
+    base::RunLoop loop;
+    service->GetInstance(base::Bind(&ReceiveTitle, &instance, &loop));
+    loop.Run();
+  }
+  EXPECT_EQ(GetNamePath(kTestAppName), instance);
+}
+
 // BlockedInterface should not be exposed to this application because it is not
 // in our CapabilityFilter whitelist.
 TEST_F(ConnectTest, BlockedInterface) {
diff --git a/mojo/shell/tests/lifecycle/exe_manifest.json b/mojo/shell/tests/lifecycle/exe_manifest.json
index 0308da76..2e6d580 100644
--- a/mojo/shell/tests/lifecycle/exe_manifest.json
+++ b/mojo/shell/tests/lifecycle/exe_manifest.json
@@ -1,5 +1,5 @@
 {
   "name": "exe:lifecycle_unittest_exe",
   "display_name": "Lifecycle Unittest Exe",
-  "capabilities": {}
+  "capabilities": { "*": ["*"] }
 }
diff --git a/mojo/shell/tests/lifecycle/lifecycle_unittest.cc b/mojo/shell/tests/lifecycle/lifecycle_unittest.cc
index e85d08b..a9829f86 100644
--- a/mojo/shell/tests/lifecycle/lifecycle_unittest.cc
+++ b/mojo/shell/tests/lifecycle/lifecycle_unittest.cc
@@ -203,12 +203,6 @@
     mojo::ScopedMessagePipeHandle pipe =
         mojo::edk::CreateParentMessagePipe(primordial_pipe_token);
 
-    mojo::shell::mojom::CapabilityFilterPtr filter(
-        mojo::shell::mojom::CapabilityFilter::New());
-    mojo::Array<mojo::String> test_interfaces;
-    test_interfaces.push_back("*");
-    filter->filter.insert("*", std::move(test_interfaces));
-
     mojo::shell::mojom::ShellPtr shell;
     connector()->ConnectToInterface("mojo:shell", &shell);
 
@@ -216,12 +210,10 @@
     factory.Bind(mojo::InterfacePtrInfo<mojo::shell::mojom::ShellClientFactory>(
         std::move(pipe), 0u));
     base::RunLoop loop;
-    mojo::shell::mojom::IdentityPtr target(mojo::shell::mojom::Identity::New());
-    target->name = kTestExeName;
-    target->user_id = mojom::kInheritUserID;
-    target->instance = "";
-    shell->CreateInstance(std::move(factory), std::move(target),
-                          std::move(filter), std::move(request),
+    mojo::Identity target(kTestExeName, mojom::kInheritUserID);
+    shell->CreateInstance(std::move(factory),
+                          mojo::shell::mojom::Identity::From(target),
+                          std::move(request),
                           base::Bind(&LifecycleTest::OnConnectionCompleted,
                                      base::Unretained(this), &loop));
     loop.Run();
diff --git a/mojo/shell/tests/shell/BUILD.gn b/mojo/shell/tests/shell/BUILD.gn
index 6742da11..fc2c25a6 100644
--- a/mojo/shell/tests/shell/BUILD.gn
+++ b/mojo/shell/tests/shell/BUILD.gn
@@ -76,8 +76,15 @@
 
   deps = [
     ":interfaces",
+    ":target_manifest",
     "//base",
     "//mojo/shell/public/cpp",
     "//mojo/shell/runner/child:test_native_main",
   ]
 }
+
+mojo_application_manifest("target_manifest") {
+  type = "exe"
+  application_name = "shell_unittest_target"
+  source = "target_manifest.json"
+}
diff --git a/mojo/shell/tests/shell/driver.cc b/mojo/shell/tests/shell/driver.cc
index 68254f8..7d9c8a7 100644
--- a/mojo/shell/tests/shell/driver.cc
+++ b/mojo/shell/tests/shell/driver.cc
@@ -85,13 +85,6 @@
     mojo::ScopedMessagePipeHandle pipe =
         mojo::edk::CreateParentMessagePipe(primordial_pipe_token);
 
-    mojo::shell::mojom::CapabilityFilterPtr filter(
-        mojo::shell::mojom::CapabilityFilter::New());
-    mojo::Array<mojo::String> test_interfaces;
-    test_interfaces.push_back(
-        mojo::shell::test::mojom::CreateInstanceTest::Name_);
-    filter->filter.insert("mojo:shell_unittest", std::move(test_interfaces));
-
     mojo::shell::mojom::ShellClientFactoryPtr factory;
     factory.Bind(mojo::InterfacePtrInfo<mojo::shell::mojom::ShellClientFactory>(
         std::move(pipe), 0u));
@@ -103,7 +96,7 @@
     target->user_id = mojo::shell::mojom::kInheritUserID;
     target->instance = "";
     shell->CreateInstance(std::move(factory), std::move(target),
-                          std::move(filter), std::move(request),
+                          std::move(request),
                           base::Bind(&Driver::OnConnectionCompleted,
                                      base::Unretained(this)));
 
diff --git a/mojo/shell/tests/shell/target_manifest.json b/mojo/shell/tests/shell/target_manifest.json
new file mode 100644
index 0000000..68ddc21
--- /dev/null
+++ b/mojo/shell/tests/shell/target_manifest.json
@@ -0,0 +1,5 @@
+{
+  "name": "exe:shell_unittest_target",
+  "display_name": "Shell Unittest: Target",
+  "capabilities": { "mojo:shell_unittest": [ "mojo::shell::test::mojom::CreateInstanceTest" ] }
+}
diff --git a/net/BUILD.gn b/net/BUILD.gn
index 4961769..3788d21 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -1590,7 +1590,6 @@
       ":net_browser_services",
       ":net_utility_services",
       "//mojo/edk/system",
-      "//mojo/environment:chromium",
     ]
   } else {
     sources -= [
diff --git a/net/cookies/cookie_monster.cc b/net/cookies/cookie_monster.cc
index eff98e32..c2b1871 100644
--- a/net/cookies/cookie_monster.cc
+++ b/net/cookies/cookie_monster.cc
@@ -349,6 +349,7 @@
       started_fetching_all_cookies_(false),
       finished_fetching_all_cookies_(false),
       fetch_strategy_(kUnknownFetch),
+      seen_global_task_(false),
       store_(store),
       last_access_threshold_(base::TimeDelta::FromMilliseconds(
           last_access_threshold_milliseconds)),
@@ -1444,12 +1445,27 @@
 void CookieMonster::InvokeQueue() {
   DCHECK(thread_checker_.CalledOnValidThread());
 
+  // Move all per-key tasks into the global queue, if there are any.  This is
+  // protection about a race where the store learns about all cookies loading
+  // before it learned about the cookies for a key loading.
+
+  // Needed to prevent any recursively queued tasks from going back into the
+  // per-key queues.
+  seen_global_task_ = true;
+  for (const auto& tasks_for_key : tasks_pending_for_key_) {
+    tasks_pending_.insert(tasks_pending_.begin(), tasks_for_key.second.begin(),
+                          tasks_for_key.second.end());
+  }
+  tasks_pending_for_key_.clear();
+
   while (!tasks_pending_.empty()) {
     scoped_refptr<CookieMonsterTask> request_task = tasks_pending_.front();
-    tasks_pending_.pop();
+    tasks_pending_.pop_front();
     request_task->Run();
   }
 
+  DCHECK(tasks_pending_for_key_.empty());
+
   finished_fetching_all_cookies_ = true;
   creation_times_.clear();
   keys_loaded_.clear();
@@ -2223,9 +2239,10 @@
 
   MarkCookieStoreAsInitialized();
   FetchAllCookiesIfNecessary();
+  seen_global_task_ = true;
 
   if (!finished_fetching_all_cookies_ && store_.get()) {
-    tasks_pending_.push(task_item);
+    tasks_pending_.push_back(task_item);
     return;
   }
 
@@ -2235,8 +2252,6 @@
 void CookieMonster::DoCookieTaskForURL(
     const scoped_refptr<CookieMonsterTask>& task_item,
     const GURL& url) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-
   MarkCookieStoreAsInitialized();
   if (ShouldFetchAllCookiesWhenFetchingAnyCookie())
     FetchAllCookiesIfNecessary();
@@ -2244,6 +2259,15 @@
   // If cookies for the requested domain key (eTLD+1) have been loaded from DB
   // then run the task, otherwise load from DB.
   if (!finished_fetching_all_cookies_ && store_.get()) {
+    // If a global task has been previously seen, queue the task as a global
+    // task. Note that the CookieMonster may be in the middle of executing
+    // the global queue, |tasks_pending_| may be empty, which is why another
+    // bool is needed.
+    if (seen_global_task_) {
+      tasks_pending_.push_back(task_item);
+      return;
+    }
+
     // Checks if the domain key has been loaded.
     std::string key(cookie_util::GetEffectiveDomain(url.scheme(), url.host()));
     if (keys_loaded_.find(key) == keys_loaded_.end()) {
diff --git a/net/cookies/cookie_monster.h b/net/cookies/cookie_monster.h
index 7a06509..14c5a08 100644
--- a/net/cookies/cookie_monster.h
+++ b/net/cookies/cookie_monster.h
@@ -652,7 +652,14 @@
 
   // Queues tasks that are blocked until all cookies are loaded from the backend
   // store.
-  std::queue<scoped_refptr<CookieMonsterTask>> tasks_pending_;
+  std::deque<scoped_refptr<CookieMonsterTask>> tasks_pending_;
+
+  // Once a global cookie task has been seen, all per-key tasks must be put in
+  // |tasks_pending_| instead of |tasks_pending_for_key_| to ensure a reasonable
+  // view of the cookie store. This more to ensure fancy cookie export/import
+  // code has a consistent view of the CookieStore, rather than out of concern
+  // for typical use.
+  bool seen_global_task_;
 
   scoped_refptr<PersistentCookieStore> store_;
 
diff --git a/net/cookies/cookie_monster_store_test.cc b/net/cookies/cookie_monster_store_test.cc
index 57cc52f..4271298 100644
--- a/net/cookies/cookie_monster_store_test.cc
+++ b/net/cookies/cookie_monster_store_test.cc
@@ -25,9 +25,19 @@
 LoadedCallbackTask::~LoadedCallbackTask() {
 }
 
+CookieStoreCommand::CookieStoreCommand(
+    Type type,
+    const CookieMonster::PersistentCookieStore::LoadedCallback& loaded_callback,
+    const std::string& key)
+    : type(type), loaded_callback(loaded_callback), key(key) {}
+
+CookieStoreCommand::CookieStoreCommand(Type type, const CanonicalCookie& cookie)
+    : type(type), cookie(cookie) {}
+
+CookieStoreCommand::~CookieStoreCommand() {}
+
 MockPersistentCookieStore::MockPersistentCookieStore()
-    : load_return_value_(true), loaded_(false) {
-}
+    : store_load_commands_(false), load_return_value_(true), loaded_(false) {}
 
 void MockPersistentCookieStore::SetLoadExpectation(
     bool return_value,
@@ -37,6 +47,11 @@
 }
 
 void MockPersistentCookieStore::Load(const LoadedCallback& loaded_callback) {
+  if (store_load_commands_) {
+    commands_.push_back(
+        CookieStoreCommand(CookieStoreCommand::LOAD, loaded_callback, ""));
+    return;
+  }
   std::vector<CanonicalCookie*> out_cookies;
   if (load_return_value_) {
     out_cookies = load_result_;
@@ -51,6 +66,11 @@
 void MockPersistentCookieStore::LoadCookiesForKey(
     const std::string& key,
     const LoadedCallback& loaded_callback) {
+  if (store_load_commands_) {
+    commands_.push_back(CookieStoreCommand(
+        CookieStoreCommand::LOAD_COOKIES_FOR_KEY, loaded_callback, key));
+    return;
+  }
   if (!loaded_) {
     Load(loaded_callback);
   } else {
diff --git a/net/cookies/cookie_monster_store_test.h b/net/cookies/cookie_monster_store_test.h
index bb8239c3..e20584d 100644
--- a/net/cookies/cookie_monster_store_test.h
+++ b/net/cookies/cookie_monster_store_test.h
@@ -51,9 +51,11 @@
   DISALLOW_COPY_AND_ASSIGN(LoadedCallbackTask);
 };  // Wrapper class LoadedCallbackTask
 
-// Describes a call to one of the 3 functions of PersistentCookieStore.
+// Describes a call to one of the 5 functions of PersistentCookieStore.
 struct CookieStoreCommand {
   enum Type {
+    LOAD,
+    LOAD_COOKIES_FOR_KEY,
     // UPDATE_ACCESS_TIME is not included in this list, because get cookie
     // commands may or may not end updating the access time, unless they have
     // the option set not to do so.
@@ -61,10 +63,27 @@
     REMOVE,
   };
 
-  CookieStoreCommand(Type type, const CanonicalCookie& cookie)
-      : type(type), cookie(cookie) {}
+  // Constructor for LOAD and LOAD_COOKIES_FOR_KEY calls.  |key| should be empty
+  // for LOAD_COOKIES_FOR_KEY.
+  CookieStoreCommand(Type type,
+                     const CookieMonster::PersistentCookieStore::LoadedCallback&
+                         loaded_callback,
+                     const std::string& key);
+
+  // Constructor for ADD, UPDATE_ACCESS_TIME, and REMOVE calls.
+  CookieStoreCommand(Type type, const CanonicalCookie& cookie);
+
+  ~CookieStoreCommand();
 
   Type type;
+
+  // Only non-null for LOAD and LOAD_COOKIES_FOR_KEY.
+  CookieMonster::PersistentCookieStore::LoadedCallback loaded_callback;
+
+  // Only non-empty for LOAD_COOKIES_FOR_KEY.
+  std::string key;
+
+  // Only non-null for ADD, UPDATE_ACCESS_TIME, and REMOVE.
   CanonicalCookie cookie;
 };
 
@@ -77,6 +96,12 @@
 
   MockPersistentCookieStore();
 
+  // When set, Load() and LoadCookiesForKey() calls are store in the command
+  // list, rather than being automatically executed. Defaults to false.
+  void set_store_load_commands(bool store_load_commands) {
+    store_load_commands_ = store_load_commands;
+  }
+
   void SetLoadExpectation(bool return_value,
                           const std::vector<CanonicalCookie*>& result);
 
@@ -103,6 +128,8 @@
  private:
   CommandList commands_;
 
+  bool store_load_commands_;
+
   // Deferred result to use when Load() is called.
   bool load_return_value_;
   std::vector<CanonicalCookie*> load_result_;
diff --git a/net/cookies/cookie_monster_unittest.cc b/net/cookies/cookie_monster_unittest.cc
index 8e61dad..08a57ff 100644
--- a/net/cookies/cookie_monster_unittest.cc
+++ b/net/cookies/cookie_monster_unittest.cc
@@ -2003,6 +2003,199 @@
   }
 }
 
+// Tests that if the main load event happens before the loaded event for a
+// particular key, the tasks for that key run first.
+TEST_F(CookieMonsterTest, WhileLoadingLoadCompletesBeforeKeyLoadCompletes) {
+  const GURL kUrl = GURL(kTopLevelDomainPlus1);
+
+  scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore);
+  store->set_store_load_commands(true);
+  scoped_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr));
+
+  // Get all cookies task that queues a task to set a cookie when executed.
+  ResultSavingCookieCallback<bool> set_cookie_callback;
+  cm->SetCookieWithOptionsAsync(
+      kUrl, "a=b", CookieOptions(),
+      base::Bind(&ResultSavingCookieCallback<bool>::Run,
+                 base::Unretained(&set_cookie_callback)));
+
+  GetCookieListCallback get_cookie_list_callback1;
+  cm->GetAllCookiesAsync(
+      base::Bind(&GetCookieListCallback::Run,
+                 base::Unretained(&get_cookie_list_callback1)));
+
+  // Two load events should have been queued.
+  ASSERT_EQ(2u, store->commands().size());
+  ASSERT_EQ(CookieStoreCommand::LOAD, store->commands()[0].type);
+  ASSERT_EQ(CookieStoreCommand::LOAD_COOKIES_FOR_KEY,
+            store->commands()[1].type);
+
+  // The main load completes first (With no cookies).
+  store->commands()[0].loaded_callback.Run(std::vector<CanonicalCookie*>());
+
+  // The tasks should run in order, and the get should see the cookies.
+
+  set_cookie_callback.WaitUntilDone();
+  EXPECT_TRUE(set_cookie_callback.result());
+
+  get_cookie_list_callback1.WaitUntilDone();
+  EXPECT_EQ(1u, get_cookie_list_callback1.cookies().size());
+
+  // The loaded for key event completes late, with not cookies (Since they
+  // were already loaded).
+  store->commands()[1].loaded_callback.Run(std::vector<CanonicalCookie*>());
+
+  // The just set cookie should still be in the store.
+  GetCookieListCallback get_cookie_list_callback2;
+  cm->GetAllCookiesAsync(
+      base::Bind(&GetCookieListCallback::Run,
+                 base::Unretained(&get_cookie_list_callback2)));
+  get_cookie_list_callback2.WaitUntilDone();
+  EXPECT_EQ(1u, get_cookie_list_callback2.cookies().size());
+}
+
+// Tests that case that DeleteAll is waiting for load to complete, and then a
+// get is queued. The get should wait to run until after all the cookies are
+// retrieved, and should return nothing, since all cookies were just deleted.
+TEST_F(CookieMonsterTest, WhileLoadingDeleteAllGetForURL) {
+  const GURL kUrl = GURL(kTopLevelDomainPlus1);
+
+  scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore);
+  store->set_store_load_commands(true);
+  scoped_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr));
+
+  ResultSavingCookieCallback<int> delete_callback;
+  cm->DeleteAllAsync(base::Bind(&ResultSavingCookieCallback<int>::Run,
+                                base::Unretained(&delete_callback)));
+
+  GetCookieListCallback get_cookie_list_callback;
+  cm->GetCookieListWithOptionsAsync(
+      kUrl, CookieOptions(),
+      base::Bind(&GetCookieListCallback::Run,
+                 base::Unretained(&get_cookie_list_callback)));
+
+  // Only the main load should have been queued.
+  ASSERT_EQ(1u, store->commands().size());
+  ASSERT_EQ(CookieStoreCommand::LOAD, store->commands()[0].type);
+
+  std::vector<CanonicalCookie*> cookies;
+  // When passed to the CookieMonster, it takes ownership of the pointed to
+  // cookies.
+  cookies.push_back(
+      CanonicalCookie::Create(kUrl, "a=b", base::Time(), CookieOptions())
+          .release());
+  ASSERT_TRUE(cookies[0]);
+  store->commands()[0].loaded_callback.Run(cookies);
+
+  delete_callback.WaitUntilDone();
+  EXPECT_EQ(1, delete_callback.result());
+
+  get_cookie_list_callback.WaitUntilDone();
+  EXPECT_EQ(0u, get_cookie_list_callback.cookies().size());
+}
+
+// Tests that a set cookie call sandwiched between two get all cookies, all
+// before load completes, affects the first but not the second. The set should
+// also not trigger a LoadCookiesForKey (As that could complete only after the
+// main load for the store).
+TEST_F(CookieMonsterTest, WhileLoadingGetAllSetGetAll) {
+  const GURL kUrl = GURL(kTopLevelDomainPlus1);
+
+  scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore);
+  store->set_store_load_commands(true);
+  scoped_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr));
+
+  GetCookieListCallback get_cookie_list_callback1;
+  cm->GetAllCookiesAsync(
+      base::Bind(&GetCookieListCallback::Run,
+                 base::Unretained(&get_cookie_list_callback1)));
+
+  ResultSavingCookieCallback<bool> set_cookie_callback;
+  cm->SetCookieWithOptionsAsync(
+      kUrl, "a=b", CookieOptions(),
+      base::Bind(&ResultSavingCookieCallback<bool>::Run,
+                 base::Unretained(&set_cookie_callback)));
+
+  GetCookieListCallback get_cookie_list_callback2;
+  cm->GetAllCookiesAsync(
+      base::Bind(&GetCookieListCallback::Run,
+                 base::Unretained(&get_cookie_list_callback2)));
+
+  // Only the main load should have been queued.
+  ASSERT_EQ(1u, store->commands().size());
+  ASSERT_EQ(CookieStoreCommand::LOAD, store->commands()[0].type);
+
+  // The load completes (With no cookies).
+  store->commands()[0].loaded_callback.Run(std::vector<CanonicalCookie*>());
+
+  get_cookie_list_callback1.WaitUntilDone();
+  EXPECT_EQ(0u, get_cookie_list_callback1.cookies().size());
+
+  set_cookie_callback.WaitUntilDone();
+  EXPECT_TRUE(set_cookie_callback.result());
+
+  get_cookie_list_callback2.WaitUntilDone();
+  EXPECT_EQ(1u, get_cookie_list_callback2.cookies().size());
+}
+
+namespace {
+
+void RunClosureOnCookieListReceived(const base::Closure& closure,
+                                    const CookieList& cookie_list) {
+  closure.Run();
+}
+
+}  // namespace
+
+// Tests that if a single cookie task is queued as a result of a task performed
+// on all cookies when loading completes, it will be run after any already
+// queued tasks.
+TEST_F(CookieMonsterTest, CheckOrderOfCookieTaskQueueWhenLoadingCompletes) {
+  const GURL kUrl = GURL(kTopLevelDomainPlus1);
+
+  scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore);
+  store->set_store_load_commands(true);
+  scoped_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr));
+
+  // Get all cookies task that queues a task to set a cookie when executed.
+  ResultSavingCookieCallback<bool> set_cookie_callback;
+  cm->GetAllCookiesAsync(base::Bind(
+      &RunClosureOnCookieListReceived,
+      base::Bind(&CookieStore::SetCookieWithOptionsAsync,
+                 base::Unretained(cm.get()), kUrl, "a=b", CookieOptions(),
+                 base::Bind(&ResultSavingCookieCallback<bool>::Run,
+                            base::Unretained(&set_cookie_callback)))));
+
+  // Get cookie task. Queued before the delete task is executed, so should not
+  // see the set cookie.
+  GetCookieListCallback get_cookie_list_callback1;
+  cm->GetAllCookiesAsync(
+      base::Bind(&GetCookieListCallback::Run,
+                 base::Unretained(&get_cookie_list_callback1)));
+
+  // Only the main load should have been queued.
+  ASSERT_EQ(1u, store->commands().size());
+  ASSERT_EQ(CookieStoreCommand::LOAD, store->commands()[0].type);
+
+  // The load completes.
+  store->commands()[0].loaded_callback.Run(std::vector<CanonicalCookie*>());
+
+  // The get cookies call should see no cookies set.
+  get_cookie_list_callback1.WaitUntilDone();
+  EXPECT_EQ(0u, get_cookie_list_callback1.cookies().size());
+
+  set_cookie_callback.WaitUntilDone();
+  EXPECT_TRUE(set_cookie_callback.result());
+
+  // A subsequent get cookies call should see the new cookie.
+  GetCookieListCallback get_cookie_list_callback2;
+  cm->GetAllCookiesAsync(
+      base::Bind(&GetCookieListCallback::Run,
+                 base::Unretained(&get_cookie_list_callback2)));
+  get_cookie_list_callback2.WaitUntilDone();
+  EXPECT_EQ(1u, get_cookie_list_callback2.cookies().size());
+}
+
 namespace {
 
 // Mock PersistentCookieStore that keeps track of the number of Flush() calls.
diff --git a/net/net.gyp b/net/net.gyp
index 7fe7e3d8..7730a5d 100644
--- a/net/net.gyp
+++ b/net/net.gyp
@@ -942,7 +942,6 @@
             'net',
             'net_interfaces',
             '../mojo/mojo_base.gyp:mojo_common_lib',
-            '../mojo/mojo_base.gyp:mojo_environment_chromium',
             '../mojo/mojo_base.gyp:mojo_url_type_converters',
             '../mojo/mojo_public.gyp:mojo_cpp_bindings',
 
diff --git a/remoting/protocol/authenticator.h b/remoting/protocol/authenticator.h
index 927790c..febf38c 100644
--- a/remoting/protocol/authenticator.h
+++ b/remoting/protocol/authenticator.h
@@ -17,6 +17,7 @@
 namespace remoting {
 namespace protocol {
 
+class Authenticator;
 class ChannelAuthenticator;
 
 typedef base::Callback<void(const std::string& secret)> SecretFetchedCallback;
@@ -25,18 +26,16 @@
     const SecretFetchedCallback& secret_fetched_callback)> FetchSecretCallback;
 
 // Authenticator is an abstract interface for authentication protocol
-// implementations. Different implementations of this interface may be
-// used on each side of the connection depending of type of the auth
-// protocol. Client and host will repeatedly call their Authenticators
-// and deliver the messages they generate, until successful
-// authentication is reported.
+// implementations. Different implementations of this interface may be used on
+// each side of the connection depending of type of the auth protocol. Client
+// and host will repeatedly call their Authenticators and deliver the messages
+// they generate, until successful authentication is reported.
 //
-// Authenticator may exchange multiple messages before session is
-// authenticated. Each message sent/received by an Authenticator is
-// delivered either in a session description inside session-initiate
-// and session-accept messages or in a session-info
-// message. Session-info messages are used only if authenticators need
-// to exchange more than one message.
+// Authenticator may exchange multiple messages before session is authenticated.
+// Each message sent/received by an Authenticator is delivered either in a
+// session description inside session-initiate and session-accept messages or in
+// a session-info message. Session-info messages are used only if authenticators
+// need to exchange more than one message.
 class Authenticator {
  public:
   // Allowed state transitions:
@@ -72,6 +71,14 @@
     PROTOCOL_ERROR,
   };
 
+  // Callback used for layered Authenticator implementations, particularly
+  // third-party and pairing authenticators. They use this callback to create
+  // base SPAKE2 authenticators.
+  typedef base::Callback<scoped_ptr<Authenticator>(
+      const std::string& shared_secret,
+      Authenticator::State initial_state)>
+      CreateBaseAuthenticatorCallback;
+
   // Returns true if |message| is an Authenticator message.
   static bool IsAuthenticatorMessage(const buzz::XmlElement* message);
 
@@ -90,7 +97,7 @@
   virtual State state() const = 0;
 
   // Returns whether authentication has started. The chromoting host uses this
-  // method to starts the back off process to prevent malicious clients from
+  // method to start the back off process to prevent malicious clients from
   // guessing the PIN by spamming the host with auth requests.
   virtual bool started() const = 0;
 
diff --git a/remoting/protocol/negotiating_authenticator_base.cc b/remoting/protocol/negotiating_authenticator_base.cc
index 1d25466..dbb3aac 100644
--- a/remoting/protocol/negotiating_authenticator_base.cc
+++ b/remoting/protocol/negotiating_authenticator_base.cc
@@ -13,7 +13,6 @@
 #include "base/strings/string_split.h"
 #include "remoting/base/rsa_key_pair.h"
 #include "remoting/protocol/channel_authenticator.h"
-#include "remoting/protocol/v2_authenticator.h"
 #include "third_party/webrtc/libjingle/xmllite/xmlelement.h"
 
 namespace remoting {
diff --git a/remoting/protocol/negotiating_client_authenticator.cc b/remoting/protocol/negotiating_client_authenticator.cc
index 2a2247ef..43b58254 100644
--- a/remoting/protocol/negotiating_client_authenticator.cc
+++ b/remoting/protocol/negotiating_client_authenticator.cc
@@ -42,8 +42,7 @@
   }
 }
 
-NegotiatingClientAuthenticator::~NegotiatingClientAuthenticator() {
-}
+NegotiatingClientAuthenticator::~NegotiatingClientAuthenticator() {}
 
 void NegotiatingClientAuthenticator::ProcessMessage(
     const buzz::XmlElement* message,
@@ -120,6 +119,7 @@
     // one |ThirdPartyClientAuthenticator| will need to be created per session.
     DCHECK(token_fetcher_);
     current_authenticator_.reset(new ThirdPartyClientAuthenticator(
+        base::Bind(&V2Authenticator::CreateForClient),
         std::move(token_fetcher_)));
     resume_callback.Run();
   } else {
@@ -143,7 +143,8 @@
     // If the client specified a pairing id and shared secret, then create a
     // PairingAuthenticator.
     current_authenticator_.reset(new PairingClientAuthenticator(
-        client_pairing_id_, shared_secret_, fetch_secret_callback_,
+        client_pairing_id_, shared_secret_,
+        base::Bind(&V2Authenticator::CreateForClient), fetch_secret_callback_,
         authentication_tag_));
     current_method_ = AuthenticationMethod::SPAKE2_PAIR;
   }
diff --git a/remoting/protocol/negotiating_host_authenticator.cc b/remoting/protocol/negotiating_host_authenticator.cc
index 57277ef..bcdb591c 100644
--- a/remoting/protocol/negotiating_host_authenticator.cc
+++ b/remoting/protocol/negotiating_host_authenticator.cc
@@ -175,13 +175,17 @@
     // one |ThirdPartyHostAuthenticator| will need to be created per session.
     DCHECK(token_validator_);
     current_authenticator_.reset(new ThirdPartyHostAuthenticator(
-        local_cert_, local_key_pair_, std::move(token_validator_)));
+        base::Bind(&V2Authenticator::CreateForHost, local_cert_,
+                   local_key_pair_),
+        std::move(token_validator_)));
   } else if (current_method_ == AuthenticationMethod::SPAKE2_PAIR &&
              preferred_initial_state == WAITING_MESSAGE) {
     // If the client requested Spake2Pair and sent an initial message, attempt
     // the paired connection protocol.
     current_authenticator_.reset(new PairingHostAuthenticator(
-        pairing_registry_, local_cert_, local_key_pair_, shared_secret_hash_));
+        pairing_registry_, base::Bind(&V2Authenticator::CreateForHost,
+                                      local_cert_, local_key_pair_),
+        shared_secret_hash_));
   } else {
     // In all other cases, use the V2 protocol. Note that this includes the
     // case where the protocol is Spake2Pair but the client is not yet paired.
diff --git a/remoting/protocol/pairing_authenticator_base.cc b/remoting/protocol/pairing_authenticator_base.cc
index 9a5d1fe9..3f9bcfa9 100644
--- a/remoting/protocol/pairing_authenticator_base.cc
+++ b/remoting/protocol/pairing_authenticator_base.cc
@@ -24,35 +24,27 @@
 const buzz::StaticQName kPairingErrorAttribute = { "", "error" };
 }  // namespace
 
-PairingAuthenticatorBase::PairingAuthenticatorBase()
-    : using_paired_secret_(false),
-      waiting_for_authenticator_(false),
-      weak_factory_(this) {
-}
-
-PairingAuthenticatorBase::~PairingAuthenticatorBase() {
-}
+PairingAuthenticatorBase::PairingAuthenticatorBase() : weak_factory_(this) {}
+PairingAuthenticatorBase::~PairingAuthenticatorBase() {}
 
 Authenticator::State PairingAuthenticatorBase::state() const {
-  if (waiting_for_authenticator_) {
-    return PROCESSING_MESSAGE;
-  }
-  return v2_authenticator_->state();
+  DCHECK(spake2_authenticator_);
+  return spake2_authenticator_->state();
 }
 
 bool PairingAuthenticatorBase::started() const {
-  if (!v2_authenticator_) {
+  if (!spake2_authenticator_) {
     return false;
   }
-  return v2_authenticator_->started();
+  return spake2_authenticator_->started();
 }
 
 Authenticator::RejectionReason
 PairingAuthenticatorBase::rejection_reason() const {
-  if (!v2_authenticator_) {
+  if (!spake2_authenticator_) {
     return PROTOCOL_ERROR;
   }
-  return v2_authenticator_->rejection_reason();
+  return spake2_authenticator_->rejection_reason();
 }
 
 void PairingAuthenticatorBase::ProcessMessage(
@@ -63,18 +55,17 @@
   // The client authenticator creates the underlying authenticator in the ctor
   // and the host creates it in response to the first message before deferring
   // to this class to process it. Either way, it should exist here.
-  DCHECK(v2_authenticator_);
+  DCHECK(spake2_authenticator_);
 
   // If pairing failed, and we haven't already done so, try again with the PIN.
   if (using_paired_secret_ && HasErrorMessage(message)) {
     using_paired_secret_ = false;
-    waiting_for_authenticator_ = true;
-    v2_authenticator_.reset();
-    SetAuthenticatorCallback set_authenticator = base::Bind(
-        &PairingAuthenticatorBase::SetAuthenticatorAndProcessMessage,
-        weak_factory_.GetWeakPtr(), base::Owned(new buzz::XmlElement(*message)),
-        resume_callback);
-    CreateV2AuthenticatorWithPIN(WAITING_MESSAGE, set_authenticator);
+    spake2_authenticator_.reset();
+    CreateSpakeAuthenticatorWithPin(
+        WAITING_MESSAGE, base::Bind(&PairingAuthenticatorBase::ProcessMessage,
+                                    weak_factory_.GetWeakPtr(),
+                                    base::Owned(new buzz::XmlElement(*message)),
+                                    resume_callback));
     return;
   }
 
@@ -82,7 +73,7 @@
   // check for a failed SPAKE exchange if we're using the paired secret. In
   // this case the pairing protocol can continue by communicating the error
   // to the peer and retrying with the PIN.
-  v2_authenticator_->ProcessMessage(
+  spake2_authenticator_->ProcessMessage(
       message,
       base::Bind(&PairingAuthenticatorBase::CheckForFailedSpakeExchange,
                  weak_factory_.GetWeakPtr(), resume_callback));
@@ -90,19 +81,19 @@
 
 scoped_ptr<buzz::XmlElement> PairingAuthenticatorBase::GetNextMessage() {
   DCHECK_EQ(state(), MESSAGE_READY);
-  scoped_ptr<buzz::XmlElement> result = v2_authenticator_->GetNextMessage();
+  scoped_ptr<buzz::XmlElement> result = spake2_authenticator_->GetNextMessage();
   AddPairingElements(result.get());
   MaybeAddErrorMessage(result.get());
   return result;
 }
 
 const std::string& PairingAuthenticatorBase::GetAuthKey() const {
-  return v2_authenticator_->GetAuthKey();
+  return spake2_authenticator_->GetAuthKey();
 }
 
 scoped_ptr<ChannelAuthenticator>
 PairingAuthenticatorBase::CreateChannelAuthenticator() const {
-  return v2_authenticator_->CreateChannelAuthenticator();
+  return spake2_authenticator_->CreateChannelAuthenticator();
 }
 
 void PairingAuthenticatorBase::MaybeAddErrorMessage(buzz::XmlElement* message) {
@@ -131,37 +122,18 @@
   // If the SPAKE exchange failed due to invalid credentials, and those
   // credentials were the paired secret, then notify the peer that the
   // PIN-less connection failed and retry using the PIN.
-  if (v2_authenticator_->state() == REJECTED &&
-      v2_authenticator_->rejection_reason() == INVALID_CREDENTIALS &&
+  if (spake2_authenticator_->state() == REJECTED &&
+      spake2_authenticator_->rejection_reason() == INVALID_CREDENTIALS &&
       using_paired_secret_) {
     using_paired_secret_ = false;
     error_message_ = "invalid-shared-secret";
-    v2_authenticator_.reset();
-    buzz::XmlElement* no_message = nullptr;
-    SetAuthenticatorCallback set_authenticator = base::Bind(
-        &PairingAuthenticatorBase::SetAuthenticatorAndProcessMessage,
-        weak_factory_.GetWeakPtr(), no_message, resume_callback);
-    CreateV2AuthenticatorWithPIN(MESSAGE_READY, set_authenticator);
+    spake2_authenticator_.reset();
+    CreateSpakeAuthenticatorWithPin(MESSAGE_READY, resume_callback);
     return;
   }
 
   resume_callback.Run();
 }
 
-void PairingAuthenticatorBase::SetAuthenticatorAndProcessMessage(
-    const buzz::XmlElement* message,
-    const base::Closure& resume_callback,
-    scoped_ptr<Authenticator> authenticator) {
-  DCHECK(!v2_authenticator_);
-  DCHECK(authenticator);
-  waiting_for_authenticator_ = false;
-  v2_authenticator_ = std::move(authenticator);
-  if (message) {
-    ProcessMessage(message, resume_callback);
-  } else {
-    resume_callback.Run();
-  }
-}
-
 }  // namespace protocol
 }  // namespace remoting
diff --git a/remoting/protocol/pairing_authenticator_base.h b/remoting/protocol/pairing_authenticator_base.h
index e241f0ae..14645c1 100644
--- a/remoting/protocol/pairing_authenticator_base.h
+++ b/remoting/protocol/pairing_authenticator_base.h
@@ -53,17 +53,14 @@
   scoped_ptr<ChannelAuthenticator> CreateChannelAuthenticator() const override;
 
  protected:
-  typedef base::Callback<void(scoped_ptr<Authenticator> authenticator)>
-      SetAuthenticatorCallback;
-
   static const buzz::StaticQName kPairingInfoTag;
   static const buzz::StaticQName kClientIdAttribute;
 
-  // Create a V2 authenticator in the specified state, prompting the user for
-  // the PIN first if necessary.
-  virtual void CreateV2AuthenticatorWithPIN(
+  // Create a Spake2 authenticator in the specified state, prompting the user
+  // for the PIN first if necessary.
+  virtual void CreateSpakeAuthenticatorWithPin(
       State initial_state,
-      const SetAuthenticatorCallback& callback) = 0;
+      const base::Closure& resume_callback) = 0;
 
   // Amend an authenticator message, for example to add client- or host-specific
   // elements to it.
@@ -75,27 +72,19 @@
   // nor is it currently used other than being logged.
   std::string error_message_;
 
-  // The underlying V2 authenticator, created with either the PIN or the
+  // The underlying SPAKE2 authenticator, created with either the PIN or the
   // Paired Secret by the derived class.
-  scoped_ptr<Authenticator> v2_authenticator_;
+  scoped_ptr<Authenticator> spake2_authenticator_;
 
   // Derived classes must set this to True if the underlying authenticator is
   // using the Paired Secret.
-  bool using_paired_secret_;
+  bool using_paired_secret_ = false;
 
  private:
   // Helper methods for ProcessMessage and GetNextMessage
   void MaybeAddErrorMessage(buzz::XmlElement* message);
   bool HasErrorMessage(const buzz::XmlElement* message) const;
   void CheckForFailedSpakeExchange(const base::Closure& resume_callback);
-  void SetAuthenticatorAndProcessMessage(
-      const buzz::XmlElement* message,
-      const base::Closure& resume_callback,
-      scoped_ptr<Authenticator> authenticator);
-
-  // Set to true if a PIN-based authenticator has been requested but has not
-  // yet been set.
-  bool waiting_for_authenticator_;
 
   base::WeakPtrFactory<PairingAuthenticatorBase> weak_factory_;
 
diff --git a/remoting/protocol/pairing_client_authenticator.cc b/remoting/protocol/pairing_client_authenticator.cc
index 5c03ab5..747654c0 100644
--- a/remoting/protocol/pairing_client_authenticator.cc
+++ b/remoting/protocol/pairing_client_authenticator.cc
@@ -10,7 +10,6 @@
 #include "remoting/base/rsa_key_pair.h"
 #include "remoting/protocol/authentication_method.h"
 #include "remoting/protocol/channel_authenticator.h"
-#include "remoting/protocol/v2_authenticator.h"
 #include "third_party/webrtc/libjingle/xmllite/xmlelement.h"
 
 namespace remoting {
@@ -19,29 +18,37 @@
 PairingClientAuthenticator::PairingClientAuthenticator(
     const std::string& client_id,
     const std::string& paired_secret,
+    const CreateBaseAuthenticatorCallback& create_base_authenticator_callback,
     const FetchSecretCallback& fetch_pin_callback,
     const std::string& authentication_tag)
-    : sent_client_id_(false),
-      client_id_(client_id),
+    : client_id_(client_id),
       paired_secret_(paired_secret),
+      create_base_authenticator_callback_(create_base_authenticator_callback),
       fetch_pin_callback_(fetch_pin_callback),
       authentication_tag_(authentication_tag),
       weak_factory_(this) {
-  v2_authenticator_ = V2Authenticator::CreateForClient(
-      paired_secret_, MESSAGE_READY);
+  spake2_authenticator_ =
+      create_base_authenticator_callback_.Run(paired_secret_, MESSAGE_READY);
   using_paired_secret_ = true;
 }
 
-PairingClientAuthenticator::~PairingClientAuthenticator() {
+PairingClientAuthenticator::~PairingClientAuthenticator() {}
+
+Authenticator::State PairingClientAuthenticator::state() const {
+  if (waiting_for_pin_)
+    return PROCESSING_MESSAGE;
+  return PairingAuthenticatorBase::state();
 }
 
-void PairingClientAuthenticator::CreateV2AuthenticatorWithPIN(
+void PairingClientAuthenticator::CreateSpakeAuthenticatorWithPin(
     State initial_state,
-    const SetAuthenticatorCallback& set_authenticator_callback) {
-  SecretFetchedCallback callback = base::Bind(
-      &PairingClientAuthenticator::OnPinFetched,
-      weak_factory_.GetWeakPtr(), initial_state, set_authenticator_callback);
-  fetch_pin_callback_.Run(true, callback);
+    const base::Closure& resume_callback) {
+  DCHECK(!waiting_for_pin_);
+  waiting_for_pin_ = true;
+  fetch_pin_callback_.Run(
+      true,
+      base::Bind(&PairingClientAuthenticator::OnPinFetched,
+                 weak_factory_.GetWeakPtr(), initial_state, resume_callback));
 }
 
 void PairingClientAuthenticator::AddPairingElements(buzz::XmlElement* message) {
@@ -59,12 +66,16 @@
 
 void PairingClientAuthenticator::OnPinFetched(
     State initial_state,
-    const SetAuthenticatorCallback& callback,
+    const base::Closure& resume_callback,
     const std::string& pin) {
-  callback.Run(V2Authenticator::CreateForClient(
+  DCHECK(waiting_for_pin_);
+  DCHECK(!spake2_authenticator_);
+  waiting_for_pin_ = false;
+  spake2_authenticator_ = create_base_authenticator_callback_.Run(
       ApplySharedSecretHashFunction(HashFunction::HMAC_SHA256,
                                     authentication_tag_, pin),
-      initial_state));
+      initial_state);
+  resume_callback.Run();
 }
 
 }  // namespace protocol
diff --git a/remoting/protocol/pairing_client_authenticator.h b/remoting/protocol/pairing_client_authenticator.h
index 50ff3e72..0e1a709 100644
--- a/remoting/protocol/pairing_client_authenticator.h
+++ b/remoting/protocol/pairing_client_authenticator.h
@@ -17,28 +17,37 @@
   PairingClientAuthenticator(
       const std::string& client_id,
       const std::string& paired_secret,
+      const CreateBaseAuthenticatorCallback& create_base_authenticator_callback,
       const FetchSecretCallback& fetch_pin_callback,
       const std::string& authentication_tag);
   ~PairingClientAuthenticator() override;
 
+  // Authenticator interface.
+  State state() const override;
+
  private:
-  // PairingAuthenticatorBase interface.
-  void CreateV2AuthenticatorWithPIN(
+  // PairingAuthenticatorBase overrides.
+  void CreateSpakeAuthenticatorWithPin(
       State initial_state,
-      const SetAuthenticatorCallback& callback) override;
+      const base::Closure& resume_callback) override;
   void AddPairingElements(buzz::XmlElement* message) override;
 
   void OnPinFetched(State initial_state,
-                    const SetAuthenticatorCallback& callback,
+                    const base::Closure& resume_callback,
                     const std::string& pin);
 
   // Protocol state.
-  bool sent_client_id_;
+  bool sent_client_id_ = false;
   std::string client_id_;
-  const std::string& paired_secret_;
+  std::string paired_secret_;
+  CreateBaseAuthenticatorCallback create_base_authenticator_callback_;
   FetchSecretCallback fetch_pin_callback_;
   std::string authentication_tag_;
 
+  // Set to true if a PIN-based authenticator has been requested but has not
+  // yet been set.
+  bool waiting_for_pin_ = false;
+
   base::WeakPtrFactory<PairingClientAuthenticator> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(PairingClientAuthenticator);
diff --git a/remoting/protocol/pairing_host_authenticator.cc b/remoting/protocol/pairing_host_authenticator.cc
index 5418dd3..b00a5c7 100644
--- a/remoting/protocol/pairing_host_authenticator.cc
+++ b/remoting/protocol/pairing_host_authenticator.cc
@@ -7,9 +7,7 @@
 #include "base/bind.h"
 #include "base/logging.h"
 #include "remoting/base/constants.h"
-#include "remoting/base/rsa_key_pair.h"
 #include "remoting/protocol/channel_authenticator.h"
-#include "remoting/protocol/v2_authenticator.h"
 #include "third_party/webrtc/libjingle/xmllite/xmlelement.h"
 
 namespace remoting {
@@ -17,27 +15,21 @@
 
 PairingHostAuthenticator::PairingHostAuthenticator(
     scoped_refptr<PairingRegistry> pairing_registry,
-    const std::string& local_cert,
-    scoped_refptr<RsaKeyPair> key_pair,
+    const CreateBaseAuthenticatorCallback& create_base_authenticator_callback,
     const std::string& pin)
     : pairing_registry_(pairing_registry),
-      local_cert_(local_cert),
-      key_pair_(key_pair),
+      create_base_authenticator_callback_(create_base_authenticator_callback),
       pin_(pin),
-      protocol_error_(false),
-      waiting_for_paired_secret_(false),
-      weak_factory_(this) {
-}
+      weak_factory_(this) {}
 
-PairingHostAuthenticator::~PairingHostAuthenticator() {
-}
+PairingHostAuthenticator::~PairingHostAuthenticator() {}
 
 Authenticator::State PairingHostAuthenticator::state() const {
   if (protocol_error_) {
     return REJECTED;
   } else if (waiting_for_paired_secret_) {
     return PROCESSING_MESSAGE;
-  } else if (!v2_authenticator_) {
+  } else if (!spake2_authenticator_) {
     return WAITING_MESSAGE;
   }
   return PairingAuthenticatorBase::state();
@@ -51,17 +43,18 @@
   return PairingAuthenticatorBase::rejection_reason();
 }
 
-void PairingHostAuthenticator::CreateV2AuthenticatorWithPIN(
+void PairingHostAuthenticator::CreateSpakeAuthenticatorWithPin(
     State initial_state,
-    const SetAuthenticatorCallback& callback) {
-  callback.Run(V2Authenticator::CreateForHost(
-      local_cert_, key_pair_, pin_, initial_state));
+    const base::Closure& resume_callback) {
+  spake2_authenticator_ =
+      create_base_authenticator_callback_.Run(pin_, initial_state);
+  resume_callback.Run();
 }
 
 void PairingHostAuthenticator::ProcessMessage(
     const buzz::XmlElement* message,
     const base::Closure& resume_callback) {
-  if (!v2_authenticator_) {
+  if (!spake2_authenticator_) {
     std::string client_id;
 
     const buzz::XmlElement* pairing_tag = message->FirstNamed(kPairingInfoTag);
@@ -72,16 +65,17 @@
     if (client_id.empty()) {
       LOG(ERROR) << "No client id specified.";
       protocol_error_ = true;
-    } else {
-      waiting_for_paired_secret_ = true;
-      pairing_registry_->GetPairing(
-          client_id,
-          base::Bind(&PairingHostAuthenticator::ProcessMessageWithPairing,
-                     weak_factory_.GetWeakPtr(),
-                     base::Owned(new buzz::XmlElement(*message)),
-                     resume_callback));
       return;
     }
+
+    waiting_for_paired_secret_ = true;
+    pairing_registry_->GetPairing(
+        client_id,
+        base::Bind(&PairingHostAuthenticator::ProcessMessageWithPairing,
+                   weak_factory_.GetWeakPtr(),
+                   base::Owned(new buzz::XmlElement(*message)),
+                   resume_callback));
+    return;
   }
 
   PairingAuthenticatorBase::ProcessMessage(message, resume_callback);
@@ -104,12 +98,12 @@
 
   using_paired_secret_ = !paired_secret.empty();
   if (using_paired_secret_) {
-    v2_authenticator_  = V2Authenticator::CreateForHost(
-        local_cert_, key_pair_, paired_secret, WAITING_MESSAGE);
+    spake2_authenticator_ =
+        create_base_authenticator_callback_.Run(paired_secret, WAITING_MESSAGE);
     PairingAuthenticatorBase::ProcessMessage(message, resume_callback);
   } else {
-    v2_authenticator_ = V2Authenticator::CreateForHost(
-        local_cert_, key_pair_, pin_, MESSAGE_READY);
+    spake2_authenticator_ =
+        create_base_authenticator_callback_.Run(pin_, MESSAGE_READY);
     // The client's optimistic SPAKE message is using a Paired Secret to
     // which the host doesn't have access, so don't bother processing it.
     resume_callback.Run();
diff --git a/remoting/protocol/pairing_host_authenticator.h b/remoting/protocol/pairing_host_authenticator.h
index bb814f1..03256913 100644
--- a/remoting/protocol/pairing_host_authenticator.h
+++ b/remoting/protocol/pairing_host_authenticator.h
@@ -11,9 +11,6 @@
 #include "remoting/protocol/pairing_registry.h"
 
 namespace remoting {
-
-class RsaKeyPair;
-
 namespace protocol {
 
 class PairingRegistry;
@@ -22,8 +19,7 @@
  public:
   PairingHostAuthenticator(
       scoped_refptr<PairingRegistry> pairing_registry,
-      const std::string& local_cert,
-      scoped_refptr<RsaKeyPair> key_pair,
+      const CreateBaseAuthenticatorCallback& create_base_authenticator_callback,
       const std::string& pin);
   ~PairingHostAuthenticator() override;
 
@@ -34,10 +30,10 @@
                       const base::Closure& resume_callback) override;
 
  private:
-  // PairingAuthenticatorBase interface.
-  void CreateV2AuthenticatorWithPIN(
+  // PairingAuthenticatorBase overrides.
+  void CreateSpakeAuthenticatorWithPin(
       State initial_state,
-      const SetAuthenticatorCallback& callback) override;
+      const base::Closure& resume_callback) override;
   void AddPairingElements(buzz::XmlElement* message) override;
 
   // Continue processing a protocol message once the pairing information for
@@ -48,11 +44,10 @@
 
   // Protocol state.
   scoped_refptr<PairingRegistry> pairing_registry_;
-  std::string local_cert_;
-  scoped_refptr<RsaKeyPair> key_pair_;
-  const std::string& pin_;
-  bool protocol_error_;
-  bool waiting_for_paired_secret_;
+  CreateBaseAuthenticatorCallback create_base_authenticator_callback_;
+  std::string pin_;
+  bool protocol_error_ = false;
+  bool waiting_for_paired_secret_ = false;
 
   base::WeakPtrFactory<PairingHostAuthenticator> weak_factory_;
 
diff --git a/remoting/protocol/third_party_authenticator_base.cc b/remoting/protocol/third_party_authenticator_base.cc
index ec5490e8..a0bdce4 100644
--- a/remoting/protocol/third_party_authenticator_base.cc
+++ b/remoting/protocol/third_party_authenticator_base.cc
@@ -11,7 +11,6 @@
 #include "remoting/base/constants.h"
 #include "remoting/base/rsa_key_pair.h"
 #include "remoting/protocol/channel_authenticator.h"
-#include "remoting/protocol/v2_authenticator.h"
 #include "third_party/webrtc/libjingle/xmllite/xmlelement.h"
 
 namespace remoting {
diff --git a/remoting/protocol/third_party_authenticator_unittest.cc b/remoting/protocol/third_party_authenticator_unittest.cc
index 441c56a..7b9c46d 100644
--- a/remoting/protocol/third_party_authenticator_unittest.cc
+++ b/remoting/protocol/third_party_authenticator_unittest.cc
@@ -17,6 +17,7 @@
 #include "remoting/protocol/third_party_client_authenticator.h"
 #include "remoting/protocol/third_party_host_authenticator.h"
 #include "remoting/protocol/token_validator.h"
+#include "remoting/protocol/v2_authenticator.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/webrtc/libjingle/xmllite/xmlelement.h"
@@ -100,14 +101,14 @@
 
  protected:
   void InitAuthenticators() {
-    scoped_ptr<TokenValidator> token_validator(new FakeTokenValidator());
-    token_validator_ = static_cast<FakeTokenValidator*>(token_validator.get());
+    token_validator_ = new FakeTokenValidator();
     host_.reset(new ThirdPartyHostAuthenticator(
-        host_cert_, key_pair_, std::move(token_validator)));
-    scoped_ptr<ThirdPartyClientAuthenticator::TokenFetcher>
-        token_fetcher(new FakeTokenFetcher());
-    token_fetcher_ = static_cast<FakeTokenFetcher*>(token_fetcher.get());
-    client_.reset(new ThirdPartyClientAuthenticator(std::move(token_fetcher)));
+        base::Bind(&V2Authenticator::CreateForHost, host_cert_, key_pair_),
+        make_scoped_ptr(token_validator_)));
+    token_fetcher_ = new FakeTokenFetcher();
+    client_.reset(new ThirdPartyClientAuthenticator(
+        base::Bind(&V2Authenticator::CreateForClient),
+        make_scoped_ptr(token_fetcher_)));
   }
 
   FakeTokenFetcher* token_fetcher_;
diff --git a/remoting/protocol/third_party_client_authenticator.cc b/remoting/protocol/third_party_client_authenticator.cc
index 544f4f2..0b199b75 100644
--- a/remoting/protocol/third_party_client_authenticator.cc
+++ b/remoting/protocol/third_party_client_authenticator.cc
@@ -13,7 +13,6 @@
 #include "remoting/base/constants.h"
 #include "remoting/base/rsa_key_pair.h"
 #include "remoting/protocol/channel_authenticator.h"
-#include "remoting/protocol/v2_authenticator.h"
 #include "third_party/webrtc/libjingle/xmllite/xmlelement.h"
 #include "url/gurl.h"
 
@@ -21,13 +20,13 @@
 namespace protocol {
 
 ThirdPartyClientAuthenticator::ThirdPartyClientAuthenticator(
+    const CreateBaseAuthenticatorCallback& create_base_authenticator_callback,
     scoped_ptr<TokenFetcher> token_fetcher)
     : ThirdPartyAuthenticatorBase(WAITING_MESSAGE),
-      token_fetcher_(std::move(token_fetcher)) {
-}
+      create_base_authenticator_callback_(create_base_authenticator_callback),
+      token_fetcher_(std::move(token_fetcher)) {}
 
-ThirdPartyClientAuthenticator::~ThirdPartyClientAuthenticator() {
-}
+ThirdPartyClientAuthenticator::~ThirdPartyClientAuthenticator() {}
 
 void ThirdPartyClientAuthenticator::ProcessTokenMessage(
     const buzz::XmlElement* message,
@@ -74,8 +73,8 @@
     rejection_reason_ = INVALID_CREDENTIALS;
   } else {
     token_state_ = MESSAGE_READY;
-    underlying_ = V2Authenticator::CreateForClient(
-        shared_secret, MESSAGE_READY);
+    underlying_ =
+        create_base_authenticator_callback_.Run(shared_secret, MESSAGE_READY);
   }
   resume_callback.Run();
 }
diff --git a/remoting/protocol/third_party_client_authenticator.h b/remoting/protocol/third_party_client_authenticator.h
index 823aad43..7ebc04f 100644
--- a/remoting/protocol/third_party_client_authenticator.h
+++ b/remoting/protocol/third_party_client_authenticator.h
@@ -55,9 +55,11 @@
         const TokenFetchedCallback& token_fetched_callback) = 0;
   };
 
-  // Creates a third-party client authenticator for the host with the given
-  // |host_public_key|. |token_fetcher| is used to get the authentication token.
-  explicit ThirdPartyClientAuthenticator(
+  // Creates a third-party client authenticator.
+  // |create_base_authenticator_callback| is used to create the base
+  // authenticator. |token_fetcher| is used to get the authentication token.
+  ThirdPartyClientAuthenticator(
+      const CreateBaseAuthenticatorCallback& create_base_authenticator_callback,
       scoped_ptr<TokenFetcher> token_fetcher);
   ~ThirdPartyClientAuthenticator() override;
 
@@ -72,8 +74,9 @@
                                 const std::string& third_party_token,
                                 const std::string& shared_secret);
 
-  std::string token_;
+  CreateBaseAuthenticatorCallback create_base_authenticator_callback_;
   scoped_ptr<TokenFetcher> token_fetcher_;
+  std::string token_;
 
   DISALLOW_COPY_AND_ASSIGN(ThirdPartyClientAuthenticator);
 };
diff --git a/remoting/protocol/third_party_host_authenticator.cc b/remoting/protocol/third_party_host_authenticator.cc
index db2ba5c..1ee4a02 100644
--- a/remoting/protocol/third_party_host_authenticator.cc
+++ b/remoting/protocol/third_party_host_authenticator.cc
@@ -11,26 +11,20 @@
 #include "base/callback.h"
 #include "base/logging.h"
 #include "remoting/base/constants.h"
-#include "remoting/base/rsa_key_pair.h"
 #include "remoting/protocol/token_validator.h"
-#include "remoting/protocol/v2_authenticator.h"
 #include "third_party/webrtc/libjingle/xmllite/xmlelement.h"
 
 namespace remoting {
 namespace protocol {
 
 ThirdPartyHostAuthenticator::ThirdPartyHostAuthenticator(
-    const std::string& local_cert,
-    scoped_refptr<RsaKeyPair> key_pair,
+    const CreateBaseAuthenticatorCallback& create_base_authenticator_callback,
     scoped_ptr<TokenValidator> token_validator)
     : ThirdPartyAuthenticatorBase(MESSAGE_READY),
-      local_cert_(local_cert),
-      key_pair_(key_pair),
-      token_validator_(std::move(token_validator)) {
-}
+      create_base_authenticator_callback_(create_base_authenticator_callback),
+      token_validator_(std::move(token_validator)) {}
 
-ThirdPartyHostAuthenticator::~ThirdPartyHostAuthenticator() {
-}
+ThirdPartyHostAuthenticator::~ThirdPartyHostAuthenticator() {}
 
 void ThirdPartyHostAuthenticator::ProcessTokenMessage(
     const buzz::XmlElement* message,
@@ -88,8 +82,8 @@
 
   // The other side already started the SPAKE authentication.
   token_state_ = ACCEPTED;
-  underlying_ = V2Authenticator::CreateForHost(
-      local_cert_, key_pair_, shared_secret, WAITING_MESSAGE);
+  underlying_ =
+      create_base_authenticator_callback_.Run(shared_secret, WAITING_MESSAGE);
   underlying_->ProcessMessage(message, resume_callback);
 }
 
diff --git a/remoting/protocol/third_party_host_authenticator.h b/remoting/protocol/third_party_host_authenticator.h
index ff2036a..f9755a9 100644
--- a/remoting/protocol/third_party_host_authenticator.h
+++ b/remoting/protocol/third_party_host_authenticator.h
@@ -13,9 +13,6 @@
 #include "remoting/protocol/third_party_authenticator_base.h"
 
 namespace remoting {
-
-class RsaKeyPair;
-
 namespace protocol {
 
 class TokenValidator;
@@ -26,16 +23,16 @@
 // Once that token is received, it calls |TokenValidator| asynchronously to
 // validate it, and exchange it for a |shared_secret|. Once the |TokenValidator|
 // returns, the host uses the |shared_secret| to create an underlying
-// |V2Authenticator|, which is used to establish the encrypted connection.
+// SPAKE2 authenticator, which is used to establish the encrypted connection.
 class ThirdPartyHostAuthenticator : public ThirdPartyAuthenticatorBase {
  public:
-  // Creates a third-party host authenticator. |local_cert| and |key_pair| are
-  // used by the underlying V2Authenticator to create the SSL channels.
-  // |token_validator| contains the token parameters to be sent to the client
-  // and is used to obtain the shared secret.
-  ThirdPartyHostAuthenticator(const std::string& local_cert,
-                              scoped_refptr<RsaKeyPair> key_pair,
-                              scoped_ptr<TokenValidator> token_validator);
+  // Creates a third-party host authenticator.
+  // |create_base_authenticator_callback| is used to create the base
+  // authenticator. |token_validator| contains the token parameters to be sent
+  // to the client and is used to obtain the shared secret.
+  ThirdPartyHostAuthenticator(
+      const CreateBaseAuthenticatorCallback& create_base_authenticator_callback,
+      scoped_ptr<TokenValidator> token_validator);
   ~ThirdPartyHostAuthenticator() override;
 
  protected:
@@ -49,8 +46,7 @@
                                   const base::Closure& resume_callback,
                                   const std::string& shared_secret);
 
-  std::string local_cert_;
-  scoped_refptr<RsaKeyPair> key_pair_;
+  CreateBaseAuthenticatorCallback create_base_authenticator_callback_;
   scoped_ptr<TokenValidator> token_validator_;
 
   DISALLOW_COPY_AND_ASSIGN(ThirdPartyHostAuthenticator);
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index ce382d1..7ddda70 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -497,12 +497,6 @@
         "test": "mojo_public_bindings_unittests"
       },
       {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "mojo_public_environment_unittests"
-      },
-      {
         "test": "mojo_public_system_unittests"
       },
       {
@@ -699,12 +693,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "mojo_public_environment_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "mojo_public_system_unittests"
       },
       {
@@ -1043,6 +1031,9 @@
         "test": "app_shell_unittests"
       },
       {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "aura_unittests"
       },
       {
@@ -1164,6 +1155,9 @@
         "test": "gpu_unittests"
       },
       {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "interactive_ui_tests"
       },
       {
@@ -1209,12 +1203,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "mojo_public_environment_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "mojo_public_system_unittests"
       },
       {
@@ -1290,6 +1278,9 @@
         "test": "ui_touch_selection_unittests"
       },
       {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "unit_tests"
       },
       {
@@ -1914,12 +1905,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "mojo_public_environment_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "mojo_public_system_unittests"
       },
       {
@@ -2215,9 +2200,6 @@
         "test": "mojo_public_bindings_unittests"
       },
       {
-        "test": "mojo_public_environment_unittests"
-      },
-      {
         "test": "mojo_public_system_unittests"
       },
       {
@@ -6466,12 +6448,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "mojo_public_environment_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "mojo_public_system_unittests"
       },
       {
@@ -6721,12 +6697,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "mojo_public_environment_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "mojo_public_system_unittests"
       },
       {
@@ -7015,9 +6985,6 @@
         "test": "mojo_public_bindings_unittests"
       },
       {
-        "test": "mojo_public_environment_unittests"
-      },
-      {
         "test": "mojo_public_system_unittests"
       },
       {
@@ -7258,9 +7225,6 @@
         "test": "mojo_public_bindings_unittests"
       },
       {
-        "test": "mojo_public_environment_unittests"
-      },
-      {
         "test": "mojo_public_system_unittests"
       },
       {
@@ -7363,42 +7327,63 @@
         "args": [
           "--top-chrome-md=material-hybrid"
         ],
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "ash_unittests"
       },
       {
         "args": [
           "--top-chrome-md=material-hybrid"
         ],
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "aura_unittests"
       },
       {
         "args": [
           "--top-chrome-md=material-hybrid"
         ],
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "browser_tests"
       },
       {
         "args": [
           "--top-chrome-md=material-hybrid"
         ],
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "interactive_ui_tests"
       },
       {
         "args": [
           "--top-chrome-md=material-hybrid"
         ],
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "ui_base_unittests"
       },
       {
         "args": [
           "--top-chrome-md=material-hybrid"
         ],
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "unit_tests"
       },
       {
         "args": [
           "--top-chrome-md=material-hybrid"
         ],
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "views_unittests"
       }
     ]
@@ -7409,24 +7394,36 @@
         "args": [
           "--top-chrome-md=non-material"
         ],
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "ash_unittests"
       },
       {
         "args": [
           "--top-chrome-md=non-material"
         ],
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "aura_unittests"
       },
       {
         "args": [
           "--top-chrome-md=non-material"
         ],
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "browser_tests"
       },
       {
         "args": [
           "--top-chrome-md=non-material"
         ],
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "interactive_ui_tests"
       },
       {
@@ -7442,6 +7439,9 @@
         "args": [
           "--top-chrome-md=non-material"
         ],
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "unit_tests"
       },
       {
@@ -7461,36 +7461,54 @@
         "args": [
           "--top-chrome-md=material"
         ],
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "aura_unittests"
       },
       {
         "args": [
           "--top-chrome-md=material"
         ],
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "browser_tests"
       },
       {
         "args": [
           "--top-chrome-md=material"
         ],
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "interactive_ui_tests"
       },
       {
         "args": [
           "--top-chrome-md=material"
         ],
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "ui_base_unittests"
       },
       {
         "args": [
           "--top-chrome-md=material"
         ],
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "unit_tests"
       },
       {
         "args": [
           "--top-chrome-md=material"
         ],
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "views_unittests"
       }
     ]
@@ -7501,36 +7519,54 @@
         "args": [
           "--top-chrome-md=material"
         ],
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "aura_unittests"
       },
       {
         "args": [
           "--top-chrome-md=material"
         ],
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "browser_tests"
       },
       {
         "args": [
           "--top-chrome-md=material"
         ],
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "interactive_ui_tests"
       },
       {
         "args": [
           "--top-chrome-md=material"
         ],
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "ui_base_unittests"
       },
       {
         "args": [
           "--top-chrome-md=material"
         ],
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "unit_tests"
       },
       {
         "args": [
           "--top-chrome-md=material"
         ],
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "views_unittests"
       }
     ]
diff --git a/testing/buildbot/chromium.gpu.fyi.json b/testing/buildbot/chromium.gpu.fyi.json
index b76e38f..696640f 100644
--- a/testing/buildbot/chromium.gpu.fyi.json
+++ b/testing/buildbot/chromium.gpu.fyi.json
@@ -476,6 +476,9 @@
           "--gtest_filter=CastStreamingApiTestWithPixelOutput.EndToEnd*:TabCaptureApiPixelTest.EndToEnd*"
         ],
         "name": "tab_capture_end2end_tests",
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "browser_tests",
         "use_xvfb": false
       },
@@ -896,6 +899,9 @@
           "--gtest_filter=CastStreamingApiTestWithPixelOutput.EndToEnd*:TabCaptureApiPixelTest.EndToEnd*"
         ],
         "name": "tab_capture_end2end_tests",
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "browser_tests",
         "use_xvfb": false
       },
@@ -2544,6 +2550,9 @@
           "--gtest_filter=CastStreamingApiTestWithPixelOutput.EndToEnd*:TabCaptureApiPixelTest.EndToEnd*"
         ],
         "name": "tab_capture_end2end_tests",
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "browser_tests",
         "use_xvfb": false
       },
diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json
index e94063f..80a577f 100644
--- a/testing/buildbot/chromium.linux.json
+++ b/testing/buildbot/chromium.linux.json
@@ -71,12 +71,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "mojo_public_environment_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "mojo_public_system_unittests"
       },
       {
@@ -821,12 +815,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "mojo_public_environment_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "mojo_public_system_unittests"
       },
       {
@@ -1238,12 +1226,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "mojo_public_environment_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "mojo_public_system_unittests"
       },
       {
@@ -1621,12 +1603,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "mojo_public_environment_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "mojo_public_system_unittests"
       },
       {
diff --git a/testing/buildbot/chromium.mac.json b/testing/buildbot/chromium.mac.json
index 7b08547..3cf6772b 100644
--- a/testing/buildbot/chromium.mac.json
+++ b/testing/buildbot/chromium.mac.json
@@ -29,7 +29,6 @@
       "media_blink_unittests",
       "mojo_common_unittests",
       "mojo_public_bindings_unittests",
-      "mojo_public_environment_unittests",
       "mojo_public_system_unittests",
       "mojo_public_utility_unittests",
       "mojo_system_unittests",
@@ -241,12 +240,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "mojo_public_environment_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "mojo_public_system_unittests"
       },
       {
@@ -569,12 +562,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "mojo_public_environment_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "mojo_public_system_unittests"
       },
       {
@@ -897,12 +884,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "mojo_public_environment_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "mojo_public_system_unittests"
       },
       {
@@ -1226,12 +1207,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "mojo_public_environment_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "mojo_public_system_unittests"
       },
       {
diff --git a/testing/buildbot/chromium.memory.fyi.json b/testing/buildbot/chromium.memory.fyi.json
index 7a2068e..ab8ad00 100644
--- a/testing/buildbot/chromium.memory.fyi.json
+++ b/testing/buildbot/chromium.memory.fyi.json
@@ -279,7 +279,6 @@
       "mojo_public_system_unittests",
       "mojo_public_utility_unittests",
       "mojo_public_bindings_unittests",
-      "mojo_public_environment_unittests",
       "mojo_common_unittests",
       "net_unittests",
       "printing_unittests",
@@ -318,7 +317,6 @@
       "mojo_public_system_unittests",
       "mojo_public_utility_unittests",
       "mojo_public_bindings_unittests",
-      "mojo_public_environment_unittests",
       "mojo_common_unittests",
       "cast_unittests",
       "cc_unittests",
@@ -536,12 +534,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "mojo_public_environment_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "mojo_public_system_unittests"
       },
       {
@@ -838,12 +830,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "mojo_public_environment_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "mojo_public_system_unittests"
       },
       {
@@ -2115,9 +2101,6 @@
         "test": "mojo_public_bindings_unittests"
       },
       {
-        "test": "mojo_public_environment_unittests"
-      },
-      {
         "test": "mojo_public_system_unittests"
       },
       {
@@ -2412,9 +2395,6 @@
         "test": "mojo_public_bindings_unittests"
       },
       {
-        "test": "mojo_public_environment_unittests"
-      },
-      {
         "test": "mojo_public_system_unittests"
       },
       {
@@ -2548,9 +2528,6 @@
         "test": "mojo_public_bindings_unittests"
       },
       {
-        "test": "mojo_public_environment_unittests"
-      },
-      {
         "test": "mojo_public_system_unittests"
       },
       {
diff --git a/testing/buildbot/chromium.win.json b/testing/buildbot/chromium.win.json
index a2a33a0..cb45f9e 100644
--- a/testing/buildbot/chromium.win.json
+++ b/testing/buildbot/chromium.win.json
@@ -250,12 +250,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "mojo_public_environment_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "mojo_public_system_unittests"
       },
       {
@@ -662,12 +656,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "mojo_public_environment_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "mojo_public_system_unittests"
       },
       {
@@ -1118,12 +1106,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "mojo_public_environment_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "mojo_public_system_unittests"
       },
       {
@@ -1502,12 +1484,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "mojo_public_environment_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "mojo_public_system_unittests"
       },
       {
@@ -1752,9 +1728,6 @@
         "test": "mojo_public_bindings_unittests"
       },
       {
-        "test": "mojo_public_environment_unittests"
-      },
-      {
         "test": "mojo_public_system_unittests"
       },
       {
diff --git a/testing/buildbot/chromium_trybot.json b/testing/buildbot/chromium_trybot.json
index f61bdd3..24a7696 100644
--- a/testing/buildbot/chromium_trybot.json
+++ b/testing/buildbot/chromium_trybot.json
@@ -223,7 +223,6 @@
     },
     "mojo_common_unittests",
     "mojo_public_bindings_unittests",
-    "mojo_public_environment_unittests",
     "mojo_public_system_unittests",
     "mojo_public_utility_unittests",
     "mojo_system_unittests",
diff --git a/testing/buildbot/client.v8.fyi.json b/testing/buildbot/client.v8.fyi.json
index c8c65ec6..89757b6 100644
--- a/testing/buildbot/client.v8.fyi.json
+++ b/testing/buildbot/client.v8.fyi.json
@@ -39,7 +39,6 @@
       "media_blink_unittests",
       "mojo_common_unittests",
       "mojo_public_bindings_unittests",
-      "mojo_public_environment_unittests",
       "mojo_public_system_unittests",
       "mojo_public_utility_unittests",
       "mojo_system_unittests",
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl
index 26d1a1fd..8c95f753 100644
--- a/testing/buildbot/gn_isolate_map.pyl
+++ b/testing/buildbot/gn_isolate_map.pyl
@@ -352,10 +352,6 @@
     "label": "//mojo/edk/test:mojo_public_bindings_unittests",
     "type": "console_test_launcher",
   },
-  "mojo_public_environment_unittests": {
-    "label": "//mojo/edk/test:mojo_public_environment_unittests",
-    "type": "console_test_launcher",
-  },
   "mojo_public_system_unittests": {
     "label": "//mojo/edk/test:mojo_public_system_unittests",
     "type": "console_test_launcher",
diff --git a/testing/buildbot/tryserver.v8.json b/testing/buildbot/tryserver.v8.json
index 7af7414..7ccbded 100644
--- a/testing/buildbot/tryserver.v8.json
+++ b/testing/buildbot/tryserver.v8.json
@@ -39,7 +39,6 @@
       "media_blink_unittests",
       "mojo_common_unittests",
       "mojo_public_bindings_unittests",
-      "mojo_public_environment_unittests",
       "mojo_public_system_unittests",
       "mojo_public_utility_unittests",
       "mojo_system_unittests",
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/webgl/resources/red-green-semi-transparent.png b/third_party/WebKit/LayoutTests/fast/canvas/webgl/resources/red-green-semi-transparent.png
new file mode 100644
index 0000000..11f2928a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/canvas/webgl/resources/red-green-semi-transparent.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/webgl/resources/red-green.ogv b/third_party/WebKit/LayoutTests/fast/canvas/webgl/resources/red-green.ogv
new file mode 100644
index 0000000..ca6c6e8
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/canvas/webgl/resources/red-green.ogv
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/webgl/resources/tex-image-and-sub-image-image-bitmap-utils.js b/third_party/WebKit/LayoutTests/fast/canvas/webgl/resources/tex-image-and-sub-image-image-bitmap-utils.js
new file mode 100644
index 0000000..fe6e884
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/canvas/webgl/resources/tex-image-and-sub-image-image-bitmap-utils.js
@@ -0,0 +1,115 @@
+function checkCanvasRect(buf, x, y, width, height, color, tolerance, bufWidth, retVal)
+{
+    for (var px = x; px < x + width; px++) {
+        for (var py = y; py < y + height; py++) {
+            var offset = (py * bufWidth + px) * 4;
+            for (var j = 0; j < color.length; j++) {
+                if (Math.abs(buf[offset + j] - color[j]) > tolerance) {
+                    retVal.testPassed = false;
+                    return;
+                }
+            }
+        }
+    }
+}
+
+function runOneIteration(useTexSubImage2D, bindingTarget, program, bitmap, flipY, premultiplyAlpha, retVal)
+{
+    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+    // Enable writes to the RGBA channels
+    gl.colorMask(1, 1, 1, 0);
+    var texture = gl.createTexture();
+    // Bind the texture to texture unit 0
+    gl.bindTexture(bindingTarget, texture);
+    // Set up texture parameters
+    gl.texParameteri(bindingTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+    gl.texParameteri(bindingTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+
+    var targets = [gl.TEXTURE_2D];
+    if (bindingTarget == gl.TEXTURE_CUBE_MAP) {
+        targets = [gl.TEXTURE_CUBE_MAP_POSITIVE_X,
+                   gl.TEXTURE_CUBE_MAP_NEGATIVE_X,
+                   gl.TEXTURE_CUBE_MAP_POSITIVE_Y,
+                   gl.TEXTURE_CUBE_MAP_NEGATIVE_Y,
+                   gl.TEXTURE_CUBE_MAP_POSITIVE_Z,
+                   gl.TEXTURE_CUBE_MAP_NEGATIVE_Z];
+    }
+    // Upload the image into the texture
+    for (var tt = 0; tt < targets.length; ++tt) {
+        if (useTexSubImage2D) {
+            // Initialize the texture to black first
+            gl.texImage2D(targets[tt], 0, gl[internalFormat], bitmap.width, bitmap.height, 0,
+                          gl[pixelFormat], gl[pixelType], null);
+            gl.texSubImage2D(targets[tt], 0, 0, 0, gl[pixelFormat], gl[pixelType], bitmap);
+        } else {
+            gl.texImage2D(targets[tt], 0, gl[internalFormat], gl[pixelFormat], gl[pixelType], bitmap);
+        }
+    }
+
+    var width = gl.canvas.width;
+    var halfWidth = Math.floor(width / 2);
+    var quaterWidth = Math.floor(halfWidth / 2);
+    var height = gl.canvas.height;
+    var halfHeight = Math.floor(height / 2);
+    var quaterHeight = Math.floor(halfHeight / 2);
+
+    var top = flipY ? quaterHeight : (height - halfHeight + quaterHeight);
+    var bottom = flipY ? (height - halfHeight + quaterHeight) : quaterHeight;
+
+    var tl = redColor;
+    var tr = premultiplyAlpha ? ((retVal.alpha == 0.5) ? halfRed : (retVal.alpha == 1) ? redColor : blackColor) : redColor;
+    var bl = greenColor;
+    var br = premultiplyAlpha ? ((retVal.alpha == 0.5) ? halfGreen : (retVal.alpha == 1) ? greenColor : blackColor) : greenColor;
+
+    var loc;
+    if (bindingTarget == gl.TEXTURE_CUBE_MAP) {
+        loc = gl.getUniformLocation(program, "face");
+    }
+
+    var tolerance = (retVal.alpha == 0) ? 0 : 3;
+    for (var tt = 0; tt < targets.length; ++tt) {
+        if (bindingTarget == gl.TEXTURE_CUBE_MAP) {
+            gl.uniform1i(loc, targets[tt]);
+        }
+        // Draw the triangles
+        gl.clearColor(0, 0, 0, 1);
+        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+        gl.drawArrays(gl.TRIANGLES, 0, 6);
+
+        // Check the top pixel and bottom pixel and make sure they have
+        // the right color.
+        var buf = new Uint8Array(width * height * 4);
+        gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+        checkCanvasRect(buf, quaterWidth, bottom, 2, 2, tl, tolerance, width, retVal);
+        checkCanvasRect(buf, halfWidth + quaterWidth, bottom, 2, 2, tr, tolerance, width, retVal);
+        checkCanvasRect(buf, quaterWidth, top, 2, 2, bl, tolerance, width, retVal);
+        checkCanvasRect(buf, halfWidth + quaterWidth, top, 2, 2, br, tolerance, width, retVal);
+    }
+}
+
+function runTestOnBindingTarget(bindingTarget, program, bitmaps, retVal) {
+    var cases = [
+        { sub: false },
+        { sub: true },
+    ];
+
+    for (var i in cases) {
+        runOneIteration(cases[i].sub, bindingTarget, program, bitmaps.defaultOption, false, true, retVal);
+        runOneIteration(cases[i].sub, bindingTarget, program, bitmaps.noFlipYPremul, false, true, retVal);
+        runOneIteration(cases[i].sub, bindingTarget, program, bitmaps.noFlipYDefault, false, true, retVal);
+        runOneIteration(cases[i].sub, bindingTarget, program, bitmaps.noFlipYUnpremul, false, false, retVal);
+        runOneIteration(cases[i].sub, bindingTarget, program, bitmaps.flipYPremul, true, true, retVal);
+        runOneIteration(cases[i].sub, bindingTarget, program, bitmaps.flipYDefault, true, true, retVal);
+        runOneIteration(cases[i].sub, bindingTarget, program, bitmaps.flipYUnpremul, true, false, retVal);
+    }
+}
+
+function runTest(bitmaps, alphaVal)
+{
+    var retVal = {testPassed: true, alpha: alphaVal};
+    var program = tiu.setupTexturedQuad(gl, internalFormat);
+    runTestOnBindingTarget(gl.TEXTURE_2D, program, bitmaps, retVal);
+//    program = tiu.setupTexturedQuadWithCubeMap(gl, internalFormat);
+//    runTestOnBindingTarget(gl.TEXTURE_CUBE_MAP, program, bitmaps, retVal);
+    return retVal.testPassed;
+}
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/webgl/resources/tex-image-and-sub-image-utils.js b/third_party/WebKit/LayoutTests/fast/canvas/webgl/resources/tex-image-and-sub-image-utils.js
new file mode 100644
index 0000000..f35774a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/canvas/webgl/resources/tex-image-and-sub-image-utils.js
@@ -0,0 +1,521 @@
+/*
+** Copyright (c) 2015 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+var TexImageUtils = (function() {
+
+  "use strict";
+
+  var wtu = WebGLTestUtils;
+
+  /**
+   * A vertex shader for a single texture.
+   * @type {string}
+   */
+  var simpleTextureVertexShaderES3 = [
+    '#version 300 es',
+    'in vec4 vPosition;',
+    'in vec2 texCoord0;',
+    'out vec2 texCoord;',
+    'void main() {',
+    '    gl_Position = vPosition;',
+    '    texCoord = texCoord0;',
+    '}'].join('\n');
+
+  /**
+   * A fragment shader for a single integer texture.
+   * @type {string}
+   */
+  // Note we always output 1.0 for alpha because if the texture does not contain
+  // alpha channel, sampling returns 1; for RGBA textures, sampling returns [0,255].
+  var simpleUintTextureFragmentShaderES3 = [
+    '#version 300 es',
+    'precision mediump float;',
+    'uniform mediump usampler2D tex;',
+    'in vec2 texCoord;',
+    'out vec4 fragData;',
+    'void main() {',
+    '    uvec4 data = texture(tex, texCoord);',
+    '    fragData = vec4(float(data[0])/255.0,',
+    '                    float(data[1])/255.0,',
+    '                    float(data[2])/255.0,',
+    '                    1.0);',
+    '}'].join('\n');
+
+  /**
+   * A fragment shader for a single cube map integer texture.
+   * @type {string}
+   */
+  // Note we always output 1.0 for alpha because if the texture does not contain
+  // alpha channel, sampling returns 1; for RGBA textures, sampling returns [0,255].
+  var simpleCubeMapUintTextureFragmentShaderES3 = [
+    '#version 300 es',
+    'precision mediump float;',
+    'uniform mediump usamplerCube tex;',
+    'uniform int face;',
+    'in vec2 texCoord;',
+    'out vec4 fragData;',
+    'void main() {',
+    // Transform [0, 1] -> [-1, 1]
+    '    vec2 texC2 = (texCoord * 2.) - 1.;',
+    // Transform 2d tex coord. to each face of TEXTURE_CUBE_MAP coord.
+    '    vec3 texCube = vec3(0., 0., 0.);',
+    '    if (face == 34069) {',         // TEXTURE_CUBE_MAP_POSITIVE_X
+    '        texCube = vec3(1., -texC2.y, -texC2.x);',
+    '    } else if (face == 34070) {',  // TEXTURE_CUBE_MAP_NEGATIVE_X
+    '        texCube = vec3(-1., -texC2.y, texC2.x);',
+    '    } else if (face == 34071) {',  // TEXTURE_CUBE_MAP_POSITIVE_Y
+    '        texCube = vec3(texC2.x, 1., texC2.y);',
+    '    } else if (face == 34072) {',  // TEXTURE_CUBE_MAP_NEGATIVE_Y
+    '        texCube = vec3(texC2.x, -1., -texC2.y);',
+    '    } else if (face == 34073) {',  // TEXTURE_CUBE_MAP_POSITIVE_Z
+    '        texCube = vec3(texC2.x, -texC2.y, 1.);',
+    '    } else if (face == 34074) {',  // TEXTURE_CUBE_MAP_NEGATIVE_Z
+    '        texCube = vec3(-texC2.x, -texC2.y, -1.);',
+    '    }',
+    '    uvec4 data = texture(tex, texCube);',
+    '    fragData = vec4(float(data[0])/255.0,',
+    '                    float(data[1])/255.0,',
+    '                    float(data[2])/255.0,',
+    '                    1.0);',
+    '}'].join('\n');
+
+  /**
+   * A fragment shader for a single 3D texture.
+   * @type {string}
+   */
+  // Note we always set the tex coordinate t to 0.
+  var simple3DTextureFragmentShaderES3 = [
+    '#version 300 es',
+    'precision mediump float;',
+    'uniform mediump sampler3D tex;',
+    'in vec2 texCoord;',
+    'out vec4 fragData;',
+    'void main() {',
+    '    fragData = vec4(texture(tex, vec3(texCoord, 0.0)).rgb, 1.0);',
+    '}'].join('\n');
+
+  /**
+   * A fragment shader for a single 3D integer texture.
+   * @type {string}
+   */
+  // Note we always set the tex coordinate t to 0.
+  // Note we always output 1.0 for alpha because if the texture does not contain
+  // alpha channel, sampling returns 1; for RGBA textures, sampling returns [0,255].
+  var simple3DUintTextureFragmentShaderES3 = [
+    '#version 300 es',
+    'precision mediump float;',
+    'uniform mediump usampler3D tex;',
+    'in vec2 texCoord;',
+    'out vec4 fragData;',
+    'void main() {',
+    '    vec4 data = vec4(texture(tex, vec3(texCoord, 0.0)).rgb, 1.0);',
+    '    fragData = vec4(float(data[0])/255.0,',
+    '                    float(data[1])/255.0,',
+    '                    float(data[2])/255.0,',
+    '                    1.0);',
+    '}'].join('\n');
+
+  /**
+   * A fragment shader for a single 2D_ARRAY texture.
+   * @type {string}
+   */
+  // Note we always use the first image in the array.
+  var simple2DArrayTextureFragmentShaderES3 = [
+    '#version 300 es',
+    'precision mediump float;',
+    'uniform mediump sampler2DArray tex;',
+    'in vec2 texCoord;',
+    'out vec4 fragData;',
+    'void main() {',
+    '    fragData = vec4(texture(tex, vec3(texCoord, 0.0)).rgb, 1.0);',
+    '}'].join('\n');
+
+  /**
+   * A fragment shader for a single 2D_ARRAY unsigned integer texture.
+   * @type {string}
+   */
+  // Note we always use the first image in the array.
+  // Note we always output 1.0 for alpha because if the texture does not contain
+  // alpha channel, sampling returns 1; for RGBA textures, sampling returns [0,255].
+  var simple2DArrayUintTextureFragmentShaderES3 = [
+    '#version 300 es',
+    'precision mediump float;',
+    'uniform mediump usampler2DArray tex;',
+    'in vec2 texCoord;',
+    'out vec4 fragData;',
+    'void main() {',
+    '    vec4 data = vec4(texture(tex, vec3(texCoord, 0.0)).rgb, 1.0);',
+    '    fragData = vec4(float(data[0])/255.0,',
+    '                    float(data[1])/255.0,',
+    '                    float(data[2])/255.0,',
+    '                    1.0);',
+    '}'].join('\n');
+
+
+  /**
+   * Creates a simple texture vertex shader.
+   * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+   * @return {!WebGLShader}
+   */
+  var setupSimpleTextureVertexShader = function(gl) {
+    return WebGLTestUtils.loadShader(gl, simpleTextureVertexShaderES3, gl.VERTEX_SHADER);
+  };
+
+  /**
+   * Creates a simple unsigned integer texture fragment shader.
+   * Output is scaled by 1/255 to bring the result into normalized float range.
+   * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+   * @return {!WebGLShader}
+   */
+  var setupSimpleUintTextureFragmentShader = function(gl) {
+    return WebGLTestUtils.loadShader(gl, simpleUintTextureFragmentShaderES3, gl.FRAGMENT_SHADER);
+  };
+
+  /**
+   * Creates a simple cube map unsigned integer texture fragment shader.
+   * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+   * @return {!WebGLShader}
+   */
+  var setupSimpleCubeMapUintTextureFragmentShader = function(gl) {
+    return WebGLTestUtils.loadShader(gl, simpleCubeMapUintTextureFragmentShaderES3, gl.FRAGMENT_SHADER);
+  };
+
+  /**
+   * Creates a simple 3D texture fragment shader.
+   * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+   * @return {!WebGLShader}
+   */
+  var setupSimple3DTextureFragmentShader = function(gl) {
+    return WebGLTestUtils.loadShader(gl, simple3DTextureFragmentShaderES3, gl.FRAGMENT_SHADER);
+  };
+
+  /**
+   * Creates a simple 3D integer texture fragment shader.
+   * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+   * @return {!WebGLShader}
+   */
+  var setupSimple3DUintTextureFragmentShader = function(gl) {
+    return WebGLTestUtils.loadShader(gl, simple3DUintTextureFragmentShaderES3, gl.FRAGMENT_SHADER);
+  };
+
+  /**
+   * Creates a simple 2D_ARRAY texture fragment shader.
+   * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+   * @return {!WebGLShader}
+   */
+  var setupSimple2DArrayTextureFragmentShader = function(gl) {
+    return WebGLTestUtils.loadShader(gl, simple2DArrayTextureFragmentShaderES3, gl.FRAGMENT_SHADER);
+  };
+
+  /**
+   * Creates a simple 2D_ARRAY integer texture fragment shader.
+   * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+   * @return {!WebGLShader}
+   */
+  var setupSimple2DArrayUintTextureFragmentShader = function(gl) {
+    return WebGLTestUtils.loadShader(gl, simple2DArrayUintTextureFragmentShaderES3, gl.FRAGMENT_SHADER);
+  };
+
+  /**
+   * Creates a simple unsigned integer texture program.
+   * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+   * @param {number} opt_positionLocation The attrib location for position.
+   * @param {number} opt_texcoordLocation The attrib location for texture coords.
+   * @return {WebGLProgram}
+   */
+  var setupSimpleUintTextureProgram = function(gl, opt_positionLocation, opt_texcoordLocation)
+  {
+    opt_positionLocation = opt_positionLocation || 0;
+    opt_texcoordLocation = opt_texcoordLocation || 1;
+    var vs = setupSimpleTextureVertexShader(gl),
+        fs = setupSimpleUintTextureFragmentShader(gl);
+    if (!vs || !fs) {
+      return null;
+    }
+    var program = WebGLTestUtils.setupProgram(
+      gl,
+      [vs, fs],
+      ['vPosition', 'texCoord0'],
+      [opt_positionLocation, opt_texcoordLocation]);
+    if (!program) {
+      gl.deleteShader(fs);
+      gl.deleteShader(vs);
+    }
+    gl.useProgram(program);
+    return program;
+  };
+
+  /**
+   * Creates a simple cube map unsigned integer texture program.
+   * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+   * @param {number} opt_positionLocation The attrib location for position.
+   * @param {number} opt_texcoordLocation The attrib location for texture coords.
+   * @return {WebGLProgram}
+   */
+  var setupSimpleCubeMapUintTextureProgram = function(gl, opt_positionLocation, opt_texcoordLocation) {
+    opt_positionLocation = opt_positionLocation || 0;
+    opt_texcoordLocation = opt_texcoordLocation || 1;
+    var vs = setupSimpleTextureVertexShader(gl);
+    var fs = setupSimpleCubeMapUintTextureFragmentShader(gl);
+    if (!vs || !fs) {
+      return null;
+    }
+    var program = WebGLTestUtils.setupProgram(
+      gl,
+      [vs, fs],
+      ['vPosition', 'texCoord0'],
+      [opt_positionLocation, opt_texcoordLocation]);
+    if (!program) {
+      gl.deleteShader(fs);
+      gl.deleteShader(vs);
+    }
+    gl.useProgram(program);
+    return program;
+  };
+
+  /**
+   * Creates a simple 3D texture program.
+   * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+   * @param {number} opt_positionLocation The attrib location for position.
+   * @param {number} opt_texcoordLocation The attrib location for texture coords.
+   * @return {WebGLProgram}
+   */
+  var setupSimple3DTextureProgram = function(gl, opt_positionLocation, opt_texcoordLocation)
+  {
+    opt_positionLocation = opt_positionLocation || 0;
+    opt_texcoordLocation = opt_texcoordLocation || 1;
+    var vs = setupSimpleTextureVertexShader(gl),
+        fs = setupSimple3DTextureFragmentShader(gl);
+    if (!vs || !fs) {
+      return null;
+    }
+    var program = WebGLTestUtils.setupProgram(
+      gl,
+      [vs, fs],
+      ['vPosition', 'texCoord0'],
+      [opt_positionLocation, opt_texcoordLocation]);
+    if (!program) {
+      gl.deleteShader(fs);
+      gl.deleteShader(vs);
+    }
+    gl.useProgram(program);
+    return program;
+  };
+
+  /**
+   * Creates a simple 3D unsigned integer texture program.
+   * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+   * @param {number} opt_positionLocation The attrib location for position.
+   * @param {number} opt_texcoordLocation The attrib location for texture coords.
+   * @return {WebGLProgram}
+   */
+  var setupSimple3DUintTextureProgram = function(gl, opt_positionLocation, opt_texcoordLocation)
+  {
+    opt_positionLocation = opt_positionLocation || 0;
+    opt_texcoordLocation = opt_texcoordLocation || 1;
+    var vs = setupSimpleTextureVertexShader(gl),
+        fs = setupSimple3DUintTextureFragmentShader(gl);
+    if (!vs || !fs) {
+      return null;
+    }
+    var program = WebGLTestUtils.setupProgram(
+      gl,
+      [vs, fs],
+      ['vPosition', 'texCoord0'],
+      [opt_positionLocation, opt_texcoordLocation]);
+    if (!program) {
+      gl.deleteShader(fs);
+      gl.deleteShader(vs);
+    }
+    gl.useProgram(program);
+    return program;
+  };
+
+  /**
+   * Creates a simple 2D_ARRAY texture program.
+   * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+   * @param {number} opt_positionLocation The attrib location for position.
+   * @param {number} opt_texcoordLocation The attrib location for texture coords.
+   * @return {WebGLProgram}
+   */
+  var setupSimple2DArrayTextureProgram = function(gl, opt_positionLocation, opt_texcoordLocation)
+  {
+    opt_positionLocation = opt_positionLocation || 0;
+    opt_texcoordLocation = opt_texcoordLocation || 1;
+    var vs = setupSimpleTextureVertexShader(gl),
+        fs = setupSimple2DArrayTextureFragmentShader(gl);
+    if (!vs || !fs) {
+      return null;
+    }
+    var program = WebGLTestUtils.setupProgram(
+      gl,
+      [vs, fs],
+      ['vPosition', 'texCoord0'],
+      [opt_positionLocation, opt_texcoordLocation]);
+    if (!program) {
+      gl.deleteShader(fs);
+      gl.deleteShader(vs);
+    }
+    gl.useProgram(program);
+    return program;
+  };
+
+  /**
+   * Creates a simple 2D_ARRAY unsigned integer texture program.
+   * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+   * @param {number} opt_positionLocation The attrib location for position.
+   * @param {number} opt_texcoordLocation The attrib location for texture coords.
+   * @return {WebGLProgram}
+   */
+  var setupSimple2DArrayUintTextureProgram = function(gl, opt_positionLocation, opt_texcoordLocation)
+  {
+    opt_positionLocation = opt_positionLocation || 0;
+    opt_texcoordLocation = opt_texcoordLocation || 1;
+    var vs = setupSimpleTextureVertexShader(gl),
+        fs = setupSimple2DArrayUintTextureFragmentShader(gl);
+    if (!vs || !fs) {
+      return null;
+    }
+    var program = WebGLTestUtils.setupProgram(
+      gl,
+      [vs, fs],
+      ['vPosition', 'texCoord0'],
+      [opt_positionLocation, opt_texcoordLocation]);
+    if (!program) {
+      gl.deleteShader(fs);
+      gl.deleteShader(vs);
+    }
+    gl.useProgram(program);
+    return program;
+  };
+
+  /**
+   * Creates a program and buffers for rendering a unsigned integer textured quad.
+   * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+   * @return {!WebGLProgram}
+   */
+  var setupUintTexturedQuad = function(gl) {
+    var program = setupSimpleUintTextureProgram(gl);
+    wtu.setupUnitQuad(gl);
+    return program;
+  };
+
+  /**
+   * Creates a program and buffers for rendering a textured quad with
+   * a cube map unsigned integer texture.
+   * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+   * @return {!WebGLProgram}
+   */
+  var setupUintTexturedQuadWithCubeMap = function(gl)
+  {
+    var program = setupSimpleCubeMapUintTextureProgram(gl);
+    wtu.setupUnitQuad(gl);
+    return program;
+  };
+
+  /**
+   * Does the GL internal format represent an unsigned integer format
+   * texture?
+   * @return {boolean}
+   */
+  var isUintFormat = function(internalFormat)
+  {
+    return (internalFormat == "R8UI" ||
+            internalFormat == "RG8UI" ||
+            internalFormat == "RGB8UI" ||
+            internalFormat == "RGBA8UI");
+  };
+
+  /**
+   * Createa a program and buffers for rendering a textured quad for
+   * tex-image-and-sub-image tests. Handle selection of correct
+   * program to handle texture format.
+   * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+   * @param {string} internalFormat The internal format for texture to be tested.
+   */
+  var setupTexturedQuad = function(gl, internalFormat)
+  {
+    if (isUintFormat(internalFormat))
+      return setupUintTexturedQuad(gl);
+
+    return wtu.setupTexturedQuad(gl);
+  };
+
+  /**
+   * Createa a program and buffers for rendering a textured quad with
+   * a cube map for tex-image-and-sub-image tests. Handle selection of
+   * correct program to handle texture format.
+   * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+   * @param {string} internalFormat The internal format for texture to be tested.
+   */
+  function setupTexturedQuadWithCubeMap(gl, internalFormat)
+  {
+    if (isUintFormat(internalFormat))
+      return setupUintTexturedQuadWithCubeMap(gl);
+
+    return wtu.setupTexturedQuadWithCubeMap(gl);
+  }
+
+  /**
+   * Createa a program and buffers for rendering a textured quad with a 3D texture
+   * for tex-image-and-sub-image tests. Handle selection of correct
+   * program to handle texture format.
+   * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+   * @param {string} internalFormat The internal format for texture to be tested.
+   */
+  var setupTexturedQuadWith3D = function(gl, internalFormat)
+  {
+    var program;
+    if (isUintFormat(internalFormat))
+      program = setupSimple3DUintTextureProgram(gl);
+    else
+      program = setupSimple3DTextureProgram(gl);
+    wtu.setupUnitQuad(gl);
+    return program;
+  };
+
+  /**
+   * Createa a program and buffers for rendering a textured quad with a 2D_ARRAY
+   * texture for tex-image-and-sub-image tests. Handle selection of correct
+   * program to handle texture format.
+   * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+   * @param {string} internalFormat The internal format for texture to be tested.
+   */
+  var setupTexturedQuadWith2DArray = function(gl, internalFormat)
+  {
+    var program;
+    if (isUintFormat(internalFormat))
+      program = setupSimple2DArrayUintTextureProgram(gl);
+    else
+      program = setupSimple2DArrayTextureProgram(gl);
+    wtu.setupUnitQuad(gl);
+    return program;
+  };
+
+  return {
+    setupTexturedQuad: setupTexturedQuad,
+    setupTexturedQuadWithCubeMap: setupTexturedQuadWithCubeMap,
+    setupTexturedQuadWith3D: setupTexturedQuadWith3D,
+    setupTexturedQuadWith2DArray: setupTexturedQuadWith2DArray
+  };
+
+}());
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/webgl/resources/webgl-test-utils-full.js b/third_party/WebKit/LayoutTests/fast/canvas/webgl/resources/webgl-test-utils-full.js
new file mode 100644
index 0000000..ec8659ef
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/canvas/webgl/resources/webgl-test-utils-full.js
@@ -0,0 +1,3056 @@
+/*
+** Copyright (c) 2012 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+var WebGLTestUtils = (function() {
+"use strict";
+
+/**
+ * Wrapped logging function.
+ * @param {string} msg The message to log.
+ */
+var log = function(msg) {
+  bufferedLogToConsole(msg);
+};
+
+/**
+ * Wrapped logging function.
+ * @param {string} msg The message to log.
+ */
+var error = function(msg) {
+  // For the time being, diverting this to window.console.log rather
+  // than window.console.error. If anyone cares enough they can
+  // generalize the mechanism in js-test-pre.js.
+  log(msg);
+};
+
+/**
+ * Turn off all logging.
+ */
+var loggingOff = function() {
+  log = function() {};
+  error = function() {};
+};
+
+/**
+ * Converts a WebGL enum to a string.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {number} value The enum value.
+ * @return {string} The enum as a string.
+ */
+var glEnumToString = function(gl, value) {
+  // Optimization for the most common enum:
+  if (value === gl.NO_ERROR) {
+    return "NO_ERROR";
+  }
+  for (var p in gl) {
+    if (gl[p] == value) {
+      if (p == 'drawingBufferWidth' || p == 'drawingBufferHeight') {
+        continue;
+      }
+      return p;
+    }
+  }
+  return "0x" + Number(value).toString(16);
+};
+
+var lastError = "";
+
+/**
+ * Returns the last compiler/linker error.
+ * @return {string} The last compiler/linker error.
+ */
+var getLastError = function() {
+  return lastError;
+};
+
+/**
+ * Whether a haystack ends with a needle.
+ * @param {string} haystack String to search
+ * @param {string} needle String to search for.
+ * @param {boolean} True if haystack ends with needle.
+ */
+var endsWith = function(haystack, needle) {
+  return haystack.substr(haystack.length - needle.length) === needle;
+};
+
+/**
+ * Whether a haystack starts with a needle.
+ * @param {string} haystack String to search
+ * @param {string} needle String to search for.
+ * @param {boolean} True if haystack starts with needle.
+ */
+var startsWith = function(haystack, needle) {
+  return haystack.substr(0, needle.length) === needle;
+};
+
+/**
+ * A vertex shader for a single texture.
+ * @type {string}
+ */
+var simpleTextureVertexShader = [
+  'attribute vec4 vPosition;',
+  'attribute vec2 texCoord0;',
+  'varying vec2 texCoord;',
+  'void main() {',
+  '    gl_Position = vPosition;',
+  '    texCoord = texCoord0;',
+  '}'].join('\n');
+
+/**
+ * A fragment shader for a single texture.
+ * @type {string}
+ */
+var simpleTextureFragmentShader = [
+  'precision mediump float;',
+  'uniform sampler2D tex;',
+  'varying vec2 texCoord;',
+  'void main() {',
+  '    gl_FragData[0] = texture2D(tex, texCoord);',
+  '}'].join('\n');
+
+/**
+ * A fragment shader for a single cube map texture.
+ * @type {string}
+ */
+var simpleCubeMapTextureFragmentShader = [
+  'precision mediump float;',
+  'uniform samplerCube tex;',
+  'uniform int face;',
+  'varying vec2 texCoord;',
+  'void main() {',
+  // Transform [0, 1] -> [-1, 1]
+  '    vec2 texC2 = (texCoord * 2.) - 1.;',
+  // Transform 2d tex coord. to each face of TEXTURE_CUBE_MAP coord.
+  '    vec3 texCube = vec3(0., 0., 0.);',
+  '    if (face == 34069) {',         // TEXTURE_CUBE_MAP_POSITIVE_X
+  '        texCube = vec3(1., -texC2.y, -texC2.x);',
+  '    } else if (face == 34070) {',  // TEXTURE_CUBE_MAP_NEGATIVE_X
+  '        texCube = vec3(-1., -texC2.y, texC2.x);',
+  '    } else if (face == 34071) {',  // TEXTURE_CUBE_MAP_POSITIVE_Y
+  '        texCube = vec3(texC2.x, 1., texC2.y);',
+  '    } else if (face == 34072) {',  // TEXTURE_CUBE_MAP_NEGATIVE_Y
+  '        texCube = vec3(texC2.x, -1., -texC2.y);',
+  '    } else if (face == 34073) {',  // TEXTURE_CUBE_MAP_POSITIVE_Z
+  '        texCube = vec3(texC2.x, -texC2.y, 1.);',
+  '    } else if (face == 34074) {',  // TEXTURE_CUBE_MAP_NEGATIVE_Z
+  '        texCube = vec3(-texC2.x, -texC2.y, -1.);',
+  '    }',
+  '    gl_FragData[0] = textureCube(tex, texCube);',
+  '}'].join('\n');
+
+/**
+ * A vertex shader for a single texture.
+ * @type {string}
+ */
+var noTexCoordTextureVertexShader = [
+  'attribute vec4 vPosition;',
+  'varying vec2 texCoord;',
+  'void main() {',
+  '    gl_Position = vPosition;',
+  '    texCoord = vPosition.xy * 0.5 + 0.5;',
+  '}'].join('\n');
+
+/**
+ * A vertex shader for a uniform color.
+ * @type {string}
+ */
+var simpleVertexShader = [
+  'attribute vec4 vPosition;',
+  'void main() {',
+  '    gl_Position = vPosition;',
+  '}'].join('\n');
+
+/**
+ * A fragment shader for a uniform color.
+ * @type {string}
+ */
+var simpleColorFragmentShader = [
+  'precision mediump float;',
+  'uniform vec4 u_color;',
+  'void main() {',
+  '    gl_FragData[0] = u_color;',
+  '}'].join('\n');
+
+/**
+ * A vertex shader for vertex colors.
+ * @type {string}
+ */
+var simpleVertexColorVertexShader = [
+  'attribute vec4 vPosition;',
+  'attribute vec4 a_color;',
+  'varying vec4 v_color;',
+  'void main() {',
+  '    gl_Position = vPosition;',
+  '    v_color = a_color;',
+  '}'].join('\n');
+
+/**
+ * A fragment shader for vertex colors.
+ * @type {string}
+ */
+var simpleVertexColorFragmentShader = [
+  'precision mediump float;',
+  'varying vec4 v_color;',
+  'void main() {',
+  '    gl_FragData[0] = v_color;',
+  '}'].join('\n');
+
+/**
+ * Creates a program, attaches shaders, binds attrib locations, links the
+ * program and calls useProgram.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {!Array.<!WebGLShader|string>} shaders The shaders to
+ *        attach, or the source, or the id of a script to get
+ *        the source from.
+ * @param {!Array.<string>} opt_attribs The attribs names.
+ * @param {!Array.<number>} opt_locations The locations for the attribs.
+ * @param {boolean} opt_logShaders Whether to log shader source.
+ */
+var setupProgram = function(
+    gl, shaders, opt_attribs, opt_locations, opt_logShaders) {
+  var realShaders = [];
+  var program = gl.createProgram();
+  var shaderCount = 0;
+  for (var ii = 0; ii < shaders.length; ++ii) {
+    var shader = shaders[ii];
+    var shaderType = undefined;
+    if (typeof shader == 'string') {
+      var element = document.getElementById(shader);
+      if (element) {
+        if (element.type != "x-shader/x-vertex" && element.type != "x-shader/x-fragment")
+          shaderType = ii ? gl.FRAGMENT_SHADER : gl.VERTEX_SHADER;
+        shader = loadShaderFromScript(gl, shader, shaderType, undefined, opt_logShaders);
+      } else if (endsWith(shader, ".vert")) {
+        shader = loadShaderFromFile(gl, shader, gl.VERTEX_SHADER, undefined, opt_logShaders);
+      } else if (endsWith(shader, ".frag")) {
+        shader = loadShaderFromFile(gl, shader, gl.FRAGMENT_SHADER, undefined, opt_logShaders);
+      } else {
+        shader = loadShader(gl, shader, ii ? gl.FRAGMENT_SHADER : gl.VERTEX_SHADER, undefined, opt_logShaders);
+      }
+    } else if (opt_logShaders) {
+      throw 'Shader source logging requested but no shader source provided';
+    }
+    if (shader) {
+      ++shaderCount;
+      gl.attachShader(program, shader);
+    }
+  }
+  if (shaderCount != 2) {
+    error("Error in compiling shader");
+    return null;
+  }
+  if (opt_attribs) {
+    for (var ii = 0; ii < opt_attribs.length; ++ii) {
+      gl.bindAttribLocation(
+          program,
+          opt_locations ? opt_locations[ii] : ii,
+          opt_attribs[ii]);
+    }
+  }
+  gl.linkProgram(program);
+
+  // Check the link status
+  var linked = gl.getProgramParameter(program, gl.LINK_STATUS);
+  if (!linked) {
+      // something went wrong with the link
+      lastError = gl.getProgramInfoLog (program);
+      error("Error in program linking:" + lastError);
+
+      gl.deleteProgram(program);
+      return null;
+  }
+
+  gl.useProgram(program);
+  return program;
+};
+
+/**
+ * Creates a program, attaches shader, sets up trasnform feedback varyings,
+ * binds attrib locations, links the program and calls useProgram.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {!Array.<!WebGLShader|string>} shaders The shaders to
+ *        attach, or the source, or the id of a script to get
+ *        the source from.
+ * @param {!Array.<string>} varyings The transform feedback varying names.
+ * @param {number} bufferMode The mode used to capture the varying variables.
+ * @param {!Array.<string>} opt_attribs The attribs names.
+ * @param {!Array.<number>} opt_locations The locations for the attribs.
+ * @param {boolean} opt_logShaders Whether to log shader source.
+ */
+var setupTransformFeedbackProgram = function(
+    gl, shaders, varyings, bufferMode, opt_attribs, opt_locations, opt_logShaders) {
+  var realShaders = [];
+  var program = gl.createProgram();
+  var shaderCount = 0;
+  for (var ii = 0; ii < shaders.length; ++ii) {
+    var shader = shaders[ii];
+    var shaderType = undefined;
+    if (typeof shader == 'string') {
+      var element = document.getElementById(shader);
+      if (element) {
+        if (element.type != "x-shader/x-vertex" && element.type != "x-shader/x-fragment")
+          shaderType = ii ? gl.FRAGMENT_SHADER : gl.VERTEX_SHADER;
+        shader = loadShaderFromScript(gl, shader, shaderType, undefined, opt_logShaders);
+      } else if (endsWith(shader, ".vert")) {
+        shader = loadShaderFromFile(gl, shader, gl.VERTEX_SHADER, undefined, opt_logShaders);
+      } else if (endsWith(shader, ".frag")) {
+        shader = loadShaderFromFile(gl, shader, gl.FRAGMENT_SHADER, undefined, opt_logShaders);
+      } else {
+        shader = loadShader(gl, shader, ii ? gl.FRAGMENT_SHADER : gl.VERTEX_SHADER, undefined, opt_logShaders);
+      }
+    } else if (opt_logShaders) {
+      throw 'Shader source logging requested but no shader source provided';
+    }
+    if (shader) {
+      ++shaderCount;
+      gl.attachShader(program, shader);
+    }
+  }
+  if (shaderCount != 2) {
+    error("Error in compiling shader");
+    return null;
+  }
+
+  if (opt_attribs) {
+    for (var ii = 0; ii < opt_attribs.length; ++ii) {
+      gl.bindAttribLocation(
+          program,
+          opt_locations ? opt_locations[ii] : ii,
+          opt_attribs[ii]);
+    }
+  }
+
+  gl.transformFeedbackVaryings(program, varyings, bufferMode);
+
+  gl.linkProgram(program);
+
+  // Check the link status
+  var linked = gl.getProgramParameter(program, gl.LINK_STATUS);
+  if (!linked) {
+      // something went wrong with the link
+      lastError = gl.getProgramInfoLog (program);
+      error("Error in program linking:" + lastError);
+
+      gl.deleteProgram(program);
+      return null;
+  }
+
+  gl.useProgram(program);
+  return program;
+};
+
+/**
+ * Creates a simple texture program.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @return {WebGLProgram}
+ */
+var setupNoTexCoordTextureProgram = function(gl) {
+  return setupProgram(gl,
+                      [noTexCoordTextureVertexShader, simpleTextureFragmentShader],
+                      ['vPosition'],
+                      [0]);
+};
+
+/**
+ * Creates a simple texture program.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {number} opt_positionLocation The attrib location for position.
+ * @param {number} opt_texcoordLocation The attrib location for texture coords.
+ * @return {WebGLProgram}
+ */
+var setupSimpleTextureProgram = function(
+    gl, opt_positionLocation, opt_texcoordLocation) {
+  opt_positionLocation = opt_positionLocation || 0;
+  opt_texcoordLocation = opt_texcoordLocation || 1;
+  return setupProgram(gl,
+                      [simpleTextureVertexShader, simpleTextureFragmentShader],
+                      ['vPosition', 'texCoord0'],
+                      [opt_positionLocation, opt_texcoordLocation]);
+};
+
+/**
+ * Creates a simple cube map texture program.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {number} opt_positionLocation The attrib location for position.
+ * @param {number} opt_texcoordLocation The attrib location for texture coords.
+ * @return {WebGLProgram}
+ */
+var setupSimpleCubeMapTextureProgram = function(
+    gl, opt_positionLocation, opt_texcoordLocation) {
+  opt_positionLocation = opt_positionLocation || 0;
+  opt_texcoordLocation = opt_texcoordLocation || 1;
+  return setupProgram(gl,
+                      [simpleTextureVertexShader, simpleCubeMapTextureFragmentShader],
+                      ['vPosition', 'texCoord0'],
+                      [opt_positionLocation, opt_texcoordLocation]);
+};
+
+/**
+ * Creates a simple vertex color program.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {number} opt_positionLocation The attrib location for position.
+ * @param {number} opt_vertexColorLocation The attrib location
+ *        for vertex colors.
+ * @return {WebGLProgram}
+ */
+var setupSimpleVertexColorProgram = function(
+    gl, opt_positionLocation, opt_vertexColorLocation) {
+  opt_positionLocation = opt_positionLocation || 0;
+  opt_vertexColorLocation = opt_vertexColorLocation || 1;
+  return setupProgram(gl,
+                      [simpleVertexColorVertexShader, simpleVertexColorFragmentShader],
+                      ['vPosition', 'a_color'],
+                      [opt_positionLocation, opt_vertexColorLocation]);
+};
+
+/**
+ * Creates a simple color program.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {number} opt_positionLocation The attrib location for position.
+ * @return {WebGLProgram}
+ */
+var setupSimpleColorProgram = function(gl, opt_positionLocation) {
+  opt_positionLocation = opt_positionLocation || 0;
+  return setupProgram(gl,
+                      [simpleVertexShader, simpleColorFragmentShader],
+                      ['vPosition'],
+                      [opt_positionLocation]);
+};
+
+/**
+ * Creates buffers for a textured unit quad and attaches them to vertex attribs.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {number} opt_positionLocation The attrib location for position.
+ * @param {number} opt_texcoordLocation The attrib location for texture coords.
+ * @return {!Array.<WebGLBuffer>} The buffer objects that were
+ *      created.
+ */
+var setupUnitQuad = function(gl, opt_positionLocation, opt_texcoordLocation) {
+  return setupUnitQuadWithTexCoords(gl, [ 0.0, 0.0 ], [ 1.0, 1.0 ],
+                                    opt_positionLocation, opt_texcoordLocation);
+};
+
+/**
+ * Creates buffers for a textured unit quad with specified lower left
+ * and upper right texture coordinates, and attaches them to vertex
+ * attribs.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {!Array.<number>} lowerLeftTexCoords The texture coordinates for the lower left corner.
+ * @param {!Array.<number>} upperRightTexCoords The texture coordinates for the upper right corner.
+ * @param {number} opt_positionLocation The attrib location for position.
+ * @param {number} opt_texcoordLocation The attrib location for texture coords.
+ * @return {!Array.<WebGLBuffer>} The buffer objects that were
+ *      created.
+ */
+var setupUnitQuadWithTexCoords = function(
+    gl, lowerLeftTexCoords, upperRightTexCoords,
+    opt_positionLocation, opt_texcoordLocation) {
+  return setupQuad(gl, {
+    positionLocation: opt_positionLocation || 0,
+    texcoordLocation: opt_texcoordLocation || 1,
+    lowerLeftTexCoords: lowerLeftTexCoords,
+    upperRightTexCoords: upperRightTexCoords
+  });
+};
+
+/**
+ * Makes a quad with various options.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {!Object} options
+ *
+ * scale: scale to multiple unit quad values by. default 1.0.
+ * positionLocation: attribute location for position.
+ * texcoordLocation: attribute location for texcoords.
+ *     If this does not exist no texture coords are created.
+ * lowerLeftTexCoords: an array of 2 values for the
+ *     lowerLeftTexCoords.
+ * upperRightTexCoords: an array of 2 values for the
+ *     upperRightTexCoords.
+ */
+var setupQuad = function(gl, options) {
+  var positionLocation = options.positionLocation || 0;
+  var scale = options.scale || 1;
+
+  var objects = [];
+
+  var vertexObject = gl.createBuffer();
+  gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
+       1.0 * scale ,  1.0 * scale,
+      -1.0 * scale ,  1.0 * scale,
+      -1.0 * scale , -1.0 * scale,
+       1.0 * scale ,  1.0 * scale,
+      -1.0 * scale , -1.0 * scale,
+       1.0 * scale , -1.0 * scale]), gl.STATIC_DRAW);
+  gl.enableVertexAttribArray(positionLocation);
+  gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
+  objects.push(vertexObject);
+
+  if (options.texcoordLocation !== undefined) {
+    var llx = options.lowerLeftTexCoords[0];
+    var lly = options.lowerLeftTexCoords[1];
+    var urx = options.upperRightTexCoords[0];
+    var ury = options.upperRightTexCoords[1];
+
+    vertexObject = gl.createBuffer();
+    gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
+        urx, ury,
+        llx, ury,
+        llx, lly,
+        urx, ury,
+        llx, lly,
+        urx, lly]), gl.STATIC_DRAW);
+    gl.enableVertexAttribArray(options.texcoordLocation);
+    gl.vertexAttribPointer(options.texcoordLocation, 2, gl.FLOAT, false, 0, 0);
+    objects.push(vertexObject);
+  }
+
+  return objects;
+};
+
+/**
+ * Creates a program and buffers for rendering a textured quad.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {number} opt_positionLocation The attrib location for
+ *        position. Default = 0.
+ * @param {number} opt_texcoordLocation The attrib location for
+ *        texture coords. Default = 1.
+ * @return {!WebGLProgram}
+ */
+var setupTexturedQuad = function(
+    gl, opt_positionLocation, opt_texcoordLocation) {
+  var program = setupSimpleTextureProgram(
+      gl, opt_positionLocation, opt_texcoordLocation);
+  setupUnitQuad(gl, opt_positionLocation, opt_texcoordLocation);
+  return program;
+};
+
+/**
+ * Creates a program and buffers for rendering a color quad.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {number} opt_positionLocation The attrib location for position.
+ * @return {!WebGLProgram}
+ */
+var setupColorQuad = function(gl, opt_positionLocation) {
+  opt_positionLocation = opt_positionLocation || 0;
+  var program = setupSimpleColorProgram(gl);
+  setupUnitQuad(gl, opt_positionLocation);
+  return program;
+};
+
+/**
+ * Creates a program and buffers for rendering a textured quad with
+ * specified lower left and upper right texture coordinates.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {!Array.<number>} lowerLeftTexCoords The texture coordinates for the lower left corner.
+ * @param {!Array.<number>} upperRightTexCoords The texture coordinates for the upper right corner.
+ * @param {number} opt_positionLocation The attrib location for position.
+ * @param {number} opt_texcoordLocation The attrib location for texture coords.
+ * @return {!WebGLProgram}
+ */
+var setupTexturedQuadWithTexCoords = function(
+    gl, lowerLeftTexCoords, upperRightTexCoords,
+    opt_positionLocation, opt_texcoordLocation) {
+  var program = setupSimpleTextureProgram(
+      gl, opt_positionLocation, opt_texcoordLocation);
+  setupUnitQuadWithTexCoords(gl, lowerLeftTexCoords, upperRightTexCoords,
+                             opt_positionLocation, opt_texcoordLocation);
+  return program;
+};
+
+/**
+ * Creates a program and buffers for rendering a textured quad with
+ * a cube map texture.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {number} opt_positionLocation The attrib location for
+ *        position. Default = 0.
+ * @param {number} opt_texcoordLocation The attrib location for
+ *        texture coords. Default = 1.
+ * @return {!WebGLProgram}
+ */
+var setupTexturedQuadWithCubeMap = function(
+    gl, opt_positionLocation, opt_texcoordLocation) {
+  var program = setupSimpleCubeMapTextureProgram(
+      gl, opt_positionLocation, opt_texcoordLocation);
+  setupUnitQuad(gl, opt_positionLocation, opt_texcoordLocation);
+  return program;
+};
+
+/**
+ * Creates a unit quad with only positions of a given resolution.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {number} gridRes The resolution of the mesh grid,
+ *     expressed in the number of quads across and down.
+ * @param {number} opt_positionLocation The attrib location for position.
+ */
+var setupIndexedQuad = function (
+    gl, gridRes, opt_positionLocation, opt_flipOddTriangles) {
+  return setupIndexedQuadWithOptions(gl,
+    { gridRes: gridRes,
+      positionLocation: opt_positionLocation,
+      flipOddTriangles: opt_flipOddTriangles
+    });
+};
+
+/**
+ * Creates a quad with various options.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {!Object} options The options. See below.
+ * @return {!Array.<WebGLBuffer>} The created buffers.
+ *     [positions, <colors>, indices]
+ *
+ * Options:
+ *   gridRes: number of quads across and down grid.
+ *   positionLocation: attrib location for position
+ *   flipOddTriangles: reverse order of vertices of every other
+ *       triangle
+ *   positionOffset: offset added to each vertex
+ *   positionMult: multipier for each vertex
+ *   colorLocation: attrib location for vertex colors. If
+ *      undefined no vertex colors will be created.
+ */
+var setupIndexedQuadWithOptions = function (gl, options) {
+  var positionLocation = options.positionLocation || 0;
+  var objects = [];
+
+  var gridRes = options.gridRes || 1;
+  var positionOffset = options.positionOffset || 0;
+  var positionMult = options.positionMult || 1;
+  var vertsAcross = gridRes + 1;
+  var numVerts = vertsAcross * vertsAcross;
+  var positions = new Float32Array(numVerts * 3);
+  var indices = new Uint16Array(6 * gridRes * gridRes);
+  var poffset = 0;
+
+  for (var yy = 0; yy <= gridRes; ++yy) {
+    for (var xx = 0; xx <= gridRes; ++xx) {
+      positions[poffset + 0] = (-1 + 2 * xx / gridRes) * positionMult + positionOffset;
+      positions[poffset + 1] = (-1 + 2 * yy / gridRes) * positionMult + positionOffset;
+      positions[poffset + 2] = 0;
+
+      poffset += 3;
+    }
+  }
+
+  var buf = gl.createBuffer();
+  gl.bindBuffer(gl.ARRAY_BUFFER, buf);
+  gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW);
+  gl.enableVertexAttribArray(positionLocation);
+  gl.vertexAttribPointer(positionLocation, 3, gl.FLOAT, false, 0, 0);
+  objects.push(buf);
+
+  if (options.colorLocation !== undefined) {
+    var colors = new Float32Array(numVerts * 4);
+    for (var yy = 0; yy <= gridRes; ++yy) {
+      for (var xx = 0; xx <= gridRes; ++xx) {
+        if (options.color !== undefined) {
+          colors[poffset + 0] = options.color[0];
+          colors[poffset + 1] = options.color[1];
+          colors[poffset + 2] = options.color[2];
+          colors[poffset + 3] = options.color[3];
+        } else {
+          colors[poffset + 0] = xx / gridRes;
+          colors[poffset + 1] = yy / gridRes;
+          colors[poffset + 2] = (xx / gridRes) * (yy / gridRes);
+          colors[poffset + 3] = (yy % 2) * 0.5 + 0.5;
+        }
+        poffset += 4;
+      }
+    }
+
+    buf = gl.createBuffer();
+    gl.bindBuffer(gl.ARRAY_BUFFER, buf);
+    gl.bufferData(gl.ARRAY_BUFFER, colors, gl.STATIC_DRAW);
+    gl.enableVertexAttribArray(options.colorLocation);
+    gl.vertexAttribPointer(options.colorLocation, 4, gl.FLOAT, false, 0, 0);
+    objects.push(buf);
+  }
+
+  var tbase = 0;
+  for (var yy = 0; yy < gridRes; ++yy) {
+    var index = yy * vertsAcross;
+    for (var xx = 0; xx < gridRes; ++xx) {
+      indices[tbase + 0] = index + 0;
+      indices[tbase + 1] = index + 1;
+      indices[tbase + 2] = index + vertsAcross;
+      indices[tbase + 3] = index + vertsAcross;
+      indices[tbase + 4] = index + 1;
+      indices[tbase + 5] = index + vertsAcross + 1;
+
+      if (options.flipOddTriangles) {
+        indices[tbase + 4] = index + vertsAcross + 1;
+        indices[tbase + 5] = index + 1;
+      }
+
+      index += 1;
+      tbase += 6;
+    }
+  }
+
+  buf = gl.createBuffer();
+  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buf);
+  gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
+  objects.push(buf);
+
+  return objects;
+};
+
+/**
+ * Returns the constructor for a typed array that corresponds to the given
+ * WebGL type.
+ * @param {!WebGLRenderingContext} gl A WebGLRenderingContext.
+ * @param {number} type The WebGL type (eg, gl.UNSIGNED_BYTE)
+ * @return {!Constructor} The typed array constructor that
+ *      corresponds to the given type.
+ */
+var glTypeToTypedArrayType = function(gl, type) {
+  switch (type) {
+    case gl.BYTE:
+      return window.Int8Array;
+    case gl.UNSIGNED_BYTE:
+      return window.Uint8Array;
+    case gl.SHORT:
+      return window.Int16Array;
+    case gl.UNSIGNED_SHORT:
+    case gl.UNSIGNED_SHORT_5_6_5:
+    case gl.UNSIGNED_SHORT_4_4_4_4:
+    case gl.UNSIGNED_SHORT_5_5_5_1:
+      return window.Uint16Array;
+    case gl.INT:
+      return window.Int32Array;
+    case gl.UNSIGNED_INT:
+      return window.Uint32Array;
+    default:
+      throw 'unknown gl type ' + glEnumToString(gl, type);
+  }
+};
+
+/**
+ * Returns the number of bytes per component for a given WebGL type.
+ * @param {!WebGLRenderingContext} gl A WebGLRenderingContext.
+ * @param {GLenum} type The WebGL type (eg, gl.UNSIGNED_BYTE)
+ * @return {number} The number of bytes per component.
+ */
+var getBytesPerComponent = function(gl, type) {
+  switch (type) {
+    case gl.BYTE:
+    case gl.UNSIGNED_BYTE:
+      return 1;
+    case gl.SHORT:
+    case gl.UNSIGNED_SHORT:
+    case gl.UNSIGNED_SHORT_5_6_5:
+    case gl.UNSIGNED_SHORT_4_4_4_4:
+    case gl.UNSIGNED_SHORT_5_5_5_1:
+      return 2;
+    case gl.INT:
+    case gl.UNSIGNED_INT:
+      return 4;
+    default:
+      throw 'unknown gl type ' + glEnumToString(gl, type);
+  }
+};
+
+/**
+ * Returns the number of typed array elements per pixel for a given WebGL
+ * format/type combination. The corresponding typed array type can be determined
+ * by calling glTypeToTypedArrayType.
+ * @param {!WebGLRenderingContext} gl A WebGLRenderingContext.
+ * @param {GLenum} format The WebGL format (eg, gl.RGBA)
+ * @param {GLenum} type The WebGL type (eg, gl.UNSIGNED_BYTE)
+ * @return {number} The number of typed array elements per pixel.
+ */
+var getTypedArrayElementsPerPixel = function(gl, format, type) {
+  switch (type) {
+    case gl.UNSIGNED_SHORT_5_6_5:
+    case gl.UNSIGNED_SHORT_4_4_4_4:
+    case gl.UNSIGNED_SHORT_5_5_5_1:
+      return 1;
+    case gl.UNSIGNED_BYTE:
+      break;
+    default:
+      throw 'not a gl type for color information ' + glEnumToString(gl, type);
+  }
+
+  switch (format) {
+    case gl.RGBA:
+      return 4;
+    case gl.RGB:
+      return 3;
+    case gl.LUMINANCE_ALPHA:
+      return 2;
+    case gl.LUMINANCE:
+    case gl.ALPHA:
+      return 1;
+    default:
+      throw 'unknown gl format ' + glEnumToString(gl, format);
+  }
+};
+
+/**
+ * Fills the given texture with a solid color.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {!WebGLTexture} tex The texture to fill.
+ * @param {number} width The width of the texture to create.
+ * @param {number} height The height of the texture to create.
+ * @param {!Array.<number>} color The color to fill with.
+ *        where each element is in the range 0 to 255.
+ * @param {number} opt_level The level of the texture to fill. Default = 0.
+ * @param {number} opt_format The format for the texture.
+ */
+var fillTexture = function(gl, tex, width, height, color, opt_level, opt_format, opt_type) {
+  opt_level = opt_level || 0;
+  opt_format = opt_format || gl.RGBA;
+  opt_type = opt_type || gl.UNSIGNED_BYTE;
+  var pack = gl.getParameter(gl.UNPACK_ALIGNMENT);
+  var numComponents = color.length;
+  var bytesPerComponent = getBytesPerComponent(gl, opt_type);
+  var rowSize = numComponents * width * bytesPerComponent;
+  var paddedRowSize = Math.floor((rowSize + pack - 1) / pack) * pack;
+  var size = rowSize + (height - 1) * paddedRowSize;
+  size = Math.floor((size + bytesPerComponent - 1) / bytesPerComponent) * bytesPerComponent;
+  var buf = new (glTypeToTypedArrayType(gl, opt_type))(size);
+  for (var yy = 0; yy < height; ++yy) {
+    var off = yy * paddedRowSize;
+    for (var xx = 0; xx < width; ++xx) {
+      for (var jj = 0; jj < numComponents; ++jj) {
+        buf[off++] = color[jj];
+      }
+    }
+  }
+  gl.bindTexture(gl.TEXTURE_2D, tex);
+  gl.texImage2D(
+      gl.TEXTURE_2D, opt_level, opt_format, width, height, 0,
+      opt_format, opt_type, buf);
+};
+
+/**
+ * Creates a texture and fills it with a solid color.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {number} width The width of the texture to create.
+ * @param {number} height The height of the texture to create.
+ * @param {!Array.<number>} color The color to fill with. A 4 element array
+ *        where each element is in the range 0 to 255.
+ * @return {!WebGLTexture}
+ */
+var createColoredTexture = function(gl, width, height, color) {
+  var tex = gl.createTexture();
+  fillTexture(gl, tex, width, height, color);
+  return tex;
+};
+
+var ubyteToFloat = function(c) {
+  return c / 255;
+};
+
+var ubyteColorToFloatColor = function(color) {
+  var floatColor = [];
+  for (var ii = 0; ii < color.length; ++ii) {
+    floatColor[ii] = ubyteToFloat(color[ii]);
+  }
+  return floatColor;
+};
+
+/**
+ * Sets the "u_color" uniform of the current program to color.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {!Array.<number>} color 4 element array of 0-1 color
+ *      components.
+ */
+var setFloatDrawColor = function(gl, color) {
+  var program = gl.getParameter(gl.CURRENT_PROGRAM);
+  var colorLocation = gl.getUniformLocation(program, "u_color");
+  gl.uniform4fv(colorLocation, color);
+};
+
+/**
+ * Sets the "u_color" uniform of the current program to color.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {!Array.<number>} color 4 element array of 0-255 color
+ *      components.
+ */
+var setUByteDrawColor = function(gl, color) {
+  setFloatDrawColor(gl, ubyteColorToFloatColor(color));
+};
+
+/**
+ * Draws a previously setup quad in the given color.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {!Array.<number>} color The color to draw with. A 4
+ *        element array where each element is in the range 0 to
+ *        1.
+ */
+var drawFloatColorQuad = function(gl, color) {
+  var program = gl.getParameter(gl.CURRENT_PROGRAM);
+  var colorLocation = gl.getUniformLocation(program, "u_color");
+  gl.uniform4fv(colorLocation, color);
+  gl.drawArrays(gl.TRIANGLES, 0, 6);
+};
+
+
+/**
+ * Draws a previously setup quad in the given color.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {!Array.<number>} color The color to draw with. A 4
+ *        element array where each element is in the range 0 to
+ *        255.
+ */
+var drawUByteColorQuad = function(gl, color) {
+  drawFloatColorQuad(gl, ubyteColorToFloatColor(color));
+};
+
+/**
+ * Draws a previously setupUnitQuad.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ */
+var drawUnitQuad = function(gl) {
+  gl.drawArrays(gl.TRIANGLES, 0, 6);
+};
+
+/**
+ * Clears then Draws a previously setupUnitQuad.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {!Array.<number>} opt_color The color to fill clear with before
+ *        drawing. A 4 element array where each element is in the range 0 to
+ *        255. Default [255, 255, 255, 255]
+ */
+var clearAndDrawUnitQuad = function(gl, opt_color) {
+  opt_color = opt_color || [255, 255, 255, 255];
+  gl.clearColor(
+      opt_color[0] / 255,
+      opt_color[1] / 255,
+      opt_color[2] / 255,
+      opt_color[3] / 255);
+  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+  drawUnitQuad(gl);
+};
+
+/**
+ * Draws a quad previously setup with setupIndexedQuad.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {number} gridRes Resolution of grid.
+ */
+var drawIndexedQuad = function(gl, gridRes) {
+  gl.drawElements(gl.TRIANGLES, gridRes * gridRes * 6, gl.UNSIGNED_SHORT, 0);
+};
+
+/**
+ * Draws a previously setupIndexedQuad
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {number} gridRes Resolution of grid.
+ * @param {!Array.<number>} opt_color The color to fill clear with before
+ *        drawing. A 4 element array where each element is in the range 0 to
+ *        255. Default [255, 255, 255, 255]
+ */
+var clearAndDrawIndexedQuad = function(gl, gridRes, opt_color) {
+  opt_color = opt_color || [255, 255, 255, 255];
+  gl.clearColor(
+      opt_color[0] / 255,
+      opt_color[1] / 255,
+      opt_color[2] / 255,
+      opt_color[3] / 255);
+  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+  drawIndexedQuad(gl, gridRes);
+};
+
+/**
+ * Clips a range to min, max
+ * (Eg. clipToRange(-5,7,0,20) would return {value:0,extent:2}
+ * @param {number} value start of range
+ * @param {number} extent extent of range
+ * @param {number} min min.
+ * @param {number} max max.
+ * @return {!{value:number,extent:number}} The clipped value.
+ */
+var clipToRange = function(value, extent, min, max) {
+  if (value < min) {
+    extent -= min - value;
+    value = min;
+  }
+  var end = value + extent;
+  if (end > max) {
+    extent -= end - max;
+  }
+  if (extent < 0) {
+    value = max;
+    extent = 0;
+  }
+  return {value:value, extent: extent};
+};
+
+/**
+ * Determines if the passed context is an instance of a WebGLRenderingContext
+ * or later variant (like WebGL2RenderingContext)
+ * @param {CanvasRenderingContext} ctx The context to check.
+ */
+var isWebGLContext = function(ctx) {
+  if (ctx instanceof WebGLRenderingContext)
+    return true;
+
+  if ('WebGL2RenderingContext' in window && ctx instanceof WebGL2RenderingContext)
+    return true;
+
+  return false;
+};
+
+/**
+ * Creates a check rect is used by checkCanvasRects.
+ * @param {number} x left corner of region to check.
+ * @param {number} y bottom corner of region to check in case of checking from
+ *        a GL context or top corner in case of checking from a 2D context.
+ * @param {number} width width of region to check.
+ * @param {number} height width of region to check.
+ * @param {!Array.<number>} color The color expected. A 4 element array where
+ *        each element is in the range 0 to 255.
+ * @param {string} opt_msg Message to associate with success. Eg
+ *        ("should be red").
+ * @param {number} opt_errorRange Optional. Acceptable error in
+ *        color checking. 0 by default.
+ */
+var makeCheckRect = function(x, y, width, height, color, msg, errorRange) {
+  var rect = {
+    'x': x, 'y': y,
+    'width': width, 'height': height,
+    'color': color, 'msg': msg,
+    'errorRange': errorRange,
+
+    'checkRect': function (buf, l, b, w) {
+      for (var px = (x - l) ; px < (x + width - l) ; ++px) {
+        for (var py = (y - b) ; py < (y + height - b) ; ++py) {
+          var offset = (py * w + px) * 4;
+          for (var j = 0; j < color.length; ++j) {
+            if (Math.abs(buf[offset + j] - color[j]) > errorRange) {
+              testFailed(msg);
+              var was = buf[offset + 0].toString();
+              for (j = 1; j < color.length; ++j) {
+                was += "," + buf[offset + j];
+              }
+              debug('at (' + px + ', ' + py +
+                    ') expected: ' + color + ' was ' + was);
+              return;
+            }
+          }
+        }
+      }
+      testPassed(msg);
+    }
+  }
+  return rect;
+};
+
+/**
+ * Checks that a portions of a canvas or the currently attached framebuffer is 1 color.
+ * @param {!WebGLRenderingContext|CanvasRenderingContext2D} gl The
+ *         WebGLRenderingContext or 2D context to use.
+ * @param {!Array.<checkRect>} array of rects to check for matching color.
+ */
+var checkCanvasRects = function(gl, rects) {
+  if (rects.length > 0) {
+    var left = rects[0].x;
+    var right = rects[0].x + rects[1].width;
+    var bottom = rects[0].y;
+    var top = rects[0].y + rects[0].height;
+    for (var i = 1; i < rects.length; ++i) {
+      left = Math.min(left, rects[i].x);
+      right = Math.max(right, rects[i].x + rects[i].width);
+      bottom = Math.min(bottom, rects[i].y);
+      top = Math.max(top, rects[i].y + rects[i].height);
+    }
+    var width = right - left;
+    var height = top - bottom;
+    var buf = new Uint8Array(width * height * 4);
+    gl.readPixels(left, bottom, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+    for (var i = 0; i < rects.length; ++i) {
+      rects[i].checkRect(buf, left, bottom, width);
+    }
+  }
+};
+
+/**
+ * Checks that a portion of a canvas or the currently attached framebuffer is 1 color.
+ * @param {!WebGLRenderingContext|CanvasRenderingContext2D} gl The
+ *         WebGLRenderingContext or 2D context to use.
+ * @param {number} x left corner of region to check.
+ * @param {number} y bottom corner of region to check in case of checking from
+ *        a GL context or top corner in case of checking from a 2D context.
+ * @param {number} width width of region to check.
+ * @param {number} height width of region to check.
+ * @param {!Array.<number>} color The color expected. A 4 element array where
+ *        each element is in the range 0 to 255.
+ * @param {number} opt_errorRange Optional. Acceptable error in
+ *        color checking. 0 by default.
+ * @param {!function()} sameFn Function to call if all pixels
+ *        are the same as color.
+ * @param {!function()} differentFn Function to call if a pixel
+ *        is different than color
+ * @param {!function()} logFn Function to call for logging.
+ * @param {Uint8Array} opt_readBackBuf typically passed to reuse existing
+ *        buffer while reading back pixels.
+ */
+var checkCanvasRectColor = function(gl, x, y, width, height, color, opt_errorRange, sameFn, differentFn, logFn, opt_readBackBuf) {
+  if (isWebGLContext(gl) && !gl.getParameter(gl.FRAMEBUFFER_BINDING)) {
+    // We're reading the backbuffer so clip.
+    var xr = clipToRange(x, width, 0, gl.canvas.width);
+    var yr = clipToRange(y, height, 0, gl.canvas.height);
+    if (!xr.extent || !yr.extent) {
+      logFn("checking rect: effective width or height is zero");
+      sameFn();
+      return;
+    }
+    x = xr.value;
+    y = yr.value;
+    width = xr.extent;
+    height = yr.extent;
+  }
+  var errorRange = opt_errorRange || 0;
+  if (!errorRange.length) {
+    errorRange = [errorRange, errorRange, errorRange, errorRange]
+  }
+  var buf;
+  if (isWebGLContext(gl)) {
+    buf = opt_readBackBuf ? opt_readBackBuf : new Uint8Array(width * height * 4);
+    gl.readPixels(x, y, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+  } else {
+    buf = gl.getImageData(x, y, width, height).data;
+  }
+  for (var i = 0; i < width * height; ++i) {
+    var offset = i * 4;
+    for (var j = 0; j < color.length; ++j) {
+      if (Math.abs(buf[offset + j] - color[j]) > errorRange[j]) {
+        var was = buf[offset + 0].toString();
+        for (j = 1; j < color.length; ++j) {
+          was += "," + buf[offset + j];
+        }
+        differentFn('at (' + (x + (i % width)) + ', ' + (y + Math.floor(i / width)) +
+                    ') expected: ' + color + ' was ' + was);
+        return;
+      }
+    }
+  }
+  sameFn();
+};
+
+/**
+ * Checks that a portion of a canvas or the currently attached framebuffer is 1 color.
+ * @param {!WebGLRenderingContext|CanvasRenderingContext2D} gl The
+ *         WebGLRenderingContext or 2D context to use.
+ * @param {number} x left corner of region to check.
+ * @param {number} y bottom corner of region to check in case of checking from
+ *        a GL context or top corner in case of checking from a 2D context.
+ * @param {number} width width of region to check.
+ * @param {number} height width of region to check.
+ * @param {!Array.<number>} color The color expected. A 4 element array where
+ *        each element is in the range 0 to 255.
+ * @param {string} opt_msg Message to associate with success. Eg
+ *        ("should be red").
+ * @param {number} opt_errorRange Optional. Acceptable error in
+ *        color checking. 0 by default.
+ */
+var checkCanvasRect = function(gl, x, y, width, height, color, opt_msg, opt_errorRange) {
+  checkCanvasRectColor(
+      gl, x, y, width, height, color, opt_errorRange,
+      function() {
+        var msg = opt_msg;
+        if (msg === undefined)
+          msg = "should be " + color.toString();
+        testPassed(msg);
+      },
+      testFailed,
+      debug);
+};
+
+/**
+ * Checks that an entire canvas or the currently attached framebuffer is 1 color.
+ * @param {!WebGLRenderingContext|CanvasRenderingContext2D} gl The
+ *         WebGLRenderingContext or 2D context to use.
+ * @param {!Array.<number>} color The color expected. A 4 element array where
+ *        each element is in the range 0 to 255.
+ * @param {string} msg Message to associate with success. Eg ("should be red").
+ * @param {number} errorRange Optional. Acceptable error in
+ *        color checking. 0 by default.
+ */
+var checkCanvas = function(gl, color, msg, errorRange) {
+  checkCanvasRect(gl, 0, 0, gl.canvas.width, gl.canvas.height, color, msg, errorRange);
+};
+
+/**
+ * Checks a rectangular area both inside the area and outside
+ * the area.
+ * @param {!WebGLRenderingContext|CanvasRenderingContext2D} gl The
+ *         WebGLRenderingContext or 2D context to use.
+ * @param {number} x left corner of region to check.
+ * @param {number} y bottom corner of region to check in case of checking from
+ *        a GL context or top corner in case of checking from a 2D context.
+ * @param {number} width width of region to check.
+ * @param {number} height width of region to check.
+ * @param {!Array.<number>} innerColor The color expected inside
+ *     the area. A 4 element array where each element is in the
+ *     range 0 to 255.
+ * @param {!Array.<number>} outerColor The color expected
+ *     outside. A 4 element array where each element is in the
+ *     range 0 to 255.
+ * @param {!number} opt_edgeSize: The number of pixels to skip
+ *     around the edges of the area. Defaut 0.
+ * @param {!{width:number, height:number}} opt_outerDimensions
+ *     The outer dimensions. Default the size of gl.canvas.
+ */
+var checkAreaInAndOut = function(gl, x, y, width, height, innerColor, outerColor, opt_edgeSize, opt_outerDimensions) {
+  var outerDimensions = opt_outerDimensions || { width: gl.canvas.width, height: gl.canvas.height };
+  var edgeSize = opt_edgeSize || 0;
+  checkCanvasRect(gl, x + edgeSize, y + edgeSize, width - edgeSize * 2, height - edgeSize * 2, innerColor);
+  checkCanvasRect(gl, 0, 0, x - edgeSize, outerDimensions.height, outerColor);
+  checkCanvasRect(gl, x + width + edgeSize, 0, outerDimensions.width - x - width - edgeSize, outerDimensions.height, outerColor);
+  checkCanvasRect(gl, 0, 0, outerDimensions.width, y - edgeSize, outerColor);
+  checkCanvasRect(gl, 0, y + height + edgeSize, outerDimensions.width, outerDimensions.height - y - height - edgeSize, outerColor);
+};
+
+/**
+ * Checks that an entire buffer matches the floating point values provided.
+ * (WebGL 2.0 only)
+ * @param {!WebGL2RenderingContext} gl The WebGL2RenderingContext to use.
+ * @param {number} target The buffer target to bind to.
+ * @param {!Array.<number>} expected The values expected.
+ * @param {string} opt_msg Optional. Message to associate with success. Eg ("should be red").
+ * @param {number} opt_errorRange Optional. Acceptable error in value checking. 0.001 by default.
+ */
+var checkFloatBuffer = function(gl, target, expected, opt_msg, opt_errorRange) {
+  if (opt_msg === undefined)
+    opt_msg = "buffer should match expected values";
+
+  if (opt_errorRange === undefined)
+    opt_errorRange = 0.001;
+
+  var outData = new ArrayBuffer(Float32Array.BYTES_PER_ELEMENT * expected.length);
+  gl.getBufferSubData(target, 0, outData);
+
+  var floatArray = new Float32Array(outData);
+  for (var i = 0; i < expected.length; i++) {
+    if (Math.abs(floatArray[i] - expected[i]) > opt_errorRange) {
+      testFailed(opt_msg);
+      debug('at [' + i + '] expected: ' + expected[i] + ' was ' + floatArray[i]);
+      return;
+    }
+  }
+  testPassed(opt_msg);
+};
+
+/**
+ * Loads a texture, calls callback when finished.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {string} url URL of image to load
+ * @param {function(!Image): void} callback Function that gets called after
+ *        image has loaded
+ * @return {!WebGLTexture} The created texture.
+ */
+var loadTexture = function(gl, url, callback) {
+    var texture = gl.createTexture();
+    gl.bindTexture(gl.TEXTURE_2D, texture);
+    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+    var image = new Image();
+    image.onload = function() {
+        gl.bindTexture(gl.TEXTURE_2D, texture);
+        gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
+        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
+        callback(image);
+    };
+    image.src = url;
+    return texture;
+};
+
+/**
+ * Checks whether the bound texture has expected dimensions. One corner pixel
+ * of the texture will be changed as a side effect.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {!WebGLTexture} texture The texture to check.
+ * @param {number} width Expected width.
+ * @param {number} height Expected height.
+ * @param {GLenum} opt_format The texture's format. Defaults to RGBA.
+ * @param {GLenum} opt_type The texture's type. Defaults to UNSIGNED_BYTE.
+ */
+var checkTextureSize = function(gl, width, height, opt_format, opt_type) {
+  opt_format = opt_format || gl.RGBA;
+  opt_type = opt_type || gl.UNSIGNED_BYTE;
+
+  var numElements = getTypedArrayElementsPerPixel(gl, opt_format, opt_type);
+  var buf = new (glTypeToTypedArrayType(gl, opt_type))(numElements);
+
+  var errors = 0;
+  gl.texSubImage2D(gl.TEXTURE_2D, 0, width - 1, height - 1, 1, 1, opt_format, opt_type, buf);
+  if (gl.getError() != gl.NO_ERROR) {
+    testFailed("Texture was smaller than the expected size " + width + "x" + height);
+    ++errors;
+  }
+  gl.texSubImage2D(gl.TEXTURE_2D, 0, width - 1, height, 1, 1, opt_format, opt_type, buf);
+  if (gl.getError() == gl.NO_ERROR) {
+    testFailed("Texture was taller than " + height);
+    ++errors;
+  }
+  gl.texSubImage2D(gl.TEXTURE_2D, 0, width, height - 1, 1, 1, opt_format, opt_type, buf);
+  if (gl.getError() == gl.NO_ERROR) {
+    testFailed("Texture was wider than " + width);
+    ++errors;
+  }
+  if (errors == 0) {
+    testPassed("Texture had the expected size " + width + "x" + height);
+  }
+};
+
+/**
+ * Makes a shallow copy of an object.
+ * @param {!Object} src Object to copy
+ * @return {!Object} The copy of src.
+ */
+var shallowCopyObject = function(src) {
+  var dst = {};
+  for (var attr in src) {
+    if (src.hasOwnProperty(attr)) {
+      dst[attr] = src[attr];
+    }
+  }
+  return dst;
+};
+
+/**
+ * Checks if an attribute exists on an object case insensitive.
+ * @param {!Object} obj Object to check
+ * @param {string} attr Name of attribute to look for.
+ * @return {string?} The name of the attribute if it exists,
+ *         undefined if not.
+ */
+var hasAttributeCaseInsensitive = function(obj, attr) {
+  var lower = attr.toLowerCase();
+  for (var key in obj) {
+    if (obj.hasOwnProperty(key) && key.toLowerCase() == lower) {
+      return key;
+    }
+  }
+};
+
+/**
+ * Returns a map of URL querystring options
+ * @return {Object?} Object containing all the values in the URL querystring
+ */
+var getUrlOptions = (function() {
+  var _urlOptionsParsed = false;
+  var _urlOptions = {};
+  return function() {
+    if (!_urlOptionsParsed) {
+      var s = window.location.href;
+      var q = s.indexOf("?");
+      var e = s.indexOf("#");
+      if (e < 0) {
+        e = s.length;
+      }
+      var query = s.substring(q + 1, e);
+      var pairs = query.split("&");
+      for (var ii = 0; ii < pairs.length; ++ii) {
+        var keyValue = pairs[ii].split("=");
+        var key = keyValue[0];
+        var value = decodeURIComponent(keyValue[1]);
+        _urlOptions[key] = value;
+      }
+      _urlOptionsParsed = true;
+    }
+
+    return _urlOptions;
+  }
+})();
+
+var default3DContextVersion = 1;
+
+/**
+ * Set the default context version for create3DContext.
+ * Initially the default version is 1.
+ * @param {number} Default version of WebGL contexts.
+ */
+var setDefault3DContextVersion = function(version) {
+    default3DContextVersion = version;
+};
+
+/**
+ * Get the default contex version for create3DContext.
+ * First it looks at the URI option |webglVersion|. If it does not exist,
+ * then look at the global default3DContextVersion variable.
+ */
+var getDefault3DContextVersion = function() {
+    return parseInt(getUrlOptions().webglVersion, 10) || default3DContextVersion;
+};
+
+/**
+ * Creates a webgl context.
+ * @param {!Canvas|string} opt_canvas The canvas tag to get
+ *     context from. If one is not passed in one will be
+ *     created. If it's a string it's assumed to be the id of a
+ *     canvas.
+ * @param {Object} opt_attributes Context attributes.
+ * @param {!number} opt_version Version of WebGL context to create.
+ *     The default version can be set by calling setDefault3DContextVersion.
+ * @return {!WebGLRenderingContext} The created context.
+ */
+var create3DContext = function(opt_canvas, opt_attributes, opt_version) {
+  if (window.initTestingHarness) {
+    window.initTestingHarness();
+  }
+  var attributes = shallowCopyObject(opt_attributes || {});
+  if (!hasAttributeCaseInsensitive(attributes, "antialias")) {
+    attributes.antialias = false;
+  }
+  if (!opt_version) {
+    opt_version = parseInt(getUrlOptions().webglVersion, 10) || default3DContextVersion;
+  }
+  opt_canvas = opt_canvas || document.createElement("canvas");
+  if (typeof opt_canvas == 'string') {
+    opt_canvas = document.getElementById(opt_canvas);
+  }
+  var context = null;
+
+  var names;
+  switch (opt_version) {
+    case 2:
+      names = ["webgl2", "experimental-webgl2"]; break;
+    default:
+      names = ["webgl", "experimental-webgl"]; break;
+  }
+
+  for (var i = 0; i < names.length; ++i) {
+    try {
+      context = opt_canvas.getContext(names[i], attributes);
+    } catch (e) {
+    }
+    if (context) {
+      break;
+    }
+  }
+  if (!context) {
+    testFailed("Unable to fetch WebGL rendering context for Canvas");
+  }
+  return context;
+};
+
+/**
+ * Defines the exception type for a GL error.
+ * @constructor
+ * @param {string} message The error message.
+ * @param {number} error GL error code
+ */
+function GLErrorException (message, error) {
+   this.message = message;
+   this.name = "GLErrorException";
+   this.error = error;
+};
+
+/**
+ * Wraps a WebGL function with a function that throws an exception if there is
+ * an error.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {string} fname Name of function to wrap.
+ * @return {function()} The wrapped function.
+ */
+var createGLErrorWrapper = function(context, fname) {
+  return function() {
+    var rv = context[fname].apply(context, arguments);
+    var err = context.getError();
+    if (err != context.NO_ERROR) {
+      var msg = "GL error " + glEnumToString(context, err) + " in " + fname;
+      throw new GLErrorException(msg, err);
+    }
+    return rv;
+  };
+};
+
+/**
+ * Creates a WebGL context where all functions are wrapped to throw an exception
+ * if there is an error.
+ * @param {!Canvas} canvas The HTML canvas to get a context from.
+ * @param {Object} opt_attributes Context attributes.
+ * @param {!number} opt_version Version of WebGL context to create
+ * @return {!Object} The wrapped context.
+ */
+function create3DContextWithWrapperThatThrowsOnGLError(canvas, opt_attributes, opt_version) {
+  var context = create3DContext(canvas, opt_attributes, opt_version);
+  var wrap = {};
+  for (var i in context) {
+    try {
+      if (typeof context[i] == 'function') {
+        wrap[i] = createGLErrorWrapper(context, i);
+      } else {
+        wrap[i] = context[i];
+      }
+    } catch (e) {
+      error("createContextWrapperThatThrowsOnGLError: Error accessing " + i);
+    }
+  }
+  wrap.getError = function() {
+      return context.getError();
+  };
+  return wrap;
+};
+
+/**
+ * Tests that an evaluated expression generates a specific GL error.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {number|Array.<number>} glErrors The expected gl error or an array of expected errors.
+ * @param {string} evalStr The string to evaluate.
+ */
+var shouldGenerateGLError = function(gl, glErrors, evalStr) {
+  var exception;
+  try {
+    eval(evalStr);
+  } catch (e) {
+    exception = e;
+  }
+  if (exception) {
+    testFailed(evalStr + " threw exception " + exception);
+  } else {
+    glErrorShouldBe(gl, glErrors, "after evaluating: " + evalStr);
+  }
+};
+
+/**
+ * Tests that an evaluated expression does not generate a GL error.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {string} evalStr The string to evaluate.
+ */
+var failIfGLError = function(gl, evalStr) {
+  var exception;
+  try {
+    eval(evalStr);
+  } catch (e) {
+    exception = e;
+  }
+  if (exception) {
+    testFailed(evalStr + " threw exception " + exception);
+  } else {
+    glErrorShouldBeImpl(gl, gl.NO_ERROR, false, "after evaluating: " + evalStr);
+  }
+};
+
+/**
+ * Tests that the first error GL returns is the specified error.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {number|Array.<number>} glErrors The expected gl error or an array of expected errors.
+ * @param {string} opt_msg Optional additional message.
+ */
+var glErrorShouldBe = function(gl, glErrors, opt_msg) {
+  glErrorShouldBeImpl(gl, glErrors, true, opt_msg);
+};
+
+
+
+/**
+ * Tests that the first error GL returns is the specified error. Allows suppression of successes.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {number|Array.<number>} glErrors The expected gl error or an array of expected errors.
+ * @param {boolean} reportSuccesses Whether to report successes as passes, or to silently pass.
+ * @param {string} opt_msg Optional additional message.
+ */
+var glErrorShouldBeImpl = function(gl, glErrors, reportSuccesses, opt_msg) {
+  if (!glErrors.length) {
+    glErrors = [glErrors];
+  }
+  opt_msg = opt_msg || "";
+  var err = gl.getError();
+  var ndx = glErrors.indexOf(err);
+  var errStrs = [];
+  for (var ii = 0; ii < glErrors.length; ++ii) {
+    errStrs.push(glEnumToString(gl, glErrors[ii]));
+  }
+  var expected = errStrs.join(" or ");
+  if (ndx < 0) {
+    var msg = "getError expected" + ((glErrors.length > 1) ? " one of: " : ": ");
+    testFailed(msg + expected +  ". Was " + glEnumToString(gl, err) + " : " + opt_msg);
+  } else if (reportSuccesses) {
+    var msg = "getError was " + ((glErrors.length > 1) ? "one of: " : "expected value: ");
+    testPassed(msg + expected + " : " + opt_msg);
+  }
+};
+
+/**
+ * Links a WebGL program, throws if there are errors.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {!WebGLProgram} program The WebGLProgram to link.
+ * @param {function(string): void} opt_errorCallback callback for errors.
+ */
+var linkProgram = function(gl, program, opt_errorCallback) {
+  var errFn = opt_errorCallback || testFailed;
+  // Link the program
+  gl.linkProgram(program);
+
+  // Check the link status
+  var linked = gl.getProgramParameter(program, gl.LINK_STATUS);
+  if (!linked) {
+    // something went wrong with the link
+    var error = gl.getProgramInfoLog (program);
+
+    errFn("Error in program linking:" + error);
+
+    gl.deleteProgram(program);
+  }
+};
+
+/**
+ * Loads text from an external file. This function is asynchronous.
+ * @param {string} url The url of the external file.
+ * @param {!function(bool, string): void} callback that is sent a bool for
+ *     success and the string.
+ */
+var loadTextFileAsync = function(url, callback) {
+  log ("loading: " + url);
+  var error = 'loadTextFileAsync failed to load url "' + url + '"';
+  var request;
+  if (window.XMLHttpRequest) {
+    request = new XMLHttpRequest();
+    if (request.overrideMimeType) {
+      request.overrideMimeType('text/plain');
+    }
+  } else {
+    throw 'XMLHttpRequest is disabled';
+  }
+  try {
+    request.open('GET', url, true);
+    request.onreadystatechange = function() {
+      if (request.readyState == 4) {
+        var text = '';
+        // HTTP reports success with a 200 status. The file protocol reports
+        // success with zero. HTTP does not use zero as a status code (they
+        // start at 100).
+        // https://developer.mozilla.org/En/Using_XMLHttpRequest
+        var success = request.status == 200 || request.status == 0;
+        if (success) {
+          text = request.responseText;
+          log("completed load request: " + url);
+        } else {
+          log("loading " + url + " resulted in unexpected status: " + request.status + " " + request.statusText);
+        }
+        callback(success, text);
+      }
+    };
+    request.onerror = function(errorEvent) {
+      log("error occurred loading " + url);
+      callback(false, '');
+    };
+    request.send(null);
+  } catch (err) {
+    log("failed to load: " + url + " with exception " + err.message);
+    callback(false, '');
+  }
+};
+
+/**
+ * Recursively loads a file as a list. Each line is parsed for a relative
+ * path. If the file ends in .txt the contents of that file is inserted in
+ * the list.
+ *
+ * @param {string} url The url of the external file.
+ * @param {!function(bool, Array<string>): void} callback that is sent a bool
+ *     for success and the array of strings.
+ */
+var getFileListAsync = function(url, callback) {
+  var files = [];
+
+  var getFileListImpl = function(url, callback) {
+    var files = [];
+    if (url.substr(url.length - 4) == '.txt') {
+      loadTextFileAsync(url, function() {
+        return function(success, text) {
+          if (!success) {
+            callback(false, '');
+            return;
+          }
+          var lines = text.split('\n');
+          var prefix = '';
+          var lastSlash = url.lastIndexOf('/');
+          if (lastSlash >= 0) {
+            prefix = url.substr(0, lastSlash + 1);
+          }
+          var fail = false;
+          var count = 1;
+          var index = 0;
+          for (var ii = 0; ii < lines.length; ++ii) {
+            var str = lines[ii].replace(/^\s\s*/, '').replace(/\s\s*$/, '');
+            if (str.length > 4 &&
+                str[0] != '#' &&
+                str[0] != ";" &&
+                str.substr(0, 2) != "//") {
+              var names = str.split(/ +/);
+              var new_url = prefix + str;
+              if (names.length == 1) {
+                new_url = prefix + str;
+                ++count;
+                getFileListImpl(new_url, function(index) {
+                  return function(success, new_files) {
+                    log("got files: " + new_files.length);
+                    if (success) {
+                      files[index] = new_files;
+                    }
+                    finish(success);
+                  };
+                }(index++));
+              } else {
+                var s = "";
+                var p = "";
+                for (var jj = 0; jj < names.length; ++jj) {
+                  s += p + prefix + names[jj];
+                  p = " ";
+                }
+                files[index++] = s;
+              }
+            }
+          }
+          finish(true);
+
+          function finish(success) {
+            if (!success) {
+              fail = true;
+            }
+            --count;
+            log("count: " + count);
+            if (!count) {
+              callback(!fail, files);
+            }
+          }
+        }
+      }());
+
+    } else {
+      files.push(url);
+      callback(true, files);
+    }
+  };
+
+  getFileListImpl(url, function(success, files) {
+    // flatten
+    var flat = [];
+    flatten(files);
+    function flatten(files) {
+      for (var ii = 0; ii < files.length; ++ii) {
+        var value = files[ii];
+        if (typeof(value) == "string") {
+          flat.push(value);
+        } else {
+          flatten(value);
+        }
+      }
+    }
+    callback(success, flat);
+  });
+};
+
+/**
+ * Gets a file from a file/URL.
+ * @param {string} file the URL of the file to get.
+ * @return {string} The contents of the file.
+ */
+var readFile = function(file) {
+  var xhr = new XMLHttpRequest();
+  xhr.open("GET", file, false);
+  xhr.send();
+  return xhr.responseText.replace(/\r/g, "");
+};
+
+var readFileList = function(url) {
+  var files = [];
+  if (url.substr(url.length - 4) == '.txt') {
+    var lines = readFile(url).split('\n');
+    var prefix = '';
+    var lastSlash = url.lastIndexOf('/');
+    if (lastSlash >= 0) {
+      prefix = url.substr(0, lastSlash + 1);
+    }
+    for (var ii = 0; ii < lines.length; ++ii) {
+      var str = lines[ii].replace(/^\s\s*/, '').replace(/\s\s*$/, '');
+      if (str.length > 4 &&
+          str[0] != '#' &&
+          str[0] != ";" &&
+          str.substr(0, 2) != "//") {
+        var names = str.split(/ +/);
+        if (names.length == 1) {
+          var new_url = prefix + str;
+          files = files.concat(readFileList(new_url));
+        } else {
+          var s = "";
+          var p = "";
+          for (var jj = 0; jj < names.length; ++jj) {
+            s += p + prefix + names[jj];
+            p = " ";
+          }
+          files.push(s);
+        }
+      }
+    }
+  } else {
+    files.push(url);
+  }
+  return files;
+};
+
+/**
+ * Loads a shader.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {string} shaderSource The shader source.
+ * @param {number} shaderType The type of shader.
+ * @param {function(string): void} opt_errorCallback callback for errors.
+ * @param {boolean} opt_logShaders Whether to log shader source.
+ * @param {string} opt_shaderLabel Label that identifies the shader source in
+ *     the log.
+ * @param {string} opt_url URL from where the shader source was loaded from.
+ *     If opt_logShaders is set, then a link to the source file will also be
+ *     added.
+ * @param {boolean} Skip compilation status check. Default = false.
+ * @return {!WebGLShader} The created shader.
+ */
+var loadShader = function(
+    gl, shaderSource, shaderType, opt_errorCallback, opt_logShaders,
+    opt_shaderLabel, opt_url, opt_skipCompileStatus) {
+  var errFn = opt_errorCallback || error;
+  // Create the shader object
+  var shader = gl.createShader(shaderType);
+  if (shader == null) {
+    errFn("*** Error: unable to create shader '"+shaderSource+"'");
+    return null;
+  }
+
+  // Load the shader source
+  gl.shaderSource(shader, shaderSource);
+  var err = gl.getError();
+  if (err != gl.NO_ERROR) {
+    errFn("*** Error loading shader '" + shader + "':" + glEnumToString(gl, err));
+    return null;
+  }
+
+  // Compile the shader
+  gl.compileShader(shader);
+
+  if (opt_logShaders) {
+    var label = shaderType == gl.VERTEX_SHADER ? 'vertex shader' : 'fragment_shader';
+    if (opt_shaderLabel) {
+      label = opt_shaderLabel + ' ' + label;
+    }
+    addShaderSources(
+        gl, document.getElementById('console'), label, shader, shaderSource, opt_url);
+  }
+
+  // Check the compile status
+  if (!opt_skipCompileStatus) {
+    var compiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
+    if (!compiled) {
+      // Something went wrong during compilation; get the error
+      lastError = gl.getShaderInfoLog(shader);
+      errFn("*** Error compiling " + glEnumToString(gl, shaderType) + " '" + shader + "':" + lastError);
+      gl.deleteShader(shader);
+      return null;
+    }
+  }
+
+  return shader;
+}
+
+/**
+ * Loads a shader from a URL.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {file} file The URL of the shader source.
+ * @param {number} type The type of shader.
+ * @param {function(string): void} opt_errorCallback callback for errors.
+ * @param {boolean} opt_logShaders Whether to log shader source.
+ * @param {boolean} Skip compilation status check. Default = false.
+ * @return {!WebGLShader} The created shader.
+ */
+var loadShaderFromFile = function(
+    gl, file, type, opt_errorCallback, opt_logShaders, opt_skipCompileStatus) {
+  var shaderSource = readFile(file);
+  return loadShader(gl, shaderSource, type, opt_errorCallback,
+      opt_logShaders, undefined, file, opt_skipCompileStatus);
+};
+
+var loadShaderFromFileAsync = function(
+    gl, file, type, opt_errorCallback, opt_logShaders, opt_skipCompileStatus, callback) {
+  loadTextFileAsync(file, function(gl, type, opt_errorCallback, opt_logShaders, file, opt_skipCompileStatus){
+      return function(success, shaderSource) {
+        if (success) {
+          var shader = loadShader(gl, shaderSource, type, opt_errorCallback,
+              opt_logShaders, undefined, file, opt_skipCompileStatus);
+          callback(true, shader);
+        } else {
+          callback(false, null);
+        }
+      }
+  }(gl, type, opt_errorCallback, opt_logShaders, file, opt_skipCompileStatus));
+};
+
+/**
+ * Gets the content of script.
+ * @param {string} scriptId The id of the script tag.
+ * @return {string} The content of the script.
+ */
+var getScript = function(scriptId) {
+  var shaderScript = document.getElementById(scriptId);
+  if (!shaderScript) {
+    throw("*** Error: unknown script element " + scriptId);
+  }
+  return shaderScript.text;
+};
+
+/**
+ * Loads a shader from a script tag.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {string} scriptId The id of the script tag.
+ * @param {number} opt_shaderType The type of shader. If not passed in it will
+ *     be derived from the type of the script tag.
+ * @param {function(string): void} opt_errorCallback callback for errors.
+ * @param {boolean} opt_logShaders Whether to log shader source.
+ * @param {boolean} Skip compilation status check. Default = false.
+ * @return {!WebGLShader} The created shader.
+ */
+var loadShaderFromScript = function(
+    gl, scriptId, opt_shaderType, opt_errorCallback, opt_logShaders, opt_skipCompileStatus) {
+  var shaderSource = "";
+  var shaderScript = document.getElementById(scriptId);
+  if (!shaderScript) {
+    throw("*** Error: unknown script element " + scriptId);
+  }
+  shaderSource = shaderScript.text;
+
+  if (!opt_shaderType) {
+    if (shaderScript.type == "x-shader/x-vertex") {
+      opt_shaderType = gl.VERTEX_SHADER;
+    } else if (shaderScript.type == "x-shader/x-fragment") {
+      opt_shaderType = gl.FRAGMENT_SHADER;
+    } else {
+      throw("*** Error: unknown shader type");
+      return null;
+    }
+  }
+
+  return loadShader(gl, shaderSource, opt_shaderType, opt_errorCallback,
+      opt_logShaders, undefined, undefined, opt_skipCompileStatus);
+};
+
+var loadStandardProgram = function(gl) {
+  var program = gl.createProgram();
+  gl.attachShader(program, loadStandardVertexShader(gl));
+  gl.attachShader(program, loadStandardFragmentShader(gl));
+  gl.bindAttribLocation(program, 0, "a_vertex");
+  gl.bindAttribLocation(program, 1, "a_normal");
+  linkProgram(gl, program);
+  return program;
+};
+
+var loadStandardProgramAsync = function(gl, callback) {
+  loadStandardVertexShaderAsync(gl, function(gl) {
+    return function(success, vs) {
+      if (success) {
+        loadStandardFragmentShaderAsync(gl, function(vs) {
+          return function(success, fs) {
+            if (success) {
+              var program = gl.createProgram();
+              gl.attachShader(program, vs);
+              gl.attachShader(program, fs);
+              gl.bindAttribLocation(program, 0, "a_vertex");
+              gl.bindAttribLocation(program, 1, "a_normal");
+              linkProgram(gl, program);
+              callback(true, program);
+            } else {
+              callback(false, null);
+            }
+          };
+        }(vs));
+      } else {
+        callback(false, null);
+      }
+    };
+  }(gl));
+};
+
+/**
+ * Loads shaders from files, creates a program, attaches the shaders and links.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {string} vertexShaderPath The URL of the vertex shader.
+ * @param {string} fragmentShaderPath The URL of the fragment shader.
+ * @param {function(string): void} opt_errorCallback callback for errors.
+ * @return {!WebGLProgram} The created program.
+ */
+var loadProgramFromFile = function(
+    gl, vertexShaderPath, fragmentShaderPath, opt_errorCallback) {
+  var program = gl.createProgram();
+  var vs = loadShaderFromFile(
+      gl, vertexShaderPath, gl.VERTEX_SHADER, opt_errorCallback);
+  var fs = loadShaderFromFile(
+      gl, fragmentShaderPath, gl.FRAGMENT_SHADER, opt_errorCallback);
+  if (vs && fs) {
+    gl.attachShader(program, vs);
+    gl.attachShader(program, fs);
+    linkProgram(gl, program, opt_errorCallback);
+  }
+  if (vs) {
+    gl.deleteShader(vs);
+  }
+  if (fs) {
+    gl.deleteShader(fs);
+  }
+  return program;
+};
+
+/**
+ * Loads shaders from script tags, creates a program, attaches the shaders and
+ * links.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {string} vertexScriptId The id of the script tag that contains the
+ *        vertex shader.
+ * @param {string} fragmentScriptId The id of the script tag that contains the
+ *        fragment shader.
+ * @param {function(string): void} opt_errorCallback callback for errors.
+ * @return {!WebGLProgram} The created program.
+ */
+var loadProgramFromScript = function loadProgramFromScript(
+    gl, vertexScriptId, fragmentScriptId, opt_errorCallback) {
+  var program = gl.createProgram();
+  gl.attachShader(
+      program,
+      loadShaderFromScript(
+          gl, vertexScriptId, gl.VERTEX_SHADER, opt_errorCallback));
+  gl.attachShader(
+      program,
+      loadShaderFromScript(
+          gl, fragmentScriptId,  gl.FRAGMENT_SHADER, opt_errorCallback));
+  linkProgram(gl, program, opt_errorCallback);
+  return program;
+};
+
+/**
+ * Loads shaders from source, creates a program, attaches the shaders and
+ * links.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {!WebGLShader} vertexShader The vertex shader.
+ * @param {!WebGLShader} fragmentShader The fragment shader.
+ * @param {function(string): void} opt_errorCallback callback for errors.
+ * @return {!WebGLProgram} The created program.
+ */
+var createProgram = function(gl, vertexShader, fragmentShader, opt_errorCallback) {
+  var program = gl.createProgram();
+  gl.attachShader(program, vertexShader);
+  gl.attachShader(program, fragmentShader);
+  linkProgram(gl, program, opt_errorCallback);
+  return program;
+};
+
+/**
+ * Loads shaders from source, creates a program, attaches the shaders and
+ * links.
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {string} vertexShader The vertex shader source.
+ * @param {string} fragmentShader The fragment shader source.
+ * @param {function(string): void} opt_errorCallback callback for errors.
+ * @param {boolean} opt_logShaders Whether to log shader source.
+ * @return {!WebGLProgram} The created program.
+ */
+var loadProgram = function(
+    gl, vertexShader, fragmentShader, opt_errorCallback, opt_logShaders) {
+  var program;
+  var vs = loadShader(
+      gl, vertexShader, gl.VERTEX_SHADER, opt_errorCallback, opt_logShaders);
+  var fs = loadShader(
+      gl, fragmentShader, gl.FRAGMENT_SHADER, opt_errorCallback, opt_logShaders);
+  if (vs && fs) {
+    program = createProgram(gl, vs, fs, opt_errorCallback)
+  }
+  if (vs) {
+    gl.deleteShader(vs);
+  }
+  if (fs) {
+    gl.deleteShader(fs);
+  }
+  return program;
+};
+
+/**
+ * Loads shaders from source, creates a program, attaches the shaders and
+ * links but expects error.
+ *
+ * GLSL 1.0.17 10.27 effectively says that compileShader can
+ * always succeed as long as linkProgram fails so we can't
+ * rely on compileShader failing. This function expects
+ * one of the shader to fail OR linking to fail.
+ *
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {string} vertexShaderScriptId The vertex shader.
+ * @param {string} fragmentShaderScriptId The fragment shader.
+ * @return {WebGLProgram} The created program.
+ */
+var loadProgramFromScriptExpectError = function(
+    gl, vertexShaderScriptId, fragmentShaderScriptId) {
+  var vertexShader = loadShaderFromScript(gl, vertexShaderScriptId);
+  if (!vertexShader) {
+    return null;
+  }
+  var fragmentShader = loadShaderFromScript(gl, fragmentShaderScriptId);
+  if (!fragmentShader) {
+    return null;
+  }
+  var linkSuccess = true;
+  var program = gl.createProgram();
+  gl.attachShader(program, vertexShader);
+  gl.attachShader(program, fragmentShader);
+  linkSuccess = true;
+  linkProgram(gl, program, function() {
+      linkSuccess = false;
+    });
+  return linkSuccess ? program : null;
+};
+
+
+var getActiveMap = function(gl, program, typeInfo) {
+  var numVariables = gl.getProgramParameter(program, gl[typeInfo.param]);
+  var variables = {};
+  for (var ii = 0; ii < numVariables; ++ii) {
+    var info = gl[typeInfo.activeFn](program, ii);
+    variables[info.name] = {
+      name: info.name,
+      size: info.size,
+      type: info.type,
+      location: gl[typeInfo.locFn](program, info.name)
+    };
+  }
+  return variables;
+};
+
+/**
+ * Returns a map of attrib names to info about those
+ * attribs.
+ *
+ * eg:
+ *    { "attrib1Name":
+ *      {
+ *        name: "attrib1Name",
+ *        size: 1,
+ *        type: gl.FLOAT_MAT2,
+ *        location: 0
+ *      },
+ *      "attrib2Name[0]":
+ *      {
+ *         name: "attrib2Name[0]",
+ *         size: 4,
+ *         type: gl.FLOAT,
+ *         location: 1
+ *      },
+ *    }
+ *
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {WebGLProgram} The program to query for attribs.
+ * @return the map.
+ */
+var getAttribMap = function(gl, program) {
+  return getActiveMap(gl, program, {
+      param: "ACTIVE_ATTRIBUTES",
+      activeFn: "getActiveAttrib",
+      locFn: "getAttribLocation"
+  });
+};
+
+/**
+ * Returns a map of uniform names to info about those uniforms.
+ *
+ * eg:
+ *    { "uniform1Name":
+ *      {
+ *        name: "uniform1Name",
+ *        size: 1,
+ *        type: gl.FLOAT_MAT2,
+ *        location: WebGLUniformLocation
+ *      },
+ *      "uniform2Name[0]":
+ *      {
+ *         name: "uniform2Name[0]",
+ *         size: 4,
+ *         type: gl.FLOAT,
+ *         location: WebGLUniformLocation
+ *      },
+ *    }
+ *
+ * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {WebGLProgram} The program to query for uniforms.
+ * @return the map.
+ */
+var getUniformMap = function(gl, program) {
+  return getActiveMap(gl, program, {
+      param: "ACTIVE_UNIFORMS",
+      activeFn: "getActiveUniform",
+      locFn: "getUniformLocation"
+  });
+};
+
+var basePath;
+var getResourcePath = function() {
+  if (!basePath) {
+    var expectedBase = "js/webgl-test-utils.js";
+    var scripts = document.getElementsByTagName('script');
+    for (var script, i = 0; script = scripts[i]; i++) {
+      var src = script.src;
+      var l = src.length;
+      if (src.substr(l - expectedBase.length) == expectedBase) {
+        basePath = src.substr(0, l - expectedBase.length);
+      }
+    }
+  }
+  return basePath + "resources/";
+};
+
+var loadStandardVertexShader = function(gl) {
+  return loadShaderFromFile(
+      gl, getResourcePath() + "vertexShader.vert", gl.VERTEX_SHADER);
+};
+var loadStandardVertexShaderAsync = function(gl, callback) {
+  loadShaderFromFileAsync(gl, getResourcePath() + "vertexShader.vert", gl.VERTEX_SHADER, undefined, undefined, undefined, callback);
+};
+
+var loadStandardFragmentShader = function(gl) {
+  return loadShaderFromFile(
+      gl, getResourcePath() + "fragmentShader.frag", gl.FRAGMENT_SHADER);
+};
+var loadStandardFragmentShaderAsync = function(gl, callback) {
+  loadShaderFromFileAsync(gl, getResourcePath() + "fragmentShader.frag", gl.FRAGMENT_SHADER, undefined, undefined, undefined, callback);
+};
+
+var loadUniformBlockProgram = function(gl) {
+  var program = gl.createProgram();
+  gl.attachShader(program, loadUniformBlockVertexShader(gl));
+  gl.attachShader(program, loadUniformBlockFragmentShader(gl));
+  gl.bindAttribLocation(program, 0, "a_vertex");
+  gl.bindAttribLocation(program, 1, "a_normal");
+  linkProgram(gl, program);
+  return program;
+};
+
+var loadUniformBlockVertexShader = function(gl) {
+  return loadShaderFromFile(
+      gl, getResourcePath() + "uniformBlockShader.vert", gl.VERTEX_SHADER);
+};
+
+var loadUniformBlockFragmentShader = function(gl) {
+  return loadShaderFromFile(
+      gl, getResourcePath() + "uniformBlockShader.frag", gl.FRAGMENT_SHADER);
+};
+
+/**
+ * Loads an image asynchronously.
+ * @param {string} url URL of image to load.
+ * @param {!function(!Element): void} callback Function to call
+ *     with loaded image.
+ */
+var loadImageAsync = function(url, callback) {
+  var img = document.createElement('img');
+  img.onload = function() {
+    callback(img);
+  };
+  img.src = url;
+};
+
+/**
+ * Loads an array of images.
+ * @param {!Array.<string>} urls URLs of images to load.
+ * @param {!function(!{string, img}): void} callback Callback
+ *     that gets passed map of urls to img tags.
+ */
+var loadImagesAsync = function(urls, callback) {
+  var count = 1;
+  var images = { };
+  function countDown() {
+    --count;
+    if (count == 0) {
+      log("loadImagesAsync: all images loaded");
+      callback(images);
+    }
+  }
+  function imageLoaded(url) {
+    return function(img) {
+      images[url] = img;
+      log("loadImagesAsync: loaded " + url);
+      countDown();
+    }
+  }
+  for (var ii = 0; ii < urls.length; ++ii) {
+    ++count;
+    loadImageAsync(urls[ii], imageLoaded(urls[ii]));
+  }
+  countDown();
+};
+
+/**
+ * Returns a map of key=value values from url.
+ * @return {!Object.<string, number>} map of keys to values.
+ */
+var getUrlArguments = function() {
+  var args = {};
+  try {
+    var s = window.location.href;
+    var q = s.indexOf("?");
+    var e = s.indexOf("#");
+    if (e < 0) {
+      e = s.length;
+    }
+    var query = s.substring(q + 1, e);
+    var pairs = query.split("&");
+    for (var ii = 0; ii < pairs.length; ++ii) {
+      var keyValue = pairs[ii].split("=");
+      var key = keyValue[0];
+      var value = decodeURIComponent(keyValue[1]);
+      args[key] = value;
+    }
+  } catch (e) {
+    throw "could not parse url";
+  }
+  return args;
+};
+
+/**
+ * Makes an image from a src.
+ * @param {string} src Image source URL.
+ * @param {function()} onload Callback to call when the image has finised loading.
+ * @param {function()} onerror Callback to call when an error occurs.
+ * @return {!Image} The created image.
+ */
+var makeImage = function(src, onload, onerror) {
+  var img = document.createElement('img');
+  if (onload) {
+    img.onload = onload;
+  }
+  if (onerror) {
+    img.onerror = onerror;
+  } else {
+    img.onerror = function() {
+      log("WARNING: creating image failed; src: " + this.src);
+    };
+  }
+  if (src) {
+    img.src = src;
+  }
+  return img;
+}
+
+/**
+ * Makes an image element from a canvas.
+ * @param {!HTMLCanvas} canvas Canvas to make image from.
+ * @param {function()} onload Callback to call when the image has finised loading.
+ * @param {string} imageFormat Image format to be passed to toDataUrl().
+ * @return {!Image} The created image.
+ */
+var makeImageFromCanvas = function(canvas, onload, imageFormat) {
+  return makeImage(canvas.toDataURL(imageFormat), onload);
+};
+
+/**
+ * Makes a video element from a src.
+ * @param {string} src Video source URL.
+ * @param {function()} onerror Callback to call when an error occurs.
+ * @return {!Video} The created video.
+ */
+var makeVideo = function(src, onerror) {
+  var vid = document.createElement('video');
+  if (onerror) {
+    vid.onerror = onerror;
+  } else {
+    vid.onerror = function() {
+      log("WARNING: creating video failed; src: " + this.src);
+    };
+  }
+  if (src) {
+    vid.src = src;
+  }
+  return vid;
+}
+
+/**
+ * Inserts an image with a caption into 'element'.
+ * @param {!HTMLElement} element Element to append image to.
+ * @param {string} caption caption to associate with image.
+ * @param {!Image} img image to insert.
+ */
+var insertImage = function(element, caption, img) {
+  var div = document.createElement("div");
+  div.appendChild(img);
+  var label = document.createElement("div");
+  label.appendChild(document.createTextNode(caption));
+  div.appendChild(label);
+   element.appendChild(div);
+};
+
+/**
+ * Inserts a 'label' that when clicked expands to the pre formatted text
+ * supplied by 'source'.
+ * @param {!HTMLElement} element element to append label to.
+ * @param {string} label label for anchor.
+ * @param {string} source preformatted text to expand to.
+ * @param {string} opt_url URL of source. If provided a link to the source file
+ *     will also be added.
+ */
+var addShaderSource = function(element, label, source, opt_url) {
+  var div = document.createElement("div");
+  var s = document.createElement("pre");
+  s.className = "shader-source";
+  s.style.display = "none";
+  var ol = document.createElement("ol");
+  //s.appendChild(document.createTextNode(source));
+  var lines = source.split("\n");
+  for (var ii = 0; ii < lines.length; ++ii) {
+    var line = lines[ii];
+    var li = document.createElement("li");
+    li.appendChild(document.createTextNode(line));
+    ol.appendChild(li);
+  }
+  s.appendChild(ol);
+  var l = document.createElement("a");
+  l.href = "show-shader-source";
+  l.appendChild(document.createTextNode(label));
+  l.addEventListener('click', function(event) {
+      if (event.preventDefault) {
+        event.preventDefault();
+      }
+      s.style.display = (s.style.display == 'none') ? 'block' : 'none';
+      return false;
+    }, false);
+  div.appendChild(l);
+  if (opt_url) {
+    var u = document.createElement("a");
+    u.href = opt_url;
+    div.appendChild(document.createTextNode(" "));
+    u.appendChild(document.createTextNode("(" + opt_url + ")"));
+    div.appendChild(u);
+  }
+  div.appendChild(s);
+  element.appendChild(div);
+};
+
+/**
+ * Inserts labels that when clicked expand to show the original source of the
+ * shader and also translated source of the shader, if that is available.
+ * @param {WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {!HTMLElement} element element to append label to.
+ * @param {string} label label for anchor.
+ * @param {WebGLShader} shader Shader to show the sources for.
+ * @param {string} shaderSource Original shader source.
+ * @param {string} opt_url URL of source. If provided a link to the source file
+ *     will also be added.
+ */
+var addShaderSources = function(
+    gl, element, label, shader, shaderSource, opt_url) {
+  addShaderSource(element, label, shaderSource, opt_url);
+
+  var debugShaders = gl.getExtension('WEBGL_debug_shaders');
+  if (debugShaders && shader) {
+    var translatedSource = debugShaders.getTranslatedShaderSource(shader);
+    if (translatedSource != '') {
+      addShaderSource(element, label + ' translated for driver', translatedSource);
+    }
+  }
+};
+
+/**
+ * Sends shader information to the server to be dumped into text files
+ * when tests are run from within the test-runner harness.
+ * @param {WebGLRenderingContext} gl The WebGLRenderingContext to use.
+ * @param {string} url URL of current.
+ * @param {string} passMsg Test description.
+ * @param {object} vInfo Object containing vertex shader information.
+ * @param {object} fInfo Object containing fragment shader information.
+ */
+var dumpShadersInfo = function(gl, url, passMsg, vInfo, fInfo) {
+  var shaderInfo = {};
+  shaderInfo.url = url;
+  shaderInfo.testDescription = passMsg;
+  shaderInfo.vLabel = vInfo.label;
+  shaderInfo.vShouldCompile = vInfo.shaderSuccess;
+  shaderInfo.vSource = vInfo.source;
+  shaderInfo.fLabel = fInfo.label;
+  shaderInfo.fShouldCompile = fInfo.shaderSuccess;
+  shaderInfo.fSource = fInfo.source;
+  shaderInfo.vTranslatedSource = null;
+  shaderInfo.fTranslatedSource = null;
+  var debugShaders = gl.getExtension('WEBGL_debug_shaders');
+  if (debugShaders) {
+    if (vInfo.shader)
+      shaderInfo.vTranslatedSource = debugShaders.getTranslatedShaderSource(vInfo.shader);
+    if (fInfo.shader)
+      shaderInfo.fTranslatedSource = debugShaders.getTranslatedShaderSource(fInfo.shader);
+  }
+
+  var dumpShaderInfoRequest = new XMLHttpRequest();
+  dumpShaderInfoRequest.open('POST', "/dumpShaderInfo", true);
+  dumpShaderInfoRequest.setRequestHeader("Content-Type", "text/plain");
+  dumpShaderInfoRequest.send(JSON.stringify(shaderInfo));
+};
+
+// Add your prefix here.
+var browserPrefixes = [
+  "",
+  "MOZ_",
+  "OP_",
+  "WEBKIT_"
+];
+
+/**
+ * Given an extension name like WEBGL_compressed_texture_s3tc
+ * returns the name of the supported version extension, like
+ * WEBKIT_WEBGL_compressed_teture_s3tc
+ * @param {string} name Name of extension to look for.
+ * @return {string} name of extension found or undefined if not
+ *     found.
+ */
+var getSupportedExtensionWithKnownPrefixes = function(gl, name) {
+  var supported = gl.getSupportedExtensions();
+  for (var ii = 0; ii < browserPrefixes.length; ++ii) {
+    var prefixedName = browserPrefixes[ii] + name;
+    if (supported.indexOf(prefixedName) >= 0) {
+      return prefixedName;
+    }
+  }
+};
+
+/**
+ * Given an extension name like WEBGL_compressed_texture_s3tc
+ * returns the supported version extension, like
+ * WEBKIT_WEBGL_compressed_teture_s3tc
+ * @param {string} name Name of extension to look for.
+ * @return {WebGLExtension} The extension or undefined if not
+ *     found.
+ */
+var getExtensionWithKnownPrefixes = function(gl, name) {
+  for (var ii = 0; ii < browserPrefixes.length; ++ii) {
+    var prefixedName = browserPrefixes[ii] + name;
+    var ext = gl.getExtension(prefixedName);
+    if (ext) {
+      return ext;
+    }
+  }
+};
+
+/**
+ * Returns possible prefixed versions of an extension's name.
+ * @param {string} name Name of extension. May already include a prefix.
+ * @return {Array.<string>} Variations of the extension name with known
+ *     browser prefixes.
+ */
+var getExtensionPrefixedNames = function(name) {
+  var unprefix = function(name) {
+    for (var ii = 0; ii < browserPrefixes.length; ++ii) {
+      if (browserPrefixes[ii].length > 0 &&
+          name.substring(0, browserPrefixes[ii].length).toLowerCase() ===
+          browserPrefixes[ii].toLowerCase()) {
+        return name.substring(browserPrefixes[ii].length);
+      }
+    }
+    return name;
+  }
+
+  var unprefixed = unprefix(name);
+
+  var variations = [];
+  for (var ii = 0; ii < browserPrefixes.length; ++ii) {
+    variations.push(browserPrefixes[ii] + unprefixed);
+  }
+
+  return variations;
+};
+
+var replaceRE = /\$\((\w+)\)/g;
+
+/**
+ * Replaces strings with property values.
+ * Given a string like "hello $(first) $(last)" and an object
+ * like {first:"John", last:"Smith"} will return
+ * "hello John Smith".
+ * @param {string} str String to do replacements in.
+ * @param {...} 1 or more objects containing properties.
+ */
+var replaceParams = function(str) {
+  var args = arguments;
+  return str.replace(replaceRE, function(str, p1, offset, s) {
+    for (var ii = 1; ii < args.length; ++ii) {
+      if (args[ii][p1] !== undefined) {
+        return args[ii][p1];
+      }
+    }
+    throw "unknown string param '" + p1 + "'";
+  });
+};
+
+var upperCaseFirstLetter = function(str) {
+  return str.substring(0, 1).toUpperCase() + str.substring(1);
+};
+
+/**
+ * Gets a prefixed property. For example,
+ *
+ *     var fn = getPrefixedProperty(
+ *        window,
+ *        "requestAnimationFrame");
+ *
+ * Will return either:
+ *    "window.requestAnimationFrame",
+ *    "window.oRequestAnimationFrame",
+ *    "window.msRequestAnimationFrame",
+ *    "window.mozRequestAnimationFrame",
+ *    "window.webKitRequestAnimationFrame",
+ *    undefined
+ *
+ * the non-prefixed function is tried first.
+ */
+var propertyPrefixes = ["", "moz", "ms", "o", "webkit"];
+var getPrefixedProperty = function(obj, propertyName) {
+  for (var ii = 0; ii < propertyPrefixes.length; ++ii) {
+    var prefix = propertyPrefixes[ii];
+    var name = prefix + propertyName;
+    log(name);
+    var property = obj[name];
+    if (property) {
+      return property;
+    }
+    if (ii == 0) {
+      propertyName = upperCaseFirstLetter(propertyName);
+    }
+  }
+  return undefined;
+};
+
+var _requestAnimFrame;
+
+/**
+ * Provides requestAnimationFrame in a cross browser way.
+ */
+var requestAnimFrame = function(callback) {
+  if (!_requestAnimFrame) {
+    _requestAnimFrame = getPrefixedProperty(window, "requestAnimationFrame") ||
+      function(callback, element) {
+        return window.setTimeout(callback, 1000 / 70);
+      };
+  }
+  _requestAnimFrame.call(window, callback);
+};
+
+var _cancelAnimFrame;
+
+/**
+ * Provides cancelAnimationFrame in a cross browser way.
+ */
+var cancelAnimFrame = function(request) {
+  if (!_cancelAnimFrame) {
+    _cancelAnimFrame = getPrefixedProperty(window, "cancelAnimationFrame") ||
+      window.clearTimeout;
+  }
+  _cancelAnimFrame.call(window, request);
+};
+
+/**
+ * Provides requestFullScreen in a cross browser way.
+ */
+var requestFullScreen = function(element) {
+  var fn = getPrefixedProperty(element, "requestFullScreen");
+  if (fn) {
+    fn.call(element);
+  }
+};
+
+/**
+ * Provides cancelFullScreen in a cross browser way.
+ */
+var cancelFullScreen = function() {
+  var fn = getPrefixedProperty(document, "cancelFullScreen");
+  if (fn) {
+    fn.call(document);
+  }
+};
+
+var fullScreenStateName;
+(function() {
+  var fullScreenStateNames = [
+    "isFullScreen",
+    "fullScreen"
+  ];
+  for (var ii = 0; ii < fullScreenStateNames.length; ++ii) {
+    var propertyName = fullScreenStateNames[ii];
+    for (var jj = 0; jj < propertyPrefixes.length; ++jj) {
+      var prefix = propertyPrefixes[jj];
+      if (prefix.length) {
+        propertyName = upperCaseFirstLetter(propertyName);
+        fullScreenStateName = prefix + propertyName;
+        if (document[fullScreenStateName] !== undefined) {
+          return;
+        }
+      }
+    }
+    fullScreenStateName = undefined;
+  }
+}());
+
+/**
+ * @return {boolean} True if fullscreen mode is active.
+ */
+var getFullScreenState = function() {
+  log("fullscreenstatename:" + fullScreenStateName);
+  log(document[fullScreenStateName]);
+  return document[fullScreenStateName];
+};
+
+/**
+ * @param {!HTMLElement} element The element to go fullscreen.
+ * @param {!function(boolean)} callback A function that will be called
+ *        when entering/exiting fullscreen. It is passed true if
+ *        entering fullscreen, false if exiting.
+ */
+var onFullScreenChange = function(element, callback) {
+  propertyPrefixes.forEach(function(prefix) {
+    var eventName = prefix + "fullscreenchange";
+    log("addevent: " + eventName);
+    document.addEventListener(eventName, function(event) {
+      log("event: " + eventName);
+      callback(getFullScreenState());
+    });
+  });
+};
+
+/**
+ * @param {!string} buttonId The id of the button that will toggle fullscreen
+ *        mode.
+ * @param {!string} fullscreenId The id of the element to go fullscreen.
+ * @param {!function(boolean)} callback A function that will be called
+ *        when entering/exiting fullscreen. It is passed true if
+ *        entering fullscreen, false if exiting.
+ * @return {boolean} True if fullscreen mode is supported.
+ */
+var setupFullscreen = function(buttonId, fullscreenId, callback) {
+  if (!fullScreenStateName) {
+    return false;
+  }
+
+  var fullscreenElement = document.getElementById(fullscreenId);
+  onFullScreenChange(fullscreenElement, callback);
+
+  var toggleFullScreen = function(event) {
+    if (getFullScreenState()) {
+      cancelFullScreen(fullscreenElement);
+    } else {
+      requestFullScreen(fullscreenElement);
+    }
+    event.preventDefault();
+    return false;
+  };
+
+  var buttonElement = document.getElementById(buttonId);
+  buttonElement.addEventListener('click', toggleFullScreen);
+
+  return true;
+};
+
+/**
+ * Waits for the browser to composite the web page.
+ * @param {function()} callback A function to call after compositing has taken
+ *        place.
+ */
+var waitForComposite = function(callback) {
+  var frames = 5;
+  var countDown = function() {
+    if (frames == 0) {
+      // TODO(kbr): unify with js-test-pre.js and enable these with
+      // verbose logging.
+      // log("waitForComposite: callback");
+      callback();
+    } else {
+      // log("waitForComposite: countdown(" + frames + ")");
+      --frames;
+      requestAnimFrame.call(window, countDown);
+    }
+  };
+  countDown();
+};
+
+/**
+ * Runs an array of functions, yielding to the browser between each step.
+ * If you want to know when all the steps are finished add a last step.
+ * @param {!Array.<function(): void>} steps Array of functions.
+ */
+var runSteps = function(steps) {
+  if (!steps.length) {
+    return;
+  }
+
+  // copy steps so they can't be modifed.
+  var stepsToRun = steps.slice();
+  var currentStep = 0;
+  var runNextStep = function() {
+    stepsToRun[currentStep++]();
+    if (currentStep < stepsToRun.length) {
+      setTimeout(runNextStep, 1);
+    }
+  };
+  runNextStep();
+};
+
+/**
+ * Starts playing a video and waits for it to be consumable.
+ * @param {!HTMLVideoElement} video An HTML5 Video element.
+ * @param {!function(!HTMLVideoElement): void} callback Function to call when
+ *        video is ready.
+ */
+var startPlayingAndWaitForVideo = function(video, callback) {
+  var gotPlaying = false;
+  var gotTimeUpdate = false;
+
+  var maybeCallCallback = function() {
+    if (gotPlaying && gotTimeUpdate && callback) {
+      callback(video);
+      callback = undefined;
+      video.removeEventListener('playing', playingListener, true);
+      video.removeEventListener('timeupdate', timeupdateListener, true);
+    }
+  };
+
+  var playingListener = function() {
+    gotPlaying = true;
+    maybeCallCallback();
+  };
+
+  var timeupdateListener = function() {
+    // Checking to make sure the current time has advanced beyond
+    // the start time seems to be a reliable heuristic that the
+    // video element has data that can be consumed.
+    if (video.currentTime > 0.0) {
+      gotTimeUpdate = true;
+      maybeCallCallback();
+    }
+  };
+
+  video.addEventListener('playing', playingListener, true);
+  video.addEventListener('timeupdate', timeupdateListener, true);
+  video.loop = true;
+  video.play();
+};
+
+var getHost = function(url) {
+  url = url.replace("\\", "/");
+  var pos = url.indexOf("://");
+  if (pos >= 0) {
+    url = url.substr(pos + 3);
+  }
+  var parts = url.split('/');
+  return parts[0];
+}
+
+// This function returns the last 2 words of the domain of a URL
+// This is probably not the correct check but it will do for now.
+var getBaseDomain = function(host) {
+  var parts = host.split(":");
+  var hostname = parts[0];
+  var port = parts[1] || "80";
+  parts = hostname.split(".");
+  if(parts.length < 2)
+    return hostname + ":" + port;
+  var tld = parts[parts.length-1];
+  var domain = parts[parts.length-2];
+  return domain + "." + tld + ":" + port;
+}
+
+var runningOnLocalhost = function() {
+  return window.location.hostname.indexOf("localhost") != -1 ||
+      window.location.hostname.indexOf("127.0.0.1") != -1;
+}
+
+var getLocalCrossOrigin = function() {
+  var domain;
+  if (window.location.host.indexOf("localhost") != -1) {
+    domain = "127.0.0.1";
+  } else {
+    domain = "localhost";
+  }
+
+  var port = window.location.port || "80";
+  return window.location.protocol + "//" + domain + ":" + port
+}
+
+var getRelativePath = function(path) {
+  var relparts = window.location.pathname.split("/");
+  relparts.pop(); // Pop off filename
+  var pathparts = path.split("/");
+
+  var i;
+  for (i = 0; i < pathparts.length; ++i) {
+    switch (pathparts[i]) {
+      case "": break;
+      case ".": break;
+      case "..":
+        relparts.pop();
+        break;
+      default:
+        relparts.push(pathparts[i]);
+        break;
+    }
+  }
+
+  return relparts.join("/");
+}
+
+var setupImageForCrossOriginTest = function(img, imgUrl, localUrl, callback) {
+  window.addEventListener("load", function() {
+    if (typeof(img) == "string")
+      img = document.querySelector(img);
+    if (!img)
+      img = new Image();
+
+    img.addEventListener("load", callback, false);
+    img.addEventListener("error", callback, false);
+
+    if (runningOnLocalhost())
+      img.src = getLocalCrossOrigin() + getRelativePath(localUrl);
+    else
+      img.src = getUrlOptions().imgUrl || imgUrl;
+  }, false);
+}
+
+var API = {
+  addShaderSource: addShaderSource,
+  addShaderSources: addShaderSources,
+  cancelAnimFrame: cancelAnimFrame,
+  create3DContext: create3DContext,
+  GLErrorException: GLErrorException,
+  create3DContextWithWrapperThatThrowsOnGLError: create3DContextWithWrapperThatThrowsOnGLError,
+  checkAreaInAndOut: checkAreaInAndOut,
+  checkCanvas: checkCanvas,
+  checkCanvasRect: checkCanvasRect,
+  checkCanvasRectColor: checkCanvasRectColor,
+  checkCanvasRects: checkCanvasRects,
+  checkFloatBuffer: checkFloatBuffer,
+  checkTextureSize: checkTextureSize,
+  clipToRange: clipToRange,
+  createColoredTexture: createColoredTexture,
+  createProgram: createProgram,
+  clearAndDrawUnitQuad: clearAndDrawUnitQuad,
+  clearAndDrawIndexedQuad: clearAndDrawIndexedQuad,
+  drawUnitQuad: drawUnitQuad,
+  drawIndexedQuad: drawIndexedQuad,
+  drawUByteColorQuad: drawUByteColorQuad,
+  drawFloatColorQuad: drawFloatColorQuad,
+  dumpShadersInfo: dumpShadersInfo,
+  endsWith: endsWith,
+  failIfGLError: failIfGLError,
+  fillTexture: fillTexture,
+  getBytesPerComponent: getBytesPerComponent,
+  getDefault3DContextVersion: getDefault3DContextVersion,
+  getExtensionPrefixedNames: getExtensionPrefixedNames,
+  getExtensionWithKnownPrefixes: getExtensionWithKnownPrefixes,
+  getFileListAsync: getFileListAsync,
+  getLastError: getLastError,
+  getPrefixedProperty: getPrefixedProperty,
+  getScript: getScript,
+  getSupportedExtensionWithKnownPrefixes: getSupportedExtensionWithKnownPrefixes,
+  getTypedArrayElementsPerPixel: getTypedArrayElementsPerPixel,
+  getUrlArguments: getUrlArguments,
+  getUrlOptions: getUrlOptions,
+  getAttribMap: getAttribMap,
+  getUniformMap: getUniformMap,
+  glEnumToString: glEnumToString,
+  glErrorShouldBe: glErrorShouldBe,
+  glTypeToTypedArrayType: glTypeToTypedArrayType,
+  hasAttributeCaseInsensitive: hasAttributeCaseInsensitive,
+  insertImage: insertImage,
+  loadImageAsync: loadImageAsync,
+  loadImagesAsync: loadImagesAsync,
+  loadProgram: loadProgram,
+  loadProgramFromFile: loadProgramFromFile,
+  loadProgramFromScript: loadProgramFromScript,
+  loadProgramFromScriptExpectError: loadProgramFromScriptExpectError,
+  loadShader: loadShader,
+  loadShaderFromFile: loadShaderFromFile,
+  loadShaderFromScript: loadShaderFromScript,
+  loadStandardProgram: loadStandardProgram,
+  loadStandardProgramAsync: loadStandardProgramAsync,
+  loadStandardVertexShader: loadStandardVertexShader,
+  loadStandardVertexShaderAsync: loadStandardVertexShaderAsync,
+  loadStandardFragmentShader: loadStandardFragmentShader,
+  loadStandardFragmentShaderAsync: loadStandardFragmentShaderAsync,
+  loadUniformBlockProgram: loadUniformBlockProgram,
+  loadUniformBlockVertexShader: loadUniformBlockVertexShader,
+  loadUniformBlockFragmentShader: loadUniformBlockFragmentShader,
+  loadTextFileAsync: loadTextFileAsync,
+  loadTexture: loadTexture,
+  log: log,
+  loggingOff: loggingOff,
+  makeCheckRect: makeCheckRect,
+  makeImage: makeImage,
+  makeImageFromCanvas: makeImageFromCanvas,
+  makeVideo: makeVideo,
+  error: error,
+  shallowCopyObject: shallowCopyObject,
+  setDefault3DContextVersion: setDefault3DContextVersion,
+  setupColorQuad: setupColorQuad,
+  setupProgram: setupProgram,
+  setupTransformFeedbackProgram: setupTransformFeedbackProgram,
+  setupQuad: setupQuad,
+  setupIndexedQuad: setupIndexedQuad,
+  setupIndexedQuadWithOptions: setupIndexedQuadWithOptions,
+  setupSimpleColorProgram: setupSimpleColorProgram,
+  setupSimpleTextureProgram: setupSimpleTextureProgram,
+  setupSimpleCubeMapTextureProgram: setupSimpleCubeMapTextureProgram,
+  setupSimpleVertexColorProgram: setupSimpleVertexColorProgram,
+  setupNoTexCoordTextureProgram: setupNoTexCoordTextureProgram,
+  setupTexturedQuad: setupTexturedQuad,
+  setupTexturedQuadWithTexCoords: setupTexturedQuadWithTexCoords,
+  setupTexturedQuadWithCubeMap: setupTexturedQuadWithCubeMap,
+  setupUnitQuad: setupUnitQuad,
+  setupUnitQuadWithTexCoords: setupUnitQuadWithTexCoords,
+  setFloatDrawColor: setFloatDrawColor,
+  setUByteDrawColor: setUByteDrawColor,
+  startPlayingAndWaitForVideo: startPlayingAndWaitForVideo,
+  startsWith: startsWith,
+  shouldGenerateGLError: shouldGenerateGLError,
+  readFile: readFile,
+  readFileList: readFileList,
+  replaceParams: replaceParams,
+  requestAnimFrame: requestAnimFrame,
+  runSteps: runSteps,
+  waitForComposite: waitForComposite,
+
+  // fullscreen api
+  setupFullscreen: setupFullscreen,
+
+  getHost: getHost,
+  getBaseDomain: getBaseDomain,
+  runningOnLocalhost: runningOnLocalhost,
+  getLocalCrossOrigin: getLocalCrossOrigin,
+  getRelativePath: getRelativePath,
+  setupImageForCrossOriginTest: setupImageForCrossOriginTest,
+
+  none: false
+};
+
+Object.defineProperties(API, {
+  noTexCoordTextureVertexShader: { value: noTexCoordTextureVertexShader, writable: false },
+  simpleTextureVertexShader: { value: simpleTextureVertexShader, writable: false },
+  simpleColorFragmentShader: { value: simpleColorFragmentShader, writable: false },
+  simpleVertexShader: { value: simpleVertexShader, writable: false },
+  simpleTextureFragmentShader: { value: simpleTextureFragmentShader, writable: false },
+  simpleCubeMapTextureFragmentShader: { value: simpleCubeMapTextureFragmentShader, writable: false },
+  simpleTextureVertexShader: { value: simpleTextureVertexShader, writable: false },
+  simpleVertexColorFragmentShader: { value: simpleVertexColorFragmentShader, writable: false },
+  simpleVertexColorVertexShader: { value: simpleVertexColorVertexShader, writable: false }
+});
+
+return API;
+
+}());
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-image-bitmap-from-blob-expected.txt b/third_party/WebKit/LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-image-bitmap-from-blob-expected.txt
new file mode 100644
index 0000000..22c2f2f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-image-bitmap-from-blob-expected.txt
@@ -0,0 +1,5 @@
+PASS successfullyParsed is true
+
+TEST COMPLETE
+ 
+Test PASSED
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-image-bitmap-from-blob.html b/third_party/WebKit/LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-image-bitmap-from-blob.html
new file mode 100644
index 0000000..a3b109c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-image-bitmap-from-blob.html
@@ -0,0 +1,88 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="./resources/webgl-test-utils-full.js"></script>
+<script src="./resources/tex-image-and-sub-image-utils.js"></script>
+<script src="./resources/tex-image-and-sub-image-image-bitmap-utils.js"></script>
+<script src="../../../resources/js-test.js"></script>
+<script>
+
+window.jsTestIsAsync = true;
+
+var wtu = WebGLTestUtils;
+var tiu = TexImageUtils;
+var gl = null;
+var internalFormat = "RGBA";
+var pixelFormat = "RGBA";
+var pixelType = "UNSIGNED_BYTE";
+var redColor = [255, 0, 0];
+var greenColor = [0, 255, 0];
+var blackColor = [0, 0, 0];
+var halfRed = [128, 0, 0];
+var halfGreen = [0, 128, 0];
+
+var blob = null;
+
+function promiseRejected()
+{
+    document.getElementById("results").innerHTML = "Promise <span style='color:red'>REJECTED</span>";
+}
+
+function pass()
+{
+    document.getElementById("results").innerHTML = "Test <span style='color:green'>PASSED</span>";
+}
+
+function generateTest()
+{
+    var bitmaps = [];
+
+    var canvas = document.getElementById("example");
+    gl = canvas.getContext("webgl");
+
+    gl.clearColor(0,0,0,1);
+    gl.clearDepth(1);
+
+    var p1 = createImageBitmap(blob).then(function(imageBitmap) { bitmaps.defaultOption = imageBitmap });
+    var p2 = createImageBitmap(blob, {imageOrientation: "none", premultiplyAlpha: "premultiply"}).then(function(imageBitmap) { bitmaps.noFlipYPremul = imageBitmap });
+    var p3 = createImageBitmap(blob, {imageOrientation: "none", premultiplyAlpha: "default"}).then(function(imageBitmap) { bitmaps.noFlipYDefault = imageBitmap });
+    var p4 = createImageBitmap(blob, {imageOrientation: "none", premultiplyAlpha: "none"}).then(function(imageBitmap) { bitmaps.noFlipYUnpremul = imageBitmap });
+    var p5 = createImageBitmap(blob, {imageOrientation: "flipY", premultiplyAlpha: "premultiply"}).then(function(imageBitmap) { bitmaps.flipYPremul = imageBitmap });
+    var p6 = createImageBitmap(blob, {imageOrientation: "flipY", premultiplyAlpha: "default"}).then(function(imageBitmap) { bitmaps.flipYDefault = imageBitmap });
+    var p7 = createImageBitmap(blob, {imageOrientation: "flipY", premultiplyAlpha: "none"}).then(function(imageBitmap) { bitmaps.flipYUnpremul = imageBitmap });
+    Promise.all([p1, p2, p3, p4, p5, p6, p7]).then(function() {
+        var alphaVal = 0.5;
+        var testPassed = runTest(bitmaps, alphaVal);
+        if (testPassed)
+            pass();
+        finishJSTest();
+    }, function() {
+        promiseRejected();
+        finishJSTest();
+    });
+}
+
+function init()
+{
+    if (window.testRunner) {
+        testRunner.overridePreference("WebKitWebGLEnabled", "1");
+        testRunner.dumpAsText();
+    }
+    var xhr = new XMLHttpRequest();
+    xhr.open("GET", 'resources/red-green-semi-transparent.png');
+    xhr.responseType = 'blob';
+    xhr.send();
+    xhr.onload = function() {
+        blob = xhr.response;
+        generateTest();
+    }
+}
+
+</script>
+</head>
+<body onload="init()">
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="results">Test <span style="color:red">FAILED</span></div>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-image-bitmap-from-canvas-expected.txt b/third_party/WebKit/LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-image-bitmap-from-canvas-expected.txt
new file mode 100644
index 0000000..22c2f2f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-image-bitmap-from-canvas-expected.txt
@@ -0,0 +1,5 @@
+PASS successfullyParsed is true
+
+TEST COMPLETE
+ 
+Test PASSED
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-image-bitmap-from-canvas.html b/third_party/WebKit/LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-image-bitmap-from-canvas.html
new file mode 100644
index 0000000..74dd83c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-image-bitmap-from-canvas.html
@@ -0,0 +1,99 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="./resources/webgl-test-utils-full.js"></script>
+<script src="./resources/tex-image-and-sub-image-utils.js"></script>
+<script src="./resources/tex-image-and-sub-image-image-bitmap-utils.js"></script>
+<script src="../../../resources/js-test.js"></script>
+<script>
+
+window.jsTestIsAsync = true;
+
+var wtu = WebGLTestUtils;
+var tiu = TexImageUtils;
+var gl = null;
+var internalFormat = "RGBA";
+var pixelFormat = "RGBA";
+var pixelType = "UNSIGNED_BYTE";
+var redColor = [255, 0, 0];
+var greenColor = [0, 255, 0];
+var blackColor = [0, 0, 0];
+var halfRed = [128, 0, 0];
+var halfGreen = [0, 128, 0];
+
+function promiseRejected()
+{
+    document.getElementById("results").innerHTML = "Promise <span style='color:red'>REJECTED</span>";
+}
+
+function pass()
+{
+    document.getElementById("results").innerHTML = "Test <span style='color:green'>PASSED</span>";
+}
+
+function setCanvasToRedGreen(ctx) {
+    ctx.canvas.width = 2;
+    ctx.canvas.height = 2;
+    var width = ctx.canvas.width;
+    var halfWidth = Math.floor(width / 2);
+    var height = ctx.canvas.height;
+    var halfHeight = Math.floor(height / 2);
+    ctx.fillStyle = "rgba(255, 0, 0, 1)";
+    ctx.fillRect(0, 0, halfWidth, halfHeight);
+    ctx.fillStyle = "rgba(255, 0, 0, 0.5)";
+    ctx.fillRect(halfWidth, 0, halfWidth, halfHeight);
+    ctx.fillStyle = "rgba(0, 255, 0, 1)";
+    ctx.fillRect(0, halfHeight, halfWidth, halfHeight);
+    ctx.fillStyle = "rgba(0, 255, 0, 0.5)";
+    ctx.fillRect(halfWidth, halfHeight, halfWidth, halfHeight);
+}
+
+function generateTest()
+{
+    var bitmaps = [];
+
+    var canvas = document.getElementById("example");
+    gl = canvas.getContext("webgl");
+
+    gl.clearColor(0,0,0,1);
+    gl.clearDepth(1);
+
+    var testCanvas = document.createElement('canvas');
+    var ctx = testCanvas.getContext("2d");
+    setCanvasToRedGreen(ctx);
+
+    var p1 = createImageBitmap(testCanvas).then(function(imageBitmap) { bitmaps.defaultOption = imageBitmap });
+    var p2 = createImageBitmap(testCanvas, {imageOrientation: "none", premultiplyAlpha: "premultiply"}).then(function(imageBitmap) { bitmaps.noFlipYPremul = imageBitmap });
+    var p3 = createImageBitmap(testCanvas, {imageOrientation: "none", premultiplyAlpha: "default"}).then(function(imageBitmap) { bitmaps.noFlipYDefault = imageBitmap });
+    var p4 = createImageBitmap(testCanvas, {imageOrientation: "none", premultiplyAlpha: "none"}).then(function(imageBitmap) { bitmaps.noFlipYUnpremul = imageBitmap });
+    var p5 = createImageBitmap(testCanvas, {imageOrientation: "flipY", premultiplyAlpha: "premultiply"}).then(function(imageBitmap) { bitmaps.flipYPremul = imageBitmap });
+    var p6 = createImageBitmap(testCanvas, {imageOrientation: "flipY", premultiplyAlpha: "default"}).then(function(imageBitmap) { bitmaps.flipYDefault = imageBitmap });
+    var p7 = createImageBitmap(testCanvas, {imageOrientation: "flipY", premultiplyAlpha: "none"}).then(function(imageBitmap) { bitmaps.flipYUnpremul = imageBitmap });
+    Promise.all([p1, p2, p3, p4, p5, p6, p7]).then(function() {
+        var alphaVal = 0.5;
+        var testPassed = runTest(bitmaps, alphaVal);
+        if (testPassed)
+            pass();
+        finishJSTest();
+    }, function() {
+        promiseRejected();
+        finishJSTest();
+    });
+}
+
+function init()
+{
+    if (window.testRunner) {
+        testRunner.overridePreference("WebKitWebGLEnabled", "1");
+        testRunner.dumpAsText();
+    }
+    generateTest();
+}
+</script>
+</head>
+<body onload="init()">
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="results">Test <span style="color:red">FAILED</span></div>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-image-bitmap-from-image-bitmap-expected.txt b/third_party/WebKit/LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-image-bitmap-from-image-bitmap-expected.txt
new file mode 100644
index 0000000..22c2f2f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-image-bitmap-from-image-bitmap-expected.txt
@@ -0,0 +1,5 @@
+PASS successfullyParsed is true
+
+TEST COMPLETE
+ 
+Test PASSED
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-image-bitmap-from-image-bitmap.html b/third_party/WebKit/LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-image-bitmap-from-image-bitmap.html
new file mode 100644
index 0000000..d3116d0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-image-bitmap-from-image-bitmap.html
@@ -0,0 +1,93 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="./resources/webgl-test-utils-full.js"></script>
+<script src="./resources/tex-image-and-sub-image-utils.js"></script>
+<script src="./resources/tex-image-and-sub-image-image-bitmap-utils.js"></script>
+<script src="../../../resources/js-test.js"></script>
+<script>
+
+window.jsTestIsAsync = true;
+
+var wtu = WebGLTestUtils;
+var tiu = TexImageUtils;
+var gl = null;
+var internalFormat = "RGBA";
+var pixelFormat = "RGBA";
+var pixelType = "UNSIGNED_BYTE";
+var redColor = [255, 0, 0];
+var greenColor = [0, 255, 0];
+var blackColor = [0, 0, 0];
+var halfRed = [128, 0, 0];
+var halfGreen = [0, 128, 0];
+
+function promiseRejected()
+{
+    document.getElementById("results").innerHTML = "Promise <span style='color:red'>REJECTED</span>";
+}
+
+function pass()
+{
+    document.getElementById("results").innerHTML = "Test <span style='color:green'>PASSED</span>";
+}
+
+function generateTest()
+{
+    var bitmaps = [];
+
+    var canvas = document.getElementById("example");
+    gl = canvas.getContext("webgl");
+
+    gl.clearColor(0,0,0,1);
+    gl.clearDepth(1);
+    gl.disable(gl.BLEND);
+
+    var imageData = new ImageData(new Uint8ClampedArray(
+                                  [255, 0, 0, 255,
+                                  255, 0, 0, 0,
+                                  0, 255, 0, 255,
+                                  0, 255, 0, 0]),
+                                  2, 2);
+
+    var bitmap; // bitmap will be in unpremultiplied format
+    createImageBitmap(imageData, {imageOrientation: "none", premultiplyAlpha: "none"}).then(function(image) {
+        bitmap = image;
+        var p1 = createImageBitmap(bitmap).then(function(imageBitmap) { bitmaps.defaultOption = imageBitmap });
+        var p2 = createImageBitmap(bitmap, {imageOrientation: "none", premultiplyAlpha: "premultiply"}).then(function(imageBitmap) { bitmaps.noFlipYPremul = imageBitmap });
+        var p3 = createImageBitmap(bitmap, {imageOrientation: "none", premultiplyAlpha: "default"}).then(function(imageBitmap) { bitmaps.noFlipYDefault = imageBitmap });
+        var p4 = createImageBitmap(bitmap, {imageOrientation: "none", premultiplyAlpha: "none"}).then(function(imageBitmap) { bitmaps.noFlipYUnpremul = imageBitmap });
+        var p5 = createImageBitmap(bitmap, {imageOrientation: "flipY", premultiplyAlpha: "premultiply"}).then(function(imageBitmap) { bitmaps.flipYPremul = imageBitmap });
+        var p6 = createImageBitmap(bitmap, {imageOrientation: "flipY", premultiplyAlpha: "default"}).then(function(imageBitmap) { bitmaps.flipYDefault = imageBitmap });
+        var p7 = createImageBitmap(bitmap, {imageOrientation: "flipY", premultiplyAlpha: "none"}).then(function(imageBitmap) { bitmaps.flipYUnpremul = imageBitmap });
+        Promise.all([p1, p2, p3, p4, p5, p6, p7]).then(function() {
+            var alphaVal = 0;
+            var testPassed = runTest(bitmaps, alphaVal);
+            if (testPassed)
+                pass();
+            finishJSTest();
+        }, function() {
+            promiseRejected();
+            finishJSTest();
+        });
+    }, function() {
+        promiseRejected();
+        finishJSTest();
+    });
+}
+
+function init()
+{
+    if (window.testRunner) {
+        testRunner.overridePreference("WebKitWebGLEnabled", "1");
+        testRunner.dumpAsText();
+    }
+    generateTest();
+}
+</script>
+</head>
+<body onload="init()">
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="results">Test <span style="color:red">FAILED</span></div>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-image-bitmap-from-image-data-expected.txt b/third_party/WebKit/LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-image-bitmap-from-image-data-expected.txt
new file mode 100644
index 0000000..22c2f2f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-image-bitmap-from-image-data-expected.txt
@@ -0,0 +1,5 @@
+PASS successfullyParsed is true
+
+TEST COMPLETE
+ 
+Test PASSED
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-image-bitmap-from-image-data.html b/third_party/WebKit/LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-image-bitmap-from-image-data.html
new file mode 100644
index 0000000..60c3c387
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-image-bitmap-from-image-data.html
@@ -0,0 +1,86 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="./resources/webgl-test-utils-full.js"></script>
+<script src="./resources/tex-image-and-sub-image-utils.js"></script>
+<script src="./resources/tex-image-and-sub-image-image-bitmap-utils.js"></script>
+<script src="../../../resources/js-test.js"></script>
+<script>
+
+window.jsTestIsAsync = true;
+
+var wtu = WebGLTestUtils;
+var tiu = TexImageUtils;
+var gl = null;
+var internalFormat = "RGBA";
+var pixelFormat = "RGBA";
+var pixelType = "UNSIGNED_BYTE";
+var redColor = [255, 0, 0];
+var greenColor = [0, 255, 0];
+var blackColor = [0, 0, 0];
+var halfRed = [128, 0, 0];
+var halfGreen = [0, 128, 0];
+
+function promiseRejected()
+{
+    document.getElementById("results").innerHTML = "Promise <span style='color:red'>REJECTED</span>";
+}
+
+function pass()
+{
+    document.getElementById("results").innerHTML = "Test <span style='color:green'>PASSED</span>";
+}
+
+function generateTest()
+{
+    var bitmaps = [];
+
+    var canvas = document.getElementById("example");
+    gl = canvas.getContext("webgl");
+
+    gl.clearColor(0,0,0,1);
+    gl.clearDepth(1);
+    gl.disable(gl.BLEND);
+
+    var imageData = new ImageData(new Uint8ClampedArray(
+                                  [255, 0, 0, 255,
+                                  255, 0, 0, 0,
+                                  0, 255, 0, 255,
+                                  0, 255, 0, 0]),
+                                  2, 2);
+
+    var p1 = createImageBitmap(imageData).then(function(imageBitmap) { bitmaps.defaultOption = imageBitmap });
+    var p2 = createImageBitmap(imageData, {imageOrientation: "none", premultiplyAlpha: "premultiply"}).then(function(imageBitmap) { bitmaps.noFlipYPremul = imageBitmap });
+    var p3 = createImageBitmap(imageData, {imageOrientation: "none", premultiplyAlpha: "default"}).then(function(imageBitmap) { bitmaps.noFlipYDefault = imageBitmap });
+    var p4 = createImageBitmap(imageData, {imageOrientation: "none", premultiplyAlpha: "none"}).then(function(imageBitmap) { bitmaps.noFlipYUnpremul = imageBitmap });
+    var p5 = createImageBitmap(imageData, {imageOrientation: "flipY", premultiplyAlpha: "premultiply"}).then(function(imageBitmap) { bitmaps.flipYPremul = imageBitmap });
+    var p6 = createImageBitmap(imageData, {imageOrientation: "flipY", premultiplyAlpha: "default"}).then(function(imageBitmap) { bitmaps.flipYDefault = imageBitmap });
+    var p7 = createImageBitmap(imageData, {imageOrientation: "flipY", premultiplyAlpha: "none"}).then(function(imageBitmap) { bitmaps.flipYUnpremul = imageBitmap });
+    Promise.all([p1, p2, p3, p4, p5, p6, p7]).then(function() {
+        var alphaVal = 0;
+        var testPassed = runTest(bitmaps, alphaVal);
+        if (testPassed)
+            pass();
+        finishJSTest();
+    }, function() {
+        promiseRejected();
+        finishJSTest();
+    });
+}
+
+function init()
+{
+    if (window.testRunner) {
+        testRunner.overridePreference("WebKitWebGLEnabled", "1");
+        testRunner.dumpAsText();
+    }
+    generateTest();
+}
+</script>
+</head>
+<body onload="init()">
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="results">Test <span style="color:red">FAILED</span></div>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-image-bitmap-from-image-expected.txt b/third_party/WebKit/LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-image-bitmap-from-image-expected.txt
new file mode 100644
index 0000000..22c2f2f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-image-bitmap-from-image-expected.txt
@@ -0,0 +1,5 @@
+PASS successfullyParsed is true
+
+TEST COMPLETE
+ 
+Test PASSED
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-image-bitmap-from-image.html b/third_party/WebKit/LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-image-bitmap-from-image.html
new file mode 100644
index 0000000..93e1b34
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-image-bitmap-from-image.html
@@ -0,0 +1,83 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="./resources/webgl-test-utils-full.js"></script>
+<script src="./resources/tex-image-and-sub-image-utils.js"></script>
+<script src="./resources/tex-image-and-sub-image-image-bitmap-utils.js"></script>
+<script src="../../../resources/js-test.js"></script>
+<script>
+
+window.jsTestIsAsync = true;
+
+var wtu = WebGLTestUtils;
+var tiu = TexImageUtils;
+var gl = null;
+var internalFormat = "RGBA";
+var pixelFormat = "RGBA";
+var pixelType = "UNSIGNED_BYTE";
+var redColor = [255, 0, 0];
+var greenColor = [0, 255, 0];
+var blackColor = [0, 0, 0];
+var halfRed = [128, 0, 0];
+var halfGreen = [0, 128, 0];
+
+var image = new Image();
+
+function promiseRejected()
+{
+    document.getElementById("results").innerHTML = "Promise <span style='color:red'>REJECTED</span>";
+}
+
+function pass()
+{
+    document.getElementById("results").innerHTML = "Test <span style='color:green'>PASSED</span>";
+}
+
+function generateTest()
+{
+    var bitmaps = [];
+
+    var canvas = document.getElementById("example");
+    gl = canvas.getContext("webgl");
+
+    gl.clearColor(0,0,0,1);
+    gl.clearDepth(1);
+
+    var p1 = createImageBitmap(image).then(function(imageBitmap) { bitmaps.defaultOption = imageBitmap });
+    var p2 = createImageBitmap(image, {imageOrientation: "none", premultiplyAlpha: "premultiply"}).then(function(imageBitmap) { bitmaps.noFlipYPremul = imageBitmap });
+    var p3 = createImageBitmap(image, {imageOrientation: "none", premultiplyAlpha: "default"}).then(function(imageBitmap) { bitmaps.noFlipYDefault = imageBitmap });
+    var p4 = createImageBitmap(image, {imageOrientation: "none", premultiplyAlpha: "none"}).then(function(imageBitmap) { bitmaps.noFlipYUnpremul = imageBitmap });
+    var p5 = createImageBitmap(image, {imageOrientation: "flipY", premultiplyAlpha: "premultiply"}).then(function(imageBitmap) { bitmaps.flipYPremul = imageBitmap });
+    var p6 = createImageBitmap(image, {imageOrientation: "flipY", premultiplyAlpha: "default"}).then(function(imageBitmap) { bitmaps.flipYDefault = imageBitmap });
+    var p7 = createImageBitmap(image, {imageOrientation: "flipY", premultiplyAlpha: "none"}).then(function(imageBitmap) { bitmaps.flipYUnpremul = imageBitmap });
+    Promise.all([p1, p2, p3, p4, p5, p6, p7]).then(function() {
+        var alphaVal = 0.5;
+        var testPassed = runTest(bitmaps, alphaVal);
+        if (testPassed)
+            pass();
+        finishJSTest();
+    }, function() {
+        promiseRejected();
+        finishJSTest();
+    });
+}
+
+function init()
+{
+    if (window.testRunner) {
+        testRunner.overridePreference("WebKitWebGLEnabled", "1");
+        testRunner.dumpAsText();
+    }
+    image.onload = function() {
+        generateTest();
+    }
+    image.src = "resources/red-green-semi-transparent.png";
+}
+</script>
+</head>
+<body onload="init()">
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="results">Test <span style="color:red">FAILED</span></div>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-image-bitmap-from-video-expected.txt b/third_party/WebKit/LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-image-bitmap-from-video-expected.txt
new file mode 100644
index 0000000..22c2f2f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-image-bitmap-from-video-expected.txt
@@ -0,0 +1,5 @@
+PASS successfullyParsed is true
+
+TEST COMPLETE
+ 
+Test PASSED
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-image-bitmap-from-video.html b/third_party/WebKit/LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-image-bitmap-from-video.html
new file mode 100644
index 0000000..f0ee8c88
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-image-bitmap-from-video.html
@@ -0,0 +1,83 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="./resources/webgl-test-utils-full.js"></script>
+<script src="./resources/tex-image-and-sub-image-utils.js"></script>
+<script src="./resources/tex-image-and-sub-image-image-bitmap-utils.js"></script>
+<script src="../../../resources/js-test.js"></script>
+<script>
+
+window.jsTestIsAsync = true;
+
+var wtu = WebGLTestUtils;
+var tiu = TexImageUtils;
+var gl = null;
+var internalFormat = "RGBA";
+var pixelFormat = "RGBA";
+var pixelType = "UNSIGNED_BYTE";
+var redColor = [255, 0, 0];
+var greenColor = [0, 255, 0];
+var blackColor = [0, 0, 0];
+var halfRed = [128, 0, 0];
+var halfGreen = [0, 128, 0];
+
+var video = document.createElement("video");
+
+function promiseRejected()
+{
+    document.getElementById("results").innerHTML = "Promise <span style='color:red'>REJECTED</span>";
+}
+
+function pass()
+{
+    document.getElementById("results").innerHTML = "Test <span style='color:green'>PASSED</span>";
+}
+
+function generateTest()
+{
+    var bitmaps = [];
+
+    var canvas = document.getElementById("example");
+    gl = canvas.getContext("webgl");
+
+    gl.clearColor(0,0,0,1);
+    gl.clearDepth(1);
+
+    var p1 = createImageBitmap(video).then(function(imageBitmap) { bitmaps.defaultOption = imageBitmap });
+    var p2 = createImageBitmap(video, {imageOrientation: "none", premultiplyAlpha: "premultiply"}).then(function(imageBitmap) { bitmaps.noFlipYPremul = imageBitmap });
+    var p3 = createImageBitmap(video, {imageOrientation: "none", premultiplyAlpha: "default"}).then(function(imageBitmap) { bitmaps.noFlipYDefault = imageBitmap });
+    var p4 = createImageBitmap(video, {imageOrientation: "none", premultiplyAlpha: "none"}).then(function(imageBitmap) { bitmaps.noFlipYUnpremul = imageBitmap });
+    var p5 = createImageBitmap(video, {imageOrientation: "flipY", premultiplyAlpha: "premultiply"}).then(function(imageBitmap) { bitmaps.flipYPremul = imageBitmap });
+    var p6 = createImageBitmap(video, {imageOrientation: "flipY", premultiplyAlpha: "default"}).then(function(imageBitmap) { bitmaps.flipYDefault = imageBitmap });
+    var p7 = createImageBitmap(video, {imageOrientation: "flipY", premultiplyAlpha: "none"}).then(function(imageBitmap) { bitmaps.flipYUnpremul = imageBitmap });
+    Promise.all([p1, p2, p3, p4, p5, p6, p7]).then(function() {
+        var alphaVal = 1;
+        var testPassed = runTest(bitmaps, alphaVal);
+        if (testPassed)
+            pass();
+        finishJSTest();
+    }, function() {
+        promiseRejected();
+        finishJSTest();
+    });
+}
+
+function init()
+{
+    if (window.testRunner) {
+        testRunner.overridePreference("WebKitWebGLEnabled", "1");
+        testRunner.dumpAsText();
+    }
+    video.oncanplaythrough = function() {
+        generateTest();
+    }
+    video.src = "resources/red-green.ogv";
+}
+</script>
+</head>
+<body onload="init()">
+<canvas id="texcanvas" width="2" height="2"></canvas>
+<canvas id="example" width="32" height="32"></canvas>
+<div id="results">Test <span style="color:red">FAILED</span></div>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/svg/canvas/canvas-default-object-sizing-expected.html b/third_party/WebKit/LayoutTests/svg/canvas/canvas-default-object-sizing-expected.html
new file mode 100644
index 0000000..03e0925
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/svg/canvas/canvas-default-object-sizing-expected.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<title>Sizing SVG image when drawn to canvas</title>
+<script>
+function createCircle(x, y, r, sx, sy)
+{
+    var canvas = document.createElement('canvas');
+    canvas.width = 100;
+    canvas.height = 100;
+    document.documentElement.appendChild(canvas);
+
+    var ctx = canvas.getContext('2d');
+    ctx.fillStyle = "blue";
+
+    ctx.translate(50, 50);
+    ctx.scale(sx || 1, sy || 1);
+    ctx.beginPath();
+    ctx.arc(x, y, r, 0, 2*Math.PI);
+    ctx.fill();
+}
+createCircle(0, 0, 50);
+createCircle(0, -25, 25);
+createCircle(-25, 0, 25);
+createCircle(0, 0, 25, 1, 2);
+createCircle(0, 0, 25, 2, 1);
+createCircle(-25, 0, 25);
+createCircle(0, -25, 25);
+createCircle(0, -25, 25);
+createCircle(0, 0, 50);
+createCircle(0, 0, 50);
+createCircle(0, -25, 25);
+createCircle(0, 0, 50);
+</script>
diff --git a/third_party/WebKit/LayoutTests/svg/canvas/canvas-default-object-sizing.html b/third_party/WebKit/LayoutTests/svg/canvas/canvas-default-object-sizing.html
new file mode 100644
index 0000000..b15fda2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/svg/canvas/canvas-default-object-sizing.html
@@ -0,0 +1,99 @@
+<!DOCTYPE html>
+<title>Sizing SVG image when drawn to canvas</title>
+<script>
+function createCanvasWithImage(imgSrc, drawFunc)
+{
+    var canvas = document.createElement('canvas');
+    canvas.width = 100;
+    canvas.height = 100;
+    var img = document.createElement('img');
+    img.src = imgSrc;
+    img.onload = function() {
+        drawFunc(canvas.getContext('2d'), img);
+        document.documentElement.removeChild(img);
+    }
+    document.documentElement.appendChild(img);
+    document.documentElement.appendChild(canvas);
+}
+
+createCanvasWithImage(
+    'data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 10"><circle cx="5" cy="5" r="5" fill="blue"/></svg>',
+    function(ctx, img) {
+        ctx.drawImage(img, 0, 0);
+    });
+
+createCanvasWithImage(
+    'data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 10"><circle cx="10" cy="5" r="5" fill="blue"/></svg>',
+    function(ctx, img) {
+        ctx.drawImage(img, 0, 0);
+    });
+
+createCanvasWithImage(
+    'data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 20"><circle cx="5" cy="10" r="5" fill="blue"/></svg>',
+    function(ctx, img) {
+        ctx.drawImage(img, 0, 0);
+    });
+
+createCanvasWithImage(
+    'data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 10"><circle cx="10" cy="5" r="5" fill="blue"/></svg>',
+    function(ctx, img) {
+        ctx.drawImage(img, 0, 0, 100, 100);
+    });
+
+createCanvasWithImage(
+    'data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 20"><circle cx="5" cy="10" r="5" fill="blue"/></svg>',
+    function(ctx, img) {
+        ctx.drawImage(img, 0, 0, 100, 100);
+    });
+
+createCanvasWithImage(
+    'data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="50" viewBox="0 0 10 20"><circle cx="5" cy="10" r="5" fill="blue"/></svg>',
+    function(ctx, img) {
+        ctx.drawImage(img, 0, 0);
+    });
+
+createCanvasWithImage(
+    'data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" height="50" viewBox="0 0 20 10"><circle cx="10" cy="5" r="5" fill="blue"/></svg>',
+    function(ctx, img) {
+        ctx.drawImage(img, 0, 0);
+    });
+
+createCanvasWithImage(
+    'data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="50"><circle cx="50" cy="25" r="25" fill="blue"/></svg>',
+    function(ctx, img) {
+        ctx.drawImage(img, 0, 0);
+    });
+
+createCanvasWithImage(
+    'data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 10"><circle cx="5" cy="5" r="5" fill="blue"/></svg>',
+    function(ctx, img) {
+        ctx.drawImage(img, 0, 0, 50, 50, 0, 0, 50, 50);
+        ctx.drawImage(img, 50, 50, 50, 50, 50, 50, 50, 50);
+        ctx.drawImage(img, 0, 50, 50, 50, 0, 50, 50, 50);
+        ctx.drawImage(img, 50, 0, 50, 50, 50, 0, 50, 50);
+    });
+
+createCanvasWithImage(
+    'data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 10"><circle cx="5" cy="5" r="5" fill="blue"/></svg>',
+    function(ctx, img) {
+        var pattern = ctx.createPattern(img, "repeat");
+        ctx.fillStyle = pattern;
+        ctx.fillRect(0, 0, 100, 100);
+    });
+
+createCanvasWithImage(
+    'data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 10"><circle cx="10" cy="5" r="5" fill="blue"/></svg>',
+    function(ctx, img) {
+        var pattern = ctx.createPattern(img, "repeat");
+        ctx.fillStyle = pattern;
+        ctx.fillRect(0, 0, 100, 100);
+    });
+
+createCanvasWithImage(
+    'data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg"><circle cx="50" cy="50" r="50" fill="blue"/></svg>',
+    function(ctx, img) {
+        var pattern = ctx.createPattern(img, "repeat");
+        ctx.fillStyle = pattern;
+        ctx.fillRect(0, 0, 100, 100);
+    });
+</script>
diff --git a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt
index 2e2f139..7ba1b95 100644
--- a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -10,7 +10,6 @@
 CONSOLE WARNING: 'webkitIDBDatabase' is deprecated. Please use 'IDBDatabase' instead.
 CONSOLE WARNING: 'webkitIDBCursor' is deprecated. Please use 'IDBCursor' instead.
 CONSOLE WARNING: 'webkitIndexedDB' is deprecated. Please use 'indexedDB' instead.
-CONSOLE ERROR: The 'WebBluetooth' feature is currently enabled in limited trials. Please see [Phosphor console URL] for information on enabling a trial for your site.
 CONSOLE WARNING: 'webkitURL' is deprecated. Please use 'URL' instead.
 This test documents all interface attributes and methods on the global window object and element instances.
 
@@ -3058,7 +3057,6 @@
     getter appCodeName
     getter appName
     getter appVersion
-    getter bluetooth
     getter cookieEnabled
     getter credentials
     getter doNotTrack
@@ -5889,13 +5887,6 @@
     setter search
     setter username
 [GLOBAL OBJECT]
-    attribute BluetoothAdvertisingData
-    attribute BluetoothCharacteristicProperties
-    attribute BluetoothDevice
-    attribute BluetoothRemoteGATTCharacteristic
-    attribute BluetoothRemoteGATTServer
-    attribute BluetoothRemoteGATTService
-    attribute BluetoothUUID
     attribute GCController
     attribute accessibilityController
     attribute applicationCache
diff --git a/third_party/WebKit/Source/core/fetch/Resource.cpp b/third_party/WebKit/Source/core/fetch/Resource.cpp
index 2bf5f86..d0a359a 100644
--- a/third_party/WebKit/Source/core/fetch/Resource.cpp
+++ b/third_party/WebKit/Source/core/fetch/Resource.cpp
@@ -164,9 +164,6 @@
     , m_status(Pending)
     , m_needsSynchronousCacheHit(false)
     , m_linkPreload(false)
-#ifdef ENABLE_RESOURCE_IS_DELETED_CHECK
-    , m_deleted(false)
-#endif
 {
     ASSERT(m_type == unsigned(type)); // m_type is a bitfield, so this tests careless updates of the enum.
     InstanceCounters::incrementCounter(InstanceCounters::ResourceCounter);
@@ -186,12 +183,6 @@
 
 Resource::~Resource()
 {
-    assertAlive();
-
-#ifdef ENABLE_RESOURCE_IS_DELETED_CHECK
-    m_deleted = true;
-#endif
-
     InstanceCounters::decrementCounter(InstanceCounters::ResourceCounter);
 }
 
@@ -836,7 +827,6 @@
         m_response.setHTTPHeaderField(header.key, header.value);
     }
 
-    assertAlive();
     m_resourceRequest = m_revalidatingRequest;
     m_revalidatingRequest = ResourceRequest();
 }
@@ -846,6 +836,7 @@
     m_resourceRequest = m_revalidatingRequest;
     m_revalidatingRequest = ResourceRequest();
     m_data.clear();
+    m_cachedMetadata.clear();
     destroyDecodedDataForFailedRevalidation();
 }
 
@@ -963,13 +954,11 @@
 {
     if (!m_callbackTaskFactory->isPending())
         Platform::current()->currentThread()->scheduler()->loadingTaskRunner()->postTask(BLINK_FROM_HERE, m_callbackTaskFactory->cancelAndCreate());
-    resource->assertAlive();
     m_resourcesWithPendingClients.add(resource);
 }
 
 void Resource::ResourceCallback::cancel(Resource* resource)
 {
-    resource->assertAlive();
     m_resourcesWithPendingClients.remove(resource);
     if (m_callbackTaskFactory->isPending() && m_resourcesWithPendingClients.isEmpty())
         m_callbackTaskFactory->cancel();
@@ -987,14 +976,8 @@
         resources.append(resource.get());
     m_resourcesWithPendingClients.clear();
 
-    for (const auto& resource : resources) {
-        resource->assertAlive();
-        resource->finishPendingClients();
-        resource->assertAlive();
-    }
-
     for (const auto& resource : resources)
-        resource->assertAlive();
+        resource->finishPendingClients();
 }
 
 static const char* initatorTypeNameToString(const AtomicString& initiatorTypeName)
diff --git a/third_party/WebKit/Source/core/fetch/Resource.h b/third_party/WebKit/Source/core/fetch/Resource.h
index 2dd4369..9c6734f 100644
--- a/third_party/WebKit/Source/core/fetch/Resource.h
+++ b/third_party/WebKit/Source/core/fetch/Resource.h
@@ -40,9 +40,6 @@
 #include "wtf/OwnPtr.h"
 #include "wtf/text/WTFString.h"
 
-// FIXME(crbug.com/352043): This is temporarily enabled even on RELEASE to diagnose a wild crash.
-#define ENABLE_RESOURCE_IS_DELETED_CHECK
-
 namespace blink {
 
 struct FetchInitiatorInfo;
@@ -51,7 +48,6 @@
 class ResourceClient;
 class ResourceFetcher;
 class ResourceTimingInfo;
-class InspectorResource;
 class ResourceLoader;
 class SecurityOrigin;
 class SharedBuffer;
@@ -62,8 +58,6 @@
 class CORE_EXPORT Resource : public RefCountedWillBeGarbageCollectedFinalized<Resource> {
     WTF_MAKE_NONCOPYABLE(Resource);
     USING_FAST_MALLOC_WITH_TYPE_NAME_WILL_BE_REMOVED(blink::Resource);
-    friend class InspectorResource;
-
 public:
     enum Type {
         MainResource,
@@ -260,12 +254,6 @@
     // TODO(japhet): Remove once oilpan ships, it doesn't need the WeakPtr.
     WeakPtrWillBeRawPtr<Resource> asWeakPtr();
 
-#ifdef ENABLE_RESOURCE_IS_DELETED_CHECK
-    void assertAlive() const { RELEASE_ASSERT(!m_deleted); }
-#else
-    void assertAlive() const { }
-#endif
-
 protected:
     Resource(const ResourceRequest&, Type);
 
@@ -379,10 +367,6 @@
     unsigned m_needsSynchronousCacheHit : 1;
     unsigned m_linkPreload : 1;
 
-#ifdef ENABLE_RESOURCE_IS_DELETED_CHECK
-    bool m_deleted;
-#endif
-
     // Ordered list of all redirects followed while fetching this resource.
     Vector<RedirectPair> m_redirectChain;
 };
diff --git a/third_party/WebKit/Source/core/frame/ImageBitmap.cpp b/third_party/WebKit/Source/core/frame/ImageBitmap.cpp
index ed6061d2..a3a1d3e3 100644
--- a/third_party/WebKit/Source/core/frame/ImageBitmap.cpp
+++ b/third_party/WebKit/Source/core/frame/ImageBitmap.cpp
@@ -433,7 +433,7 @@
     }
 }
 
-PassRefPtr<Image> ImageBitmap::getSourceImageForCanvas(SourceImageStatus* status, AccelerationHint, SnapshotReason) const
+PassRefPtr<Image> ImageBitmap::getSourceImageForCanvas(SourceImageStatus* status, AccelerationHint, SnapshotReason, const FloatSize&) const
 {
     *status = NormalSourceImageStatus;
     return m_image ? m_image : nullptr;
@@ -443,7 +443,7 @@
 {
 }
 
-FloatSize ImageBitmap::elementSize() const
+FloatSize ImageBitmap::elementSize(const FloatSize&) const
 {
     return FloatSize(width(), height());
 }
diff --git a/third_party/WebKit/Source/core/frame/ImageBitmap.h b/third_party/WebKit/Source/core/frame/ImageBitmap.h
index b29cdd0..6e8f52c 100644
--- a/third_party/WebKit/Source/core/frame/ImageBitmap.h
+++ b/third_party/WebKit/Source/core/frame/ImageBitmap.h
@@ -58,10 +58,10 @@
     ~ImageBitmap() override;
 
     // CanvasImageSource implementation
-    PassRefPtr<Image> getSourceImageForCanvas(SourceImageStatus*, AccelerationHint, SnapshotReason) const override;
+    PassRefPtr<Image> getSourceImageForCanvas(SourceImageStatus*, AccelerationHint, SnapshotReason, const FloatSize&) const override;
     bool wouldTaintOrigin(SecurityOrigin*) const override { return !m_image->originClean(); }
     void adjustDrawRects(FloatRect* srcRect, FloatRect* dstRect) const override;
-    FloatSize elementSize() const override;
+    FloatSize elementSize(const FloatSize&) const override;
 
     // ImageBitmapSource implementation
     IntSize bitmapSourceSize() const override { return size(); }
diff --git a/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp b/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp
index 06208a1..282719c7 100644
--- a/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp
@@ -424,7 +424,7 @@
 
     if (listenerNeedsNewFrameCapture) {
         SourceImageStatus status;
-        RefPtr<Image> sourceImage = getSourceImageForCanvas(&status, PreferNoAcceleration, SnapshotReasonCanvasListenerCapture);
+        RefPtr<Image> sourceImage = getSourceImageForCanvas(&status, PreferNoAcceleration, SnapshotReasonCanvasListenerCapture, FloatSize());
         if (status != NormalSourceImageStatus)
             return;
         RefPtr<SkImage> image = sourceImage->imageForCurrentFrame();
@@ -969,7 +969,7 @@
     HTMLElement::didMoveToNewDocument(oldDocument);
 }
 
-PassRefPtr<Image> HTMLCanvasElement::getSourceImageForCanvas(SourceImageStatus* status, AccelerationHint hint, SnapshotReason reason) const
+PassRefPtr<Image> HTMLCanvasElement::getSourceImageForCanvas(SourceImageStatus* status, AccelerationHint hint, SnapshotReason reason, const FloatSize&) const
 {
     if (!width() || !height()) {
         *status = ZeroSizeCanvasSourceImageStatus;
@@ -1005,7 +1005,7 @@
     return !originClean();
 }
 
-FloatSize HTMLCanvasElement::elementSize() const
+FloatSize HTMLCanvasElement::elementSize(const FloatSize&) const
 {
     return FloatSize(width(), height());
 }
diff --git a/third_party/WebKit/Source/core/html/HTMLCanvasElement.h b/third_party/WebKit/Source/core/html/HTMLCanvasElement.h
index 5d7d9d9..e9ee1b4 100644
--- a/third_party/WebKit/Source/core/html/HTMLCanvasElement.h
+++ b/third_party/WebKit/Source/core/html/HTMLCanvasElement.h
@@ -152,9 +152,9 @@
     void willDetachDocument() override;
 
     // CanvasImageSource implementation
-    PassRefPtr<Image> getSourceImageForCanvas(SourceImageStatus*, AccelerationHint, SnapshotReason) const override;
+    PassRefPtr<Image> getSourceImageForCanvas(SourceImageStatus*, AccelerationHint, SnapshotReason, const FloatSize&) const override;
     bool wouldTaintOrigin(SecurityOrigin*) const override;
-    FloatSize elementSize() const override;
+    FloatSize elementSize(const FloatSize&) const override;
     bool isCanvasElement() const override { return true; }
     bool isOpaque() const override;
 
diff --git a/third_party/WebKit/Source/core/html/HTMLImageElement.cpp b/third_party/WebKit/Source/core/html/HTMLImageElement.cpp
index 710c63fb..f39c27b 100644
--- a/third_party/WebKit/Source/core/html/HTMLImageElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLImageElement.cpp
@@ -603,7 +603,7 @@
     return fastHasAttribute(usemapAttr);
 }
 
-PassRefPtr<Image> HTMLImageElement::getSourceImageForCanvas(SourceImageStatus* status, AccelerationHint, SnapshotReason) const
+PassRefPtr<Image> HTMLImageElement::getSourceImageForCanvas(SourceImageStatus* status, AccelerationHint, SnapshotReason, const FloatSize& defaultObjectSize) const
 {
     if (!complete() || !cachedImage()) {
         *status = IncompleteSourceImageStatus;
@@ -617,8 +617,10 @@
 
     RefPtr<Image> sourceImage;
     if (cachedImage()->image()->isSVGImage()) {
-        sourceImage = SVGImageForContainer::create(toSVGImage(cachedImage()->image()),
-            cachedImage()->image()->size(), 1, document().completeURL(imageSourceURL()));
+        SVGImage* svgImage = toSVGImage(cachedImage()->image());
+        IntSize imageSize = roundedIntSize(svgImage->concreteObjectSize(defaultObjectSize));
+        sourceImage = SVGImageForContainer::create(svgImage,
+            imageSize, 1, document().completeURL(imageSourceURL()));
     } else {
         sourceImage = cachedImage()->image();
     }
@@ -640,20 +642,27 @@
     return !image->isAccessAllowed(destinationSecurityOrigin);
 }
 
-FloatSize HTMLImageElement::elementSize() const
+FloatSize HTMLImageElement::elementSize(const FloatSize& defaultObjectSize) const
 {
     ImageResource* image = cachedImage();
     if (!image)
         return FloatSize();
 
+    if (image->image() && image->image()->isSVGImage())
+        return toSVGImage(cachedImage()->image())->concreteObjectSize(defaultObjectSize);
+
     return FloatSize(image->imageSize(LayoutObject::shouldRespectImageOrientation(layoutObject()), 1.0f));
 }
 
-FloatSize HTMLImageElement::defaultDestinationSize() const
+FloatSize HTMLImageElement::defaultDestinationSize(const FloatSize& defaultObjectSize) const
 {
     ImageResource* image = cachedImage();
     if (!image)
         return FloatSize();
+
+    if (image->image() && image->image()->isSVGImage())
+        return toSVGImage(cachedImage()->image())->concreteObjectSize(defaultObjectSize);
+
     LayoutSize size;
     size = image->imageSize(LayoutObject::shouldRespectImageOrientation(layoutObject()), 1.0f);
     if (layoutObject() && layoutObject()->isLayoutImage() && image->image() && !image->image()->hasRelativeSize())
diff --git a/third_party/WebKit/Source/core/html/HTMLImageElement.h b/third_party/WebKit/Source/core/html/HTMLImageElement.h
index 8107e1c..fa7cf46 100644
--- a/third_party/WebKit/Source/core/html/HTMLImageElement.h
+++ b/third_party/WebKit/Source/core/html/HTMLImageElement.h
@@ -96,11 +96,11 @@
     virtual void ensurePrimaryContent();
 
     // CanvasImageSource implementation
-    PassRefPtr<Image> getSourceImageForCanvas(SourceImageStatus*, AccelerationHint, SnapshotReason) const override;
+    PassRefPtr<Image> getSourceImageForCanvas(SourceImageStatus*, AccelerationHint, SnapshotReason, const FloatSize&) const override;
     bool isSVGSource() const override;
     bool wouldTaintOrigin(SecurityOrigin*) const override;
-    FloatSize elementSize() const override;
-    FloatSize defaultDestinationSize() const override;
+    FloatSize elementSize(const FloatSize&) const override;
+    FloatSize defaultDestinationSize(const FloatSize&) const override;
     const KURL& sourceURL() const override;
     bool isOpaque() const override;
 
diff --git a/third_party/WebKit/Source/core/html/HTMLVideoElement.cpp b/third_party/WebKit/Source/core/html/HTMLVideoElement.cpp
index 6fc3269..85d0cad 100644
--- a/third_party/WebKit/Source/core/html/HTMLVideoElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLVideoElement.cpp
@@ -285,7 +285,7 @@
     return document().completeURL(url);
 }
 
-PassRefPtr<Image> HTMLVideoElement::getSourceImageForCanvas(SourceImageStatus* status, AccelerationHint, SnapshotReason) const
+PassRefPtr<Image> HTMLVideoElement::getSourceImageForCanvas(SourceImageStatus* status, AccelerationHint, SnapshotReason, const FloatSize&) const
 {
     if (!hasAvailableVideoFrame()) {
         *status = InvalidSourceImageStatus;
@@ -316,7 +316,7 @@
     return !isMediaDataCORSSameOrigin(destinationSecurityOrigin);
 }
 
-FloatSize HTMLVideoElement::elementSize() const
+FloatSize HTMLVideoElement::elementSize(const FloatSize&) const
 {
     return FloatSize(videoWidth(), videoHeight());
 }
diff --git a/third_party/WebKit/Source/core/html/HTMLVideoElement.h b/third_party/WebKit/Source/core/html/HTMLVideoElement.h
index 9f0fa8ec..5899174 100644
--- a/third_party/WebKit/Source/core/html/HTMLVideoElement.h
+++ b/third_party/WebKit/Source/core/html/HTMLVideoElement.h
@@ -80,10 +80,10 @@
     KURL posterImageURL() const override;
 
     // CanvasImageSource implementation
-    PassRefPtr<Image> getSourceImageForCanvas(SourceImageStatus*, AccelerationHint, SnapshotReason) const override;
+    PassRefPtr<Image> getSourceImageForCanvas(SourceImageStatus*, AccelerationHint, SnapshotReason, const FloatSize&) const override;
     bool isVideoElement() const override { return true; }
     bool wouldTaintOrigin(SecurityOrigin*) const override;
-    FloatSize elementSize() const override;
+    FloatSize elementSize(const FloatSize&) const override;
     const KURL& sourceURL() const override { return currentSrc(); }
 
     bool isHTMLVideoElement() const override { return true; }
diff --git a/third_party/WebKit/Source/core/html/canvas/CanvasImageSource.h b/third_party/WebKit/Source/core/html/canvas/CanvasImageSource.h
index b1a8788..7e897c43 100644
--- a/third_party/WebKit/Source/core/html/canvas/CanvasImageSource.h
+++ b/third_party/WebKit/Source/core/html/canvas/CanvasImageSource.h
@@ -46,7 +46,7 @@
 
 class CORE_EXPORT CanvasImageSource {
 public:
-    virtual PassRefPtr<Image> getSourceImageForCanvas(SourceImageStatus*, AccelerationHint, SnapshotReason) const = 0;
+    virtual PassRefPtr<Image> getSourceImageForCanvas(SourceImageStatus*, AccelerationHint, SnapshotReason, const FloatSize&) const = 0;
 
     // IMPORTANT: Result must be independent of whether destinationContext is
     // already tainted because this function may be used to determine whether
@@ -62,8 +62,8 @@
     // source image is a subregion of the image returned by getSourceImageForCanvas.
     virtual void adjustDrawRects(FloatRect* srcRect, FloatRect* dstRect) const { }
 
-    virtual FloatSize elementSize() const = 0;
-    virtual FloatSize defaultDestinationSize() const { return elementSize(); }
+    virtual FloatSize elementSize(const FloatSize& defaultObjectSize) const = 0;
+    virtual FloatSize defaultDestinationSize(const FloatSize& defaultObjectSize) const { return elementSize(defaultObjectSize); }
     virtual const KURL& sourceURL() const { return blankURL(); }
     virtual bool isOpaque() const { return false; }
 
diff --git a/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp b/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp
index ec2136e8..b9b19b90 100644
--- a/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp
+++ b/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp
@@ -671,9 +671,12 @@
 {
     if (!m_page->mainFrame()->isLocalFrame() || !m_page->deprecatedLocalMainFrame()->view())
         return;
-    if (WebLayer* scrollLayer = toWebLayer(m_page->deprecatedLocalMainFrame()->view()->layerForScrolling())) {
+    GraphicsLayer* layer = m_page->deprecatedLocalMainFrame()->view()->layerForScrolling();
+    if (WebLayer* scrollLayer = toWebLayer(layer)) {
         m_lastMainThreadScrollingReasons = mainThreadScrollingReasons;
         if (mainThreadScrollingReasons) {
+            if (ScrollAnimatorBase* scrollAnimator = layer->scrollableArea()->existingScrollAnimator())
+                scrollAnimator->takeoverCompositorAnimation();
             scrollLayer->addMainThreadScrollingReasons(mainThreadScrollingReasons);
         } else {
             // Clear all main thread scrolling reasons except the one that's set
diff --git a/third_party/WebKit/Source/core/svg/graphics/SVGImage.cpp b/third_party/WebKit/Source/core/svg/graphics/SVGImage.cpp
index aaccff3..f566ad8 100644
--- a/third_party/WebKit/Source/core/svg/graphics/SVGImage.cpp
+++ b/third_party/WebKit/Source/core/svg/graphics/SVGImage.cpp
@@ -261,7 +261,7 @@
 
 PassRefPtr<SkImage> SVGImage::imageForCurrentFrame()
 {
-    return imageForCurrentFrameForContainer(KURL());
+    return imageForCurrentFrameForContainer(KURL(), FloatSize(size()));
 }
 
 void SVGImage::drawPatternForContainer(GraphicsContext& context, const FloatSize containerSize,
@@ -301,14 +301,14 @@
     context.drawRect(dstRect, paint);
 }
 
-PassRefPtr<SkImage> SVGImage::imageForCurrentFrameForContainer(const KURL& url)
+PassRefPtr<SkImage> SVGImage::imageForCurrentFrameForContainer(const KURL& url, const FloatSize& containerSize)
 {
     if (!m_page)
         return nullptr;
 
     SkPictureRecorder recorder;
     SkCanvas* canvas = recorder.beginRecording(width(), height());
-    drawForContainer(canvas, SkPaint(), FloatSize(size()), 1, rect(), rect(), url);
+    drawForContainer(canvas, SkPaint(), containerSize, 1, rect(), rect(), url);
     RefPtr<SkPicture> picture = adoptRef(recorder.endRecording());
 
     return adoptRef(
diff --git a/third_party/WebKit/Source/core/svg/graphics/SVGImage.h b/third_party/WebKit/Source/core/svg/graphics/SVGImage.h
index 903b9a8..04e8e5eca 100644
--- a/third_party/WebKit/Source/core/svg/graphics/SVGImage.h
+++ b/third_party/WebKit/Source/core/svg/graphics/SVGImage.h
@@ -110,7 +110,7 @@
     void drawForContainer(SkCanvas*, const SkPaint&, const FloatSize, float, const FloatRect&, const FloatRect&, const KURL&);
     void drawPatternForContainer(GraphicsContext&, const FloatSize, float, const FloatRect&, const FloatSize&, const FloatPoint&,
         SkXfermode::Mode, const FloatRect&, const FloatSize& repeatSpacing, const KURL&);
-    PassRefPtr<SkImage> imageForCurrentFrameForContainer(const KURL&);
+    PassRefPtr<SkImage> imageForCurrentFrameForContainer(const KURL&, const FloatSize& containerSize);
     void drawInternal(SkCanvas*, const SkPaint&, const FloatRect& fromRect, const FloatRect& toRect, RespectImageOrientationEnum,
         ImageClampingMode, const KURL&);
 
diff --git a/third_party/WebKit/Source/core/svg/graphics/SVGImageForContainer.cpp b/third_party/WebKit/Source/core/svg/graphics/SVGImageForContainer.cpp
index cb7957d..3a2a1ce 100644
--- a/third_party/WebKit/Source/core/svg/graphics/SVGImageForContainer.cpp
+++ b/third_party/WebKit/Source/core/svg/graphics/SVGImageForContainer.cpp
@@ -53,7 +53,7 @@
 
 PassRefPtr<SkImage> SVGImageForContainer::imageForCurrentFrame()
 {
-    return m_image->imageForCurrentFrameForContainer(m_url);
+    return m_image->imageForCurrentFrameForContainer(m_url, m_containerSize);
 }
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/modules/bluetooth/Bluetooth.cpp b/third_party/WebKit/Source/modules/bluetooth/Bluetooth.cpp
index 6ff6ed2..c881c4d9 100644
--- a/third_party/WebKit/Source/modules/bluetooth/Bluetooth.cpp
+++ b/third_party/WebKit/Source/modules/bluetooth/Bluetooth.cpp
@@ -129,12 +129,15 @@
 // https://webbluetoothchrome.github.io/web-bluetooth/#dom-bluetooth-requestdevice
 ScriptPromise Bluetooth::requestDevice(ScriptState* scriptState, const RequestDeviceOptions& options, ExceptionState& exceptionState)
 {
+    // TODO(https://crbug.com/584113) Enable Web Bluetooth Experiment.
+    // Restore this logic when re-enabling the experiment:
+    //
     // By adding the "OriginTrialEnabled" extended binding, we enable the
     // requestDevice function on all platforms for whitelisted domains. Since we
     // only support Chrome OS and Android for this experiment we reject any
     // promises from other platforms unless they have the enable-web-bluetooth
     // flag on.
-#if !OS(CHROMEOS) && !OS(ANDROID)
+#if 0 // !OS(CHROMEOS) && !OS(ANDROID)
     if (!RuntimeEnabledFeatures::webBluetoothEnabled()) {
         return ScriptPromise::rejectWithDOMException(scriptState, DOMException::create(NotSupportedError, "Web Bluetooth is not enabled on this platform. To find out how to enable it and the current implementation status visit https://goo.gl/HKa2If"));
     }
diff --git a/third_party/WebKit/Source/modules/bluetooth/Bluetooth.idl b/third_party/WebKit/Source/modules/bluetooth/Bluetooth.idl
index 88f0d2e..4055338 100644
--- a/third_party/WebKit/Source/modules/bluetooth/Bluetooth.idl
+++ b/third_party/WebKit/Source/modules/bluetooth/Bluetooth.idl
@@ -8,7 +8,8 @@
     GarbageCollected,
     NoInterfaceObject,
     RuntimeEnabled=WebBluetooth,
-    OriginTrialEnabled=WebBluetooth,
+    // TODO(https://crbug.com/584113) Enable Web Bluetooth Experiment.
+    // OriginTrialEnabled=WebBluetooth,
 ] interface Bluetooth {
     [CallWith=ScriptState, RaisesException] Promise<BluetoothDevice> requestDevice (
         RequestDeviceOptions options
diff --git a/third_party/WebKit/Source/modules/bluetooth/BluetoothAdvertisingData.idl b/third_party/WebKit/Source/modules/bluetooth/BluetoothAdvertisingData.idl
index 5b24c37..818e5b4 100644
--- a/third_party/WebKit/Source/modules/bluetooth/BluetoothAdvertisingData.idl
+++ b/third_party/WebKit/Source/modules/bluetooth/BluetoothAdvertisingData.idl
@@ -9,7 +9,8 @@
 [
     GarbageCollected,
     RuntimeEnabled=WebBluetooth,
-    OriginTrialEnabled=WebBluetooth,
+    // TODO(https://crbug.com/584113) Enable Web Bluetooth Experiment.
+    // OriginTrialEnabled=WebBluetooth,
 ] interface BluetoothAdvertisingData {
     // readonly attribute unsigned short? appearance;
     readonly attribute byte? txPower;
diff --git a/third_party/WebKit/Source/modules/bluetooth/BluetoothCharacteristicProperties.idl b/third_party/WebKit/Source/modules/bluetooth/BluetoothCharacteristicProperties.idl
index b848b3a7..ca87d7d 100644
--- a/third_party/WebKit/Source/modules/bluetooth/BluetoothCharacteristicProperties.idl
+++ b/third_party/WebKit/Source/modules/bluetooth/BluetoothCharacteristicProperties.idl
@@ -9,7 +9,8 @@
 [
     GarbageCollected,
     RuntimeEnabled=WebBluetooth,
-    OriginTrialEnabled=WebBluetooth,
+    // TODO(https://crbug.com/584113) Enable Web Bluetooth Experiment.
+    // OriginTrialEnabled=WebBluetooth,
 ] interface BluetoothCharacteristicProperties {
     readonly attribute boolean broadcast;
     readonly attribute boolean read;
diff --git a/third_party/WebKit/Source/modules/bluetooth/BluetoothDevice.idl b/third_party/WebKit/Source/modules/bluetooth/BluetoothDevice.idl
index 3a10f7c..13ac479 100644
--- a/third_party/WebKit/Source/modules/bluetooth/BluetoothDevice.idl
+++ b/third_party/WebKit/Source/modules/bluetooth/BluetoothDevice.idl
@@ -15,7 +15,8 @@
     GarbageCollected,
     DependentLifetime,
     RuntimeEnabled=WebBluetooth,
-    OriginTrialEnabled=WebBluetooth,
+    // TODO(https://crbug.com/584113) Enable Web Bluetooth Experiment.
+    // OriginTrialEnabled=WebBluetooth,
 ] interface BluetoothDevice : EventTarget
 // Implement ServiceEventHandlers interface: http://crbug.com/421670
 // : ServiceEventHandlers
diff --git a/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTCharacteristic.idl b/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTCharacteristic.idl
index 7f3d77c..16c2dd2 100644
--- a/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTCharacteristic.idl
+++ b/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTCharacteristic.idl
@@ -10,7 +10,8 @@
     GarbageCollected,
     DependentLifetime,
     RuntimeEnabled=WebBluetooth,
-    OriginTrialEnabled=WebBluetooth,
+    // TODO(https://crbug.com/584113) Enable Web Bluetooth Experiment.
+    // OriginTrialEnabled=WebBluetooth,
 ] interface BluetoothRemoteGATTCharacteristic : EventTarget {//: CharacteristicEventHandlers {
     // TODO(ortuno): Add test to make sure service matches the service
     // used to call getCharacteristic.
diff --git a/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTServer.idl b/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTServer.idl
index fee90a2b..5e26954 100644
--- a/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTServer.idl
+++ b/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTServer.idl
@@ -9,7 +9,8 @@
 [
     GarbageCollected,
     RuntimeEnabled=WebBluetooth,
-    OriginTrialEnabled=WebBluetooth,
+    // TODO(https://crbug.com/584113) Enable Web Bluetooth Experiment.
+    // OriginTrialEnabled=WebBluetooth,
 ] interface BluetoothRemoteGATTServer
 {
     readonly attribute BluetoothDevice                   device;
diff --git a/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTService.idl b/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTService.idl
index 281e5bb..85ce907 100644
--- a/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTService.idl
+++ b/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTService.idl
@@ -9,7 +9,8 @@
 [
     GarbageCollected,
     RuntimeEnabled=WebBluetooth,
-    OriginTrialEnabled=WebBluetooth,
+    // TODO(https://crbug.com/584113) Enable Web Bluetooth Experiment.
+    // OriginTrialEnabled=WebBluetooth,
 ] interface BluetoothRemoteGATTService { // : ServiceEventHandlers {
     readonly    attribute UUID            uuid;
     readonly    attribute boolean         isPrimary;
diff --git a/third_party/WebKit/Source/modules/bluetooth/BluetoothUUID.idl b/third_party/WebKit/Source/modules/bluetooth/BluetoothUUID.idl
index f36b616..a064b3d 100644
--- a/third_party/WebKit/Source/modules/bluetooth/BluetoothUUID.idl
+++ b/third_party/WebKit/Source/modules/bluetooth/BluetoothUUID.idl
@@ -10,7 +10,8 @@
 [
     GarbageCollected,
     RuntimeEnabled=WebBluetooth,
-    OriginTrialEnabled=WebBluetooth,
+    // TODO(https://crbug.com/584113) Enable Web Bluetooth Experiment.
+    // OriginTrialEnabled=WebBluetooth,
 ] interface BluetoothUUID {
     [RaisesException] static UUID getService((DOMString or unsigned long) name);
     [RaisesException] static UUID getCharacteristic((DOMString or unsigned long) name);
diff --git a/third_party/WebKit/Source/modules/bluetooth/NavigatorBluetooth.idl b/third_party/WebKit/Source/modules/bluetooth/NavigatorBluetooth.idl
index 4c33b72..e7c777c 100644
--- a/third_party/WebKit/Source/modules/bluetooth/NavigatorBluetooth.idl
+++ b/third_party/WebKit/Source/modules/bluetooth/NavigatorBluetooth.idl
@@ -10,5 +10,8 @@
     // Experimental Framework doesn't support adding bindings to partial
     // interfaces yet, so we add it to the bluetooth attribute instead.
     // https://crbug.com/585656
-    [OriginTrialEnabled=WebBluetooth] readonly attribute Bluetooth bluetooth;
+    [
+        // TODO(https://crbug.com/584113) Enable Web Bluetooth Experiment.
+        // OriginTrialEnabled=WebBluetooth
+    ] readonly attribute Bluetooth bluetooth;
 };
diff --git a/third_party/WebKit/Source/modules/canvas2d/BaseRenderingContext2D.cpp b/third_party/WebKit/Source/modules/canvas2d/BaseRenderingContext2D.cpp
index fc3b511..dd9b9ed 100644
--- a/third_party/WebKit/Source/modules/canvas2d/BaseRenderingContext2D.cpp
+++ b/third_party/WebKit/Source/modules/canvas2d/BaseRenderingContext2D.cpp
@@ -856,8 +856,9 @@
 void BaseRenderingContext2D::drawImage(const CanvasImageSourceUnion& imageSource, double x, double y, ExceptionState& exceptionState)
 {
     CanvasImageSource* imageSourceInternal = toImageSourceInternal(imageSource);
-    FloatSize sourceRectSize = imageSourceInternal->elementSize();
-    FloatSize destRectSize = imageSourceInternal->defaultDestinationSize();
+    FloatSize defaultObjectSize(width(), height());
+    FloatSize sourceRectSize = imageSourceInternal->elementSize(defaultObjectSize);
+    FloatSize destRectSize = imageSourceInternal->defaultDestinationSize(defaultObjectSize);
     drawImage(imageSourceInternal, 0, 0, sourceRectSize.width(), sourceRectSize.height(), x, y, destRectSize.width(), destRectSize.height(), exceptionState);
 }
 
@@ -865,7 +866,8 @@
     double x, double y, double width, double height, ExceptionState& exceptionState)
 {
     CanvasImageSource* imageSourceInternal = toImageSourceInternal(imageSource);
-    FloatSize sourceRectSize = imageSourceInternal->elementSize();
+    FloatSize defaultObjectSize(this->width(), this->height());
+    FloatSize sourceRectSize = imageSourceInternal->elementSize(defaultObjectSize);
     drawImage(imageSourceInternal, 0, 0, sourceRectSize.width(), sourceRectSize.height(), x, y, width, height, exceptionState);
 }
 
@@ -971,10 +973,11 @@
         return;
 
     RefPtr<Image> image;
+    FloatSize defaultObjectSize(width(), height());
     SourceImageStatus sourceImageStatus = InvalidSourceImageStatus;
     if (!imageSource->isVideoElement()) {
         AccelerationHint hint = imageBuffer()->isAccelerated() ? PreferAcceleration : PreferNoAcceleration;
-        image = imageSource->getSourceImageForCanvas(&sourceImageStatus, hint, SnapshotReasonDrawImage);
+        image = imageSource->getSourceImageForCanvas(&sourceImageStatus, hint, SnapshotReasonDrawImage, defaultObjectSize);
         if (sourceImageStatus == UndecodableSourceImageStatus)
             exceptionState.throwDOMException(InvalidStateError, "The HTMLImageElement provided is in the 'broken' state.");
         if (!image || !image->width() || !image->height())
@@ -991,8 +994,9 @@
 
     FloatRect srcRect = normalizeRect(FloatRect(sx, sy, sw, sh));
     FloatRect dstRect = normalizeRect(FloatRect(dx, dy, dw, dh));
+    FloatSize imageSize = imageSource->elementSize(defaultObjectSize);
 
-    clipRectsToImageRect(FloatRect(FloatPoint(), imageSource->elementSize()), &srcRect, &dstRect);
+    clipRectsToImageRect(FloatRect(FloatPoint(), imageSize), &srcRect, &dstRect);
 
     imageSource->adjustDrawRects(&srcRect, &dstRect);
 
@@ -1023,7 +1027,7 @@
     if (ExpensiveCanvasHeuristicParameters::SVGImageSourcesAreExpensive && imageSource->isSVGSource())
         isExpensive = true;
 
-    if (imageSource->elementSize().width() * imageSource->elementSize().height() > width() * height() * ExpensiveCanvasHeuristicParameters::ExpensiveImageSizeRatio)
+    if (imageSize.width() * imageSize.height() > width() * height() * ExpensiveCanvasHeuristicParameters::ExpensiveImageSizeRatio)
         isExpensive = true;
 
     if (isExpensive) {
@@ -1083,13 +1087,14 @@
 
     SourceImageStatus status;
     CanvasImageSource* imageSourceInternal = toImageSourceInternal(imageSource);
-    RefPtr<Image> imageForRendering = imageSourceInternal->getSourceImageForCanvas(&status, PreferNoAcceleration, SnapshotReasonCreatePattern);
+    FloatSize defaultObjectSize(width(), height());
+    RefPtr<Image> imageForRendering = imageSourceInternal->getSourceImageForCanvas(&status, PreferNoAcceleration, SnapshotReasonCreatePattern, defaultObjectSize);
 
     switch (status) {
     case NormalSourceImageStatus:
         break;
     case ZeroSizeCanvasSourceImageStatus:
-        exceptionState.throwDOMException(InvalidStateError, String::format("The canvas %s is 0.", imageSourceInternal->elementSize().width() ? "height" : "width"));
+        exceptionState.throwDOMException(InvalidStateError, String::format("The canvas %s is 0.", imageSourceInternal->elementSize(defaultObjectSize).width() ? "height" : "width"));
         return nullptr;
     case UndecodableSourceImageStatus:
         exceptionState.throwDOMException(InvalidStateError, "Source image is in the 'broken' state.");
@@ -1140,9 +1145,12 @@
     return true;
 }
 
-ImageData* BaseRenderingContext2D::createImageData(ImageData* imageData) const
+ImageData* BaseRenderingContext2D::createImageData(ImageData* imageData, ExceptionState &exceptionState) const
 {
-    return ImageData::create(imageData->size());
+    ImageData* result = ImageData::create(imageData->size());
+    if (!result)
+        exceptionState.throwRangeError("Out of memory at ImageData creation");
+    return result;
 }
 
 ImageData* BaseRenderingContext2D::createImageData(double sw, double sh, ExceptionState& exceptionState) const
@@ -1162,7 +1170,10 @@
     if (size.height() < 1)
         size.setHeight(1);
 
-    return ImageData::create(size);
+    ImageData* result = ImageData::create(size);
+    if (!result)
+        exceptionState.throwRangeError("Out of memory at ImageData creation");
+    return result;
 }
 
 ImageData* BaseRenderingContext2D::getImageData(double sx, double sy, double sw, double sh, ExceptionState& exceptionState) const
@@ -1194,12 +1205,18 @@
 
     IntRect imageDataRect = enclosingIntRect(logicalRect);
     ImageBuffer* buffer = imageBuffer();
-    if (!buffer || isContextLost())
-        return ImageData::create(imageDataRect.size());
+    if (!buffer || isContextLost()) {
+        ImageData* result = ImageData::create(imageDataRect.size());
+        if (!result)
+            exceptionState.throwRangeError("Out of memory at ImageData creation");
+        return result;
+    }
 
     WTF::ArrayBufferContents contents;
-    if (!buffer->getImageData(Unmultiplied, imageDataRect, contents))
+    if (!buffer->getImageData(Unmultiplied, imageDataRect, contents)) {
+        exceptionState.throwRangeError("Out of memory at ImageData creation");
         return nullptr;
+    }
 
     RefPtr<DOMArrayBuffer> arrayBuffer = DOMArrayBuffer::create(contents);
     return ImageData::create(
diff --git a/third_party/WebKit/Source/modules/canvas2d/BaseRenderingContext2D.h b/third_party/WebKit/Source/modules/canvas2d/BaseRenderingContext2D.h
index 8021b8e..e9e0b78 100644
--- a/third_party/WebKit/Source/modules/canvas2d/BaseRenderingContext2D.h
+++ b/third_party/WebKit/Source/modules/canvas2d/BaseRenderingContext2D.h
@@ -115,7 +115,7 @@
     CanvasGradient* createRadialGradient(double x0, double y0, double r0, double x1, double y1, double r1, ExceptionState&);
     CanvasPattern* createPattern(const CanvasImageSourceUnion&, const String& repetitionType, ExceptionState&);
 
-    ImageData* createImageData(ImageData*) const;
+    ImageData* createImageData(ImageData*, ExceptionState&) const;
     ImageData* createImageData(double width, double height, ExceptionState&) const;
     ImageData* getImageData(double sx, double sy, double sw, double sh, ExceptionState&) const;
     void putImageData(ImageData*, double dx, double dy, ExceptionState&);
diff --git a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.idl b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.idl
index a2a897c6..997969a 100644
--- a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.idl
+++ b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.idl
@@ -116,7 +116,7 @@
     [RuntimeEnabled=ExperimentalCanvasFeatures] void clearHitRegions();
 
     // pixel manipulation
-    ImageData createImageData(ImageData imagedata);
+    [RaisesException] ImageData createImageData(ImageData imagedata);
     [RaisesException] ImageData createImageData(double sw, double sh);
     [RaisesException] ImageData getImageData(double sx, double sy, double sw, double sh);
     [RaisesException] void putImageData(ImageData imagedata, double dx, double dy);
diff --git a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DAPITest.cpp b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DAPITest.cpp
index ef9e97f..905931f 100644
--- a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DAPITest.cpp
+++ b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DAPITest.cpp
@@ -216,7 +216,8 @@
     // createImageData(imageData) should create a new ImageData of the same size as 'imageData'
     // but filled with transparent black
 
-    ImageData* sameSizeImageData = context2d()->createImageData(imageData);
+    ImageData* sameSizeImageData = context2d()->createImageData(imageData, exceptionState);
+    EXPECT_FALSE(exceptionState.hadException());
     EXPECT_EQ(100, sameSizeImageData->width());
     EXPECT_EQ(50, sameSizeImageData->height());
     EXPECT_EQ(0, sameSizeImageData->data()->data()[32]);
@@ -238,6 +239,26 @@
     EXPECT_EQ((unsigned)800, imgdata4->data()->length());
 }
 
+TEST_F(CanvasRenderingContext2DAPITest, CreateImageDataTooBig)
+{
+    createContext(NonOpaque);
+    TrackExceptionState exceptionState;
+    ImageData* tooBigImageData = context2d()->createImageData(1000000, 1000000, exceptionState);
+    EXPECT_EQ(nullptr, tooBigImageData);
+    EXPECT_TRUE(exceptionState.hadException());
+    EXPECT_EQ(V8RangeError, exceptionState.code());
+}
+
+TEST_F(CanvasRenderingContext2DAPITest, GetImageDataTooBig)
+{
+    createContext(NonOpaque);
+    TrackExceptionState exceptionState;
+    ImageData* imageData = context2d()->getImageData(0, 0, 1000000, 1000000, exceptionState);
+    EXPECT_EQ(nullptr, imageData);
+    EXPECT_TRUE(exceptionState.hadException());
+    EXPECT_EQ(V8RangeError, exceptionState.code());
+}
+
 void resetCanvasForAccessibilityRectTest(HTMLDocument& document)
 {
     document.documentElement()->setInnerHTML(
diff --git a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DTest.cpp b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DTest.cpp
index e6325a9..3ab020a9 100644
--- a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DTest.cpp
+++ b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DTest.cpp
@@ -37,10 +37,10 @@
 public:
     FakeImageSource(IntSize, BitmapOpacity);
 
-    PassRefPtr<Image> getSourceImageForCanvas(SourceImageStatus*, AccelerationHint, SnapshotReason) const override;
+    PassRefPtr<Image> getSourceImageForCanvas(SourceImageStatus*, AccelerationHint, SnapshotReason, const FloatSize&) const override;
 
     bool wouldTaintOrigin(SecurityOrigin* destinationSecurityOrigin) const override { return false; }
-    FloatSize elementSize() const override { return FloatSize(m_size); }
+    FloatSize elementSize(const FloatSize&) const override { return FloatSize(m_size); }
     bool isOpaque() const override { return m_isOpaque; }
 
     ~FakeImageSource() override { }
@@ -61,7 +61,7 @@
     m_image = StaticBitmapImage::create(image);
 }
 
-PassRefPtr<Image> FakeImageSource::getSourceImageForCanvas(SourceImageStatus* status, AccelerationHint, SnapshotReason) const
+PassRefPtr<Image> FakeImageSource::getSourceImageForCanvas(SourceImageStatus* status, AccelerationHint, SnapshotReason, const FloatSize&) const
 {
     if (status)
         *status = NormalSourceImageStatus;
diff --git a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in
index 8a0bcf0..24f228ed 100644
--- a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in
+++ b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in
@@ -199,7 +199,9 @@
 UserSelectAll status=experimental
 WebAnimationsAPI status=experimental
 WebAnimationsSVG status=experimental
-WebBluetooth origin_trial_feature_name=WebBluetooth
+// TODO(https://crbug.com/584113) Enable Web Bluetooth Experiment.
+// WebBluetooth origin_trial_feature_name=WebBluetooth
+WebBluetooth
 WebGLDraftExtensions status=experimental
 WebGLImageChromium
 WebUSB status=experimental
diff --git a/third_party/WebKit/Source/platform/blink_platform.gyp b/third_party/WebKit/Source/platform/blink_platform.gyp
index b1c485e3..8db80e79 100644
--- a/third_party/WebKit/Source/platform/blink_platform.gyp
+++ b/third_party/WebKit/Source/platform/blink_platform.gyp
@@ -133,8 +133,8 @@
       '<(DEPTH)/cc/cc.gyp:cc',
       '<(DEPTH)/device/battery/battery.gyp:device_battery_mojo_bindings',
       '<(DEPTH)/gpu/gpu.gyp:gles2_c_lib',
-      '<(DEPTH)/mojo/mojo_base.gyp:mojo_environment_chromium',
       '<(DEPTH)/mojo/mojo_edk.gyp:mojo_system_impl',
+      '<(DEPTH)/mojo/mojo_public.gyp:mojo_cpp_bindings',
       '<(DEPTH)/skia/skia.gyp:skia',
       '<(DEPTH)/third_party/iccjpeg/iccjpeg.gyp:iccjpeg',
       '<(DEPTH)/third_party/icu/icu.gyp:icui18n',
diff --git a/third_party/WebKit/Source/platform/blink_platform_tests.gyp b/third_party/WebKit/Source/platform/blink_platform_tests.gyp
index 90569f0..7254d69 100644
--- a/third_party/WebKit/Source/platform/blink_platform_tests.gyp
+++ b/third_party/WebKit/Source/platform/blink_platform_tests.gyp
@@ -113,8 +113,8 @@
         'blink_platform.gyp:blink_platform',
         '<(DEPTH)/cc/cc.gyp:cc',
         '<(DEPTH)/device/battery/battery.gyp:device_battery_mojo_bindings',
-        '<(DEPTH)/mojo/mojo_base.gyp:mojo_environment_chromium',
         '<(DEPTH)/mojo/mojo_edk.gyp:mojo_system_impl',
+        '<(DEPTH)/mojo/mojo_public.gyp:mojo_cpp_bindings',
         '<(DEPTH)/testing/gmock.gyp:gmock',
       ],
       'defines': [
diff --git a/third_party/WebKit/Source/platform/graphics/ImageBuffer.cpp b/third_party/WebKit/Source/platform/graphics/ImageBuffer.cpp
index cc0fd7f..8b76f1e 100644
--- a/third_party/WebKit/Source/platform/graphics/ImageBuffer.cpp
+++ b/third_party/WebKit/Source/platform/graphics/ImageBuffer.cpp
@@ -292,7 +292,12 @@
         return false;
 
     if (!isSurfaceValid()) {
-        WTF::ArrayBufferContents result(rect.width() * rect.height(), 4, WTF::ArrayBufferContents::NotShared, WTF::ArrayBufferContents::ZeroInitialize);
+        size_t allocSizeInBytes = rect.width() * rect.height() * 4;
+        void* data;
+        WTF::ArrayBufferContents::allocateMemoryOrNull(allocSizeInBytes, WTF::ArrayBufferContents::ZeroInitialize, data);
+        if (!data)
+            return false;
+        WTF::ArrayBufferContents result(data, allocSizeInBytes, WTF::ArrayBufferContents::NotShared);
         result.transfer(contents);
         return true;
     }
@@ -308,12 +313,13 @@
         || rect.y() < 0
         || rect.maxX() > m_surface->size().width()
         || rect.maxY() > m_surface->size().height();
-    WTF::ArrayBufferContents result(
-        rect.width() * rect.height(), 4,
-        WTF::ArrayBufferContents::NotShared,
-        mayHaveStrayArea
-        ? WTF::ArrayBufferContents::ZeroInitialize
-        : WTF::ArrayBufferContents::DontInitialize);
+    size_t allocSizeInBytes = rect.width() * rect.height() * 4;
+    void* data;
+    WTF::ArrayBufferContents::InitializationPolicy initializationPolicy = mayHaveStrayArea ? WTF::ArrayBufferContents::ZeroInitialize : WTF::ArrayBufferContents::DontInitialize;
+    WTF::ArrayBufferContents::allocateMemoryOrNull(allocSizeInBytes, initializationPolicy, data);
+    if (!data)
+        return false;
+    WTF::ArrayBufferContents result(data, allocSizeInBytes, WTF::ArrayBufferContents::NotShared);
 
     SkAlphaType alphaType = (multiplied == Premultiplied) ? kPremul_SkAlphaType : kUnpremul_SkAlphaType;
     SkImageInfo info = SkImageInfo::Make(rect.width(), rect.height(), kRGBA_8888_SkColorType, alphaType);
diff --git a/third_party/WebKit/Source/platform/scroll/ProgrammaticScrollAnimator.h b/third_party/WebKit/Source/platform/scroll/ProgrammaticScrollAnimator.h
index 2e047b6..601ccc8e 100644
--- a/third_party/WebKit/Source/platform/scroll/ProgrammaticScrollAnimator.h
+++ b/third_party/WebKit/Source/platform/scroll/ProgrammaticScrollAnimator.h
@@ -35,6 +35,7 @@
     // ScrollAnimatorCompositorCoordinator implementation.
     void resetAnimationState() override;
     void cancelAnimation() override;
+    void takeoverCompositorAnimation() override { };
     ScrollableArea* scrollableArea() const override { return m_scrollableArea; }
     void tickAnimation(double monotonicTime) override;
     void updateCompositorAnimations() override;
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollAnimator.cpp b/third_party/WebKit/Source/platform/scroll/ScrollAnimator.cpp
index b5e80716..21ffb6eb 100644
--- a/third_party/WebKit/Source/platform/scroll/ScrollAnimator.cpp
+++ b/third_party/WebKit/Source/platform/scroll/ScrollAnimator.cpp
@@ -143,18 +143,18 @@
         m_targetOffset = targetPos;
         ASSERT(m_runState == RunState::RunningOnMainThread
             || m_runState == RunState::RunningOnCompositor
-            || m_runState == RunState::RunningOnCompositorButNeedsUpdate);
-
-        if (m_runState == RunState::RunningOnCompositor
-            || m_runState == RunState::RunningOnCompositorButNeedsUpdate) {
-            if (registerAndScheduleAnimation())
-                m_runState = RunState::RunningOnCompositorButNeedsUpdate;
-            return true;
-        }
+            || m_runState == RunState::RunningOnCompositorButNeedsUpdate
+            || m_runState == RunState::RunningOnCompositorButNeedsTakeover);
 
         // Running on the main thread, simply update the target offset instead
         // of sending to the compositor.
-        m_animationCurve->updateTarget(m_timeFunction() - m_startTime, targetPos);
+        if (m_runState == RunState::RunningOnMainThread) {
+            m_animationCurve->updateTarget(m_timeFunction() - m_startTime, targetPos);
+            return true;
+        }
+
+        if (registerAndScheduleAnimation())
+            m_runState = RunState::RunningOnCompositorButNeedsUpdate;
         return true;
     }
 
@@ -212,6 +212,36 @@
     resetAnimationState();
 }
 
+bool ScrollAnimator::sendAnimationToCompositor()
+{
+    if (m_scrollableArea->shouldScrollOnMainThread())
+        return false;
+
+    OwnPtr<CompositorAnimation> animation = adoptPtr(
+        CompositorFactory::current().createAnimation(
+            *m_animationCurve,
+            CompositorTargetProperty::SCROLL_OFFSET));
+    // Being here means that either there is an animation that needs
+    // to be sent to the compositor, or an animation that needs to
+    // be updated (a new scroll event before the previous animation
+    // is finished). In either case, the start time is when the
+    // first animation was initiated. This re-targets the animation
+    // using the current time on main thread.
+    animation->setStartTime(m_startTime);
+
+    int animationId = animation->id();
+    int animationGroupId = animation->group();
+
+    bool sentToCompositor = addAnimation(animation.release());
+    if (sentToCompositor) {
+        m_runState = RunState::RunningOnCompositor;
+        m_compositorAnimationId = animationId;
+        m_compositorAnimationGroupId = animationGroupId;
+    }
+
+    return sentToCompositor;
+}
+
 void ScrollAnimator::updateCompositorAnimations()
 {
     if (m_runState == RunState::PostAnimationCleanup) {
@@ -226,9 +256,16 @@
         // compositor animation that needs to be removed here before the new
         // animation is added below.
         ASSERT(m_runState == RunState::WaitingToCancelOnCompositor
-            || m_runState == RunState::WaitingToSendToCompositor);
+            || m_runState == RunState::WaitingToSendToCompositor
+            || m_runState == RunState::RunningOnCompositorButNeedsTakeover);
 
-        abortAnimation();
+        if (m_runState == RunState::RunningOnCompositorButNeedsTakeover) {
+            // The animation is already aborted when the call to
+            // ::takeoverCompositorAnimation is made.
+            m_runState = RunState::WaitingToSendToCompositor;
+        } else {
+            abortAnimation();
+        }
 
         m_compositorAnimationId = 0;
         m_compositorAnimationGroupId = 0;
@@ -263,32 +300,8 @@
             m_animationCurve->setInitialValue(currentPosition());
         }
 
-        bool sentToCompositor = false;
-        if (!m_scrollableArea->shouldScrollOnMainThread()) {
-            OwnPtr<CompositorAnimation> animation = adoptPtr(
-                CompositorFactory::current().createAnimation(
-                    *m_animationCurve,
-                    CompositorTargetProperty::SCROLL_OFFSET));
-            // Being here means that either there is an animation that needs
-            // to be sent to the compositor, or an animation that needs to
-            // be updated (a new scroll event before the previous animation
-            // is finished). In either case, the start time is when the
-            // first animation was initiated. This re-targets the animation
-            // using the current time on main thread.
-            animation->setStartTime(m_startTime);
-
-            int animationId = animation->id();
-            int animationGroupId = animation->group();
-
-            sentToCompositor = addAnimation(animation.release());
-            if (sentToCompositor) {
-                m_runState = RunState::RunningOnCompositor;
-                m_compositorAnimationId = animationId;
-                m_compositorAnimationGroupId = animationGroupId;
-            }
-        }
-
         bool runningOnMainThread = false;
+        bool sentToCompositor = sendAnimationToCompositor();
         if (!sentToCompositor) {
             runningOnMainThread = registerAndScheduleAnimation();
             if (runningOnMainThread)
@@ -358,6 +371,15 @@
     ScrollAnimatorCompositorCoordinator::cancelAnimation();
 }
 
+void ScrollAnimator::takeoverCompositorAnimation()
+{
+    if (m_runState == RunState::RunningOnCompositor
+        || m_runState ==  RunState::RunningOnCompositorButNeedsUpdate)
+        removeMainThreadScrollingReason();
+
+    ScrollAnimatorCompositorCoordinator::takeoverCompositorAnimation();
+}
+
 void ScrollAnimator::layerForCompositedScrollingDidChange(
     CompositorAnimationTimeline* timeline)
 {
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollAnimator.h b/third_party/WebKit/Source/platform/scroll/ScrollAnimator.h
index a9e2684..ea8676b 100644
--- a/third_party/WebKit/Source/platform/scroll/ScrollAnimator.h
+++ b/third_party/WebKit/Source/platform/scroll/ScrollAnimator.h
@@ -43,7 +43,7 @@
 class ScrollAnimatorTest;
 class CompositorAnimationTimeline;
 
-class PLATFORM_EXPORT ScrollAnimator final : public ScrollAnimatorBase {
+class PLATFORM_EXPORT ScrollAnimator : public ScrollAnimatorBase {
 public:
     explicit ScrollAnimator(ScrollableArea*, WTF::TimeFunction = WTF::monotonicallyIncreasingTime);
     ~ScrollAnimator() override;
@@ -58,6 +58,7 @@
     // ScrollAnimatorCompositorCoordinator implementation.
     void tickAnimation(double monotonicTime) override;
     void cancelAnimation() override;
+    void takeoverCompositorAnimation() override;
     void resetAnimationState() override;
     void updateCompositorAnimations() override;
     void notifyCompositorAnimationFinished(int groupId) override;
@@ -67,6 +68,9 @@
     DECLARE_VIRTUAL_TRACE();
 
 protected:
+    // Returns whether or not the animation was sent to the compositor.
+    virtual bool sendAnimationToCompositor();
+
     void notifyAnimationTakeover(
         double monotonicTime,
         double animationStartTime,
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollAnimatorBase.h b/third_party/WebKit/Source/platform/scroll/ScrollAnimatorBase.h
index d92ffac..39da482 100644
--- a/third_party/WebKit/Source/platform/scroll/ScrollAnimatorBase.h
+++ b/third_party/WebKit/Source/platform/scroll/ScrollAnimatorBase.h
@@ -81,6 +81,7 @@
     ScrollableArea* scrollableArea() const override { return m_scrollableArea; }
     void tickAnimation(double monotonicTime) override { };
     void cancelAnimation() override { }
+    void takeoverCompositorAnimation() override { }
     void updateCompositorAnimations() override { };
     void notifyCompositorAnimationFinished(int groupId) override { };
     void notifyCompositorAnimationAborted(int groupId) override { };
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollAnimatorCompositorCoordinator.cpp b/third_party/WebKit/Source/platform/scroll/ScrollAnimatorCompositorCoordinator.cpp
index a7e33e2..294fcbe 100644
--- a/third_party/WebKit/Source/platform/scroll/ScrollAnimatorCompositorCoordinator.cpp
+++ b/third_party/WebKit/Source/platform/scroll/ScrollAnimatorCompositorCoordinator.cpp
@@ -60,6 +60,7 @@
     case RunState::WaitingToSendToCompositor:
     case RunState::RunningOnMainThread:
     case RunState::RunningOnCompositorButNeedsUpdate:
+    case RunState::RunningOnCompositorButNeedsTakeover:
     case RunState::WaitingToCancelOnCompositor:
         return true;
     }
@@ -96,6 +97,7 @@
     case RunState::WaitingToCancelOnCompositor:
     case RunState::PostAnimationCleanup:
         break;
+    case RunState::RunningOnCompositorButNeedsTakeover:
     case RunState::WaitingToSendToCompositor:
         if (m_compositorAnimationId) {
             // We still have a previous animation running on the compositor.
@@ -116,6 +118,30 @@
     }
 }
 
+void ScrollAnimatorCompositorCoordinator::takeoverCompositorAnimation()
+{
+    switch (m_runState) {
+    case RunState::Idle:
+    case RunState::WaitingToCancelOnCompositor:
+    case RunState::PostAnimationCleanup:
+    case RunState::RunningOnCompositorButNeedsTakeover:
+    case RunState::WaitingToSendToCompositor:
+    case RunState::RunningOnMainThread:
+        break;
+    case RunState::RunningOnCompositorButNeedsUpdate:
+    case RunState::RunningOnCompositor:
+        // We call abortAnimation that makes changes to the animation running on
+        // the compositor. Thus, this function should only be called when in
+        // CompositingClean state.
+        abortAnimation();
+
+        m_runState = RunState::RunningOnCompositorButNeedsTakeover;
+
+        // Get serviced the next time compositor updates are allowed.
+        scrollableArea()->registerForAnimation();
+    }
+}
+
 void ScrollAnimatorCompositorCoordinator::compositorAnimationFinished(
     int groupId)
 {
@@ -135,6 +161,7 @@
         break;
     case RunState::RunningOnCompositor:
     case RunState::RunningOnCompositorButNeedsUpdate:
+    case RunState::RunningOnCompositorButNeedsTakeover:
     case RunState::WaitingToCancelOnCompositor:
         m_runState = RunState::PostAnimationCleanup;
         // Get serviced the next time compositor updates are allowed.
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollAnimatorCompositorCoordinator.h b/third_party/WebKit/Source/platform/scroll/ScrollAnimatorCompositorCoordinator.h
index f962bf0..49daf59c 100644
--- a/third_party/WebKit/Source/platform/scroll/ScrollAnimatorCompositorCoordinator.h
+++ b/third_party/WebKit/Source/platform/scroll/ScrollAnimatorCompositorCoordinator.h
@@ -36,6 +36,10 @@
 
     virtual void resetAnimationState();
     virtual void cancelAnimation();
+    // Aborts the currently running scroll offset animation on the compositor
+    // and continues it on the main thread. This should only be called when in
+    // DocumentLifecycle::LifecycleState::CompositingClean state.
+    virtual void takeoverCompositorAnimation();
 
     virtual ScrollableArea* scrollableArea() const = 0;
     virtual void tickAnimation(double monotonicTime) = 0;
@@ -51,7 +55,7 @@
 
     bool addAnimation(PassOwnPtr<CompositorAnimation>);
     void removeAnimation();
-    void abortAnimation();
+    virtual void abortAnimation();
 
     void compositorAnimationFinished(int groupId);
     // Returns true if the compositor player was attached to a new layer.
@@ -71,6 +75,7 @@
 
     friend class Internals;
     FRIEND_TEST_ALL_PREFIXES(ScrollAnimatorTest, MainThreadStates);
+    FRIEND_TEST_ALL_PREFIXES(ScrollAnimatorTest, AnimatedScrollTakeover);
 
     enum class RunState {
         // No animation.
@@ -97,7 +102,12 @@
         // Finished an animation that was running on the main thread or the
         // compositor thread. When in this state, post animation cleanup can
         // be performed.
-        PostAnimationCleanup
+        PostAnimationCleanup,
+
+        // Running an animation on the compositor but need to continue it
+        // on the main thread. This could happen if a main thread scrolling
+        // reason is added while animating the scroll offset.
+        RunningOnCompositorButNeedsTakeover,
     };
 
     OwnPtr<CompositorAnimationPlayer> m_compositorPlayer;
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollAnimatorTest.cpp b/third_party/WebKit/Source/platform/scroll/ScrollAnimatorTest.cpp
index 56f4bd2..d3f67d8d 100644
--- a/third_party/WebKit/Source/platform/scroll/ScrollAnimatorTest.cpp
+++ b/third_party/WebKit/Source/platform/scroll/ScrollAnimatorTest.cpp
@@ -94,6 +94,34 @@
     bool m_scrollAnimatorEnabled;
 };
 
+class TestScrollAnimator : public ScrollAnimator {
+public:
+    TestScrollAnimator(ScrollableArea* scrollableArea, WTF::TimeFunction timingFunction)
+        : ScrollAnimator(scrollableArea, timingFunction) {};
+    ~TestScrollAnimator() override {};
+
+    void setShouldSendToCompositor(bool send)
+    {
+        m_shouldSendToCompositor = send;
+    }
+
+    bool sendAnimationToCompositor() override
+    {
+        if (m_shouldSendToCompositor) {
+            m_runState = ScrollAnimatorCompositorCoordinator::RunState::RunningOnCompositor;
+            m_compositorAnimationId = 1;
+            return true;
+        }
+        return false;
+    }
+
+protected:
+    void abortAnimation() override {}
+
+private:
+    bool m_shouldSendToCompositor = false;
+};
+
 } // namespace
 
 static void reset(ScrollAnimator& scrollAnimator)
@@ -276,6 +304,59 @@
     reset(*scrollAnimator);
 }
 
+// Test that a smooth scroll offset animation running on the compositor is
+// completed on the main thread.
+TEST(ScrollAnimatorTest, AnimatedScrollTakeover)
+{
+    OwnPtrWillBeRawPtr<MockScrollableArea> scrollableArea =
+        MockScrollableArea::create(true);
+    OwnPtrWillBeRawPtr<TestScrollAnimator> scrollAnimator = adoptPtrWillBeNoop(
+        new TestScrollAnimator(scrollableArea.get(), getMockedTime));
+
+    EXPECT_CALL(*scrollableArea, minimumScrollPosition()).Times(AtLeast(1))
+        .WillRepeatedly(Return(IntPoint()));
+    EXPECT_CALL(*scrollableArea, maximumScrollPosition()).Times(AtLeast(1))
+        .WillRepeatedly(Return(IntPoint(1000, 1000)));
+    EXPECT_CALL(*scrollableArea, setScrollOffset(_, _)).Times(2);
+    // Called from userScroll, updateCompositorAnimations, then
+    // takeoverCompositorAnimation (to re-register after RunningOnCompositor).
+    EXPECT_CALL(*scrollableArea, registerForAnimation()).Times(3);
+    EXPECT_CALL(*scrollableArea, scheduleAnimation()).Times(AtLeast(1))
+        .WillRepeatedly(Return(true));
+
+    EXPECT_FALSE(scrollAnimator->hasAnimationThatRequiresService());
+
+    // Smooth scroll.
+    ScrollResult result = scrollAnimator->userScroll(ScrollByLine, FloatSize(100, 0));
+    EXPECT_TRUE(scrollAnimator->hasAnimationThatRequiresService());
+    EXPECT_TRUE(result.didScrollX);
+    EXPECT_FLOAT_EQ(0.0, result.unusedScrollDeltaX);
+    EXPECT_TRUE(scrollAnimator->hasRunningAnimation());
+
+    // Update compositor animation.
+    gMockedTime += 0.05;
+    scrollAnimator->setShouldSendToCompositor(true);
+    scrollAnimator->updateCompositorAnimations();
+    EXPECT_EQ(scrollAnimator->m_runState,
+        ScrollAnimatorCompositorCoordinator::RunState::RunningOnCompositor);
+
+    // Takeover.
+    scrollAnimator->takeoverCompositorAnimation();
+    EXPECT_EQ(scrollAnimator->m_runState,
+        ScrollAnimatorCompositorCoordinator::RunState::RunningOnCompositorButNeedsTakeover);
+
+    // Animation should now be running on the main thread.
+    scrollAnimator->setShouldSendToCompositor(false);
+    scrollAnimator->updateCompositorAnimations();
+    EXPECT_EQ(scrollAnimator->m_runState,
+        ScrollAnimatorCompositorCoordinator::RunState::RunningOnMainThread);
+    scrollAnimator->tickAnimation(getMockedTime());
+    EXPECT_NE(100, scrollAnimator->currentPosition().x());
+    EXPECT_NE(0, scrollAnimator->currentPosition().x());
+    EXPECT_EQ(0, scrollAnimator->currentPosition().y());
+    reset(*scrollAnimator);
+}
+
 TEST(ScrollAnimatorTest, Disabled)
 {
     OwnPtrWillBeRawPtr<MockScrollableArea> scrollableArea = MockScrollableArea::create(false);
diff --git a/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp b/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp
index 17d5bfc..a3fc227 100644
--- a/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp
+++ b/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp
@@ -1537,7 +1537,8 @@
 
         bool enableWebBluetooth = RuntimeEnabledFeatures::webBluetoothEnabled();
 #if OS(CHROMEOS) || OS(ANDROID)
-        enableWebBluetooth = true;
+// TODO(https://crbug.com/584113) Enable Web Bluetooth Experiment.
+// enableWebBluetooth = true;
 #endif
 
         if (enableWebBluetooth) {
diff --git a/third_party/WebKit/Source/web/tests/WebFrameTest.cpp b/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
index b9822d6..a687a86 100644
--- a/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
+++ b/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
@@ -313,9 +313,9 @@
 // Flakily failing on Mac ASAN.
 // https://crbug.com/592771
 #if OS(MACOSX) && defined(ADDRESS_SANITIZER)
-#define MAYBE(test) DISABLED_##test
+#define MAYBE_TEST_P(fixture, test) TEST_P(fixture, DISABLED_##test)
 #else
-#define MAYBE(test) test
+#define MAYBE_TEST_P(fixture, test) TEST_P(fixture, test)
 #endif
 
 INSTANTIATE_TEST_CASE_P(All, ParameterizedWebFrameTest, ::testing::Values(
@@ -1386,7 +1386,7 @@
     EXPECT_EQ(enforcedPageScaleFactor, webViewHelper.webView()->pageScaleFactor());
 }
 
-TEST_P(ParameterizedWebFrameTest, MAYBE(SmallPermanentInitialPageScaleFactorIsClobbered))
+MAYBE_TEST_P(ParameterizedWebFrameTest, SmallPermanentInitialPageScaleFactorIsClobbered)
 {
     const char* pages[] = {
         // These pages trigger the clobbering condition. There must be a matching item in "pageScaleFactors" array.
@@ -1638,7 +1638,7 @@
 }
 
 
-TEST_P(ParameterizedWebFrameTest, MAYBE(SetForceZeroLayoutHeightWorksAcrossNavigations))
+MAYBE_TEST_P(ParameterizedWebFrameTest, SetForceZeroLayoutHeightWorksAcrossNavigations)
 {
     registerMockedHttpURLLoad("200-by-300.html");
     registerMockedHttpURLLoad("large-div.html");
@@ -1680,7 +1680,7 @@
     EXPECT_EQ(0, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->layoutSize().height());
 }
 
-TEST_P(ParameterizedWebFrameTest, MAYBE(WideViewportAndWideContentWithInitialScale))
+MAYBE_TEST_P(ParameterizedWebFrameTest, WideViewportAndWideContentWithInitialScale)
 {
     registerMockedHttpURLLoad("wide_document_width_viewport.html");
     registerMockedHttpURLLoad("white-1x1.png");
@@ -1706,7 +1706,7 @@
     EXPECT_EQ(minimumPageScaleFactor, webViewHelper.webViewImpl()->minimumPageScaleFactor());
 }
 
-TEST_P(ParameterizedWebFrameTest, MAYBE(WideViewportQuirkClobbersHeight))
+MAYBE_TEST_P(ParameterizedWebFrameTest, WideViewportQuirkClobbersHeight)
 {
     registerMockedHttpURLLoad("viewport-height-1000.html");
 
@@ -1729,7 +1729,7 @@
     EXPECT_EQ(1, webViewHelper.webView()->pageScaleFactor());
 }
 
-TEST_P(ParameterizedWebFrameTest, MAYBE(LayoutSize320Quirk))
+MAYBE_TEST_P(ParameterizedWebFrameTest, LayoutSize320Quirk)
 {
     registerMockedHttpURLLoad("viewport/viewport-30.html");
 
@@ -2028,7 +2028,7 @@
     EXPECT_EQ(980, webViewHelper.webViewImpl()->mainFrameImpl()->frameView()->contentsSize().width());
 }
 
-TEST_P(ParameterizedWebFrameTest, MAYBE(targetDensityDpiHigh))
+MAYBE_TEST_P(ParameterizedWebFrameTest, targetDensityDpiHigh)
 {
     registerMockedHttpURLLoad("viewport-target-densitydpi-high.html");
 
@@ -2059,7 +2059,7 @@
     }
 }
 
-TEST_P(ParameterizedWebFrameTest, MAYBE(targetDensityDpiDevice))
+MAYBE_TEST_P(ParameterizedWebFrameTest, targetDensityDpiDevice)
 {
     registerMockedHttpURLLoad("viewport-target-densitydpi-device.html");
 
@@ -2084,7 +2084,7 @@
     }
 }
 
-TEST_P(ParameterizedWebFrameTest, MAYBE(targetDensityDpiDeviceAndFixedWidth))
+MAYBE_TEST_P(ParameterizedWebFrameTest, targetDensityDpiDeviceAndFixedWidth)
 {
     registerMockedHttpURLLoad("viewport-target-densitydpi-device-and-fixed-width.html");
 
@@ -2890,7 +2890,7 @@
     EXPECT_RECT_EQ(rectRightBottom, blockBound);
 }
 
-TEST_P(ParameterizedWebFrameTest, MAYBE(DivMultipleTargetZoomMultipleDivsTest))
+MAYBE_TEST_P(ParameterizedWebFrameTest, DivMultipleTargetZoomMultipleDivsTest)
 {
     registerMockedHttpURLLoad("get_multiple_divs_for_auto_zoom_test.html");
 
@@ -3166,7 +3166,7 @@
     EXPECT_FALSE(needAnimation);
 }
 
-TEST_P(ParameterizedWebFrameTest, MAYBE(CharacterIndexAtPointWithPinchZoom))
+MAYBE_TEST_P(ParameterizedWebFrameTest, CharacterIndexAtPointWithPinchZoom)
 {
     registerMockedHttpURLLoad("sometext.html");
 
@@ -4415,7 +4415,7 @@
     // EXPECT_EQ("Editable 1. Editable 2. ]", selectionAsString(frame));
 }
 
-TEST_P(ParameterizedWebFrameTest, MAYBE(MoveRangeSelectionExtent))
+MAYBE_TEST_P(ParameterizedWebFrameTest, MoveRangeSelectionExtent)
 {
     WebLocalFrameImpl* frame;
     WebRect startWebRect;
@@ -4449,7 +4449,7 @@
     EXPECT_EQ("", selectionAsString(frame));
 }
 
-TEST_P(ParameterizedWebFrameTest, MAYBE(MoveRangeSelectionExtentCannotCollapse))
+MAYBE_TEST_P(ParameterizedWebFrameTest, MoveRangeSelectionExtentCannotCollapse)
 {
     WebLocalFrameImpl* frame;
     WebRect startWebRect;
@@ -4474,7 +4474,7 @@
     EXPECT_EQ("This text is initially selected.", selectionAsString(frame));
 }
 
-TEST_P(ParameterizedWebFrameTest, MAYBE(MoveRangeSelectionExtentScollsInputField))
+MAYBE_TEST_P(ParameterizedWebFrameTest, MoveRangeSelectionExtentScollsInputField)
 {
     WebLocalFrameImpl* frame;
     WebRect startWebRect;
@@ -4836,7 +4836,7 @@
     return event;
 }
 
-TEST_P(ParameterizedWebFrameTest, MAYBE(DisambiguationPopup))
+MAYBE_TEST_P(ParameterizedWebFrameTest, DisambiguationPopup)
 {
     const std::string htmlFile = "disambiguation_popup.html";
     registerMockedHttpURLLoad(htmlFile);
@@ -4890,7 +4890,7 @@
     }
 }
 
-TEST_P(ParameterizedWebFrameTest, MAYBE(DisambiguationPopupNoContainer))
+MAYBE_TEST_P(ParameterizedWebFrameTest, DisambiguationPopupNoContainer)
 {
     registerMockedHttpURLLoad("disambiguation_popup_no_container.html");
 
@@ -4907,7 +4907,7 @@
     EXPECT_FALSE(client.triggered());
 }
 
-TEST_P(ParameterizedWebFrameTest, MAYBE(DisambiguationPopupMobileSite))
+MAYBE_TEST_P(ParameterizedWebFrameTest, DisambiguationPopupMobileSite)
 {
     const std::string htmlFile = "disambiguation_popup_mobile_site.html";
     registerMockedHttpURLLoad(htmlFile);
@@ -4941,7 +4941,7 @@
     }
 }
 
-TEST_P(ParameterizedWebFrameTest, MAYBE(DisambiguationPopupViewportSite))
+MAYBE_TEST_P(ParameterizedWebFrameTest, DisambiguationPopupViewportSite)
 {
     const std::string htmlFile = "disambiguation_popup_viewport_site.html";
     registerMockedHttpURLLoad(htmlFile);
@@ -5025,7 +5025,7 @@
     EXPECT_FALSE(client.triggered());
 }
 
-TEST_P(ParameterizedWebFrameTest, MAYBE(DisambiguationPopupBlacklist))
+MAYBE_TEST_P(ParameterizedWebFrameTest, DisambiguationPopupBlacklist)
 {
     const unsigned viewportWidth = 500;
     const unsigned viewportHeight = 1000;
@@ -5057,7 +5057,7 @@
     EXPECT_FALSE(client.triggered());
 }
 
-TEST_P(ParameterizedWebFrameTest, MAYBE(DisambiguationPopupPageScale))
+MAYBE_TEST_P(ParameterizedWebFrameTest, DisambiguationPopupPageScale)
 {
     registerMockedHttpURLLoad("disambiguation_popup_page_scale.html");
 
@@ -6414,7 +6414,7 @@
     EXPECT_EQ(500, leftRightFixed->offsetWidth());
 }
 
-TEST_P(ParameterizedWebFrameTest, MAYBE(FrameViewMoveWithSetFrameRect))
+MAYBE_TEST_P(ParameterizedWebFrameTest, FrameViewMoveWithSetFrameRect)
 {
     FrameTestHelpers::WebViewHelper webViewHelper(this);
     webViewHelper.initializeAndLoad("about:blank");
@@ -6617,7 +6617,7 @@
     ASSERT_TRUE(webScrollLayer->userScrollableVertical());
 }
 
-TEST_P(ParameterizedWebFrameTest, MAYBE(FullscreenSubframe))
+MAYBE_TEST_P(ParameterizedWebFrameTest, FullscreenSubframe)
 {
     FakeCompositingWebViewClient client;
     registerMockedHttpURLLoad("fullscreen_iframe.html");
@@ -6738,7 +6738,7 @@
     EXPECT_FLOAT_EQ(5.0, webViewImpl->maximumPageScaleFactor());
 }
 
-TEST_P(ParameterizedWebFrameTest, MAYBE(LayoutBlockPercentHeightDescendants))
+MAYBE_TEST_P(ParameterizedWebFrameTest, LayoutBlockPercentHeightDescendants)
 {
     registerMockedHttpURLLoad("percent-height-descendants.html");
     FrameTestHelpers::WebViewHelper webViewHelper(this);
diff --git a/third_party/WebKit/Source/wtf/HashTable.h b/third_party/WebKit/Source/wtf/HashTable.h
index 5b6edd2..c6ac0bda 100644
--- a/third_party/WebKit/Source/wtf/HashTable.h
+++ b/third_party/WebKit/Source/wtf/HashTable.h
@@ -1276,16 +1276,18 @@
 template <typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
 struct WeakProcessingHashTableHelper<WeakHandlingInCollections, Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> {
     STATIC_ONLY(WeakProcessingHashTableHelper);
+
+    using HashTableType = HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>;
+    using ValueType = typename HashTableType::ValueType;
+
     // Used for purely weak and for weak-and-strong tables (ephemerons).
     static void process(typename Allocator::Visitor* visitor, void* closure)
     {
-        typedef HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> HashTableType;
         HashTableType* table = reinterpret_cast<HashTableType*>(closure);
         if (!table->m_table)
             return;
         // Now perform weak processing (this is a no-op if the backing was
         // accessible through an iterator and was already marked strongly).
-        typedef typename HashTableType::ValueType ValueType;
         for (ValueType* element = table->m_table + table->m_tableSize - 1; element >= table->m_table; element--) {
             if (!HashTableType::isEmptyOrDeletedBucket(*element)) {
                 // At this stage calling trace can make no difference
@@ -1310,13 +1312,11 @@
     // Called repeatedly for tables that have both weak and strong pointers.
     static void ephemeronIteration(typename Allocator::Visitor* visitor, void* closure)
     {
-        typedef HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> HashTableType;
         HashTableType* table = reinterpret_cast<HashTableType*>(closure);
         ASSERT(table->m_table);
         // Check the hash table for elements that we now know will not be
         // removed by weak processing. Those elements need to have their strong
         // pointers traced.
-        typedef typename HashTableType::ValueType ValueType;
         for (ValueType* element = table->m_table + table->m_tableSize - 1; element >= table->m_table; element--) {
             if (!HashTableType::isEmptyOrDeletedBucket(*element))
                 TraceInCollectionTrait<WeakHandlingInCollections, WeakPointersActWeak, ValueType, Traits>::trace(visitor, *element);
@@ -1328,7 +1328,6 @@
     // is resumed.
     static void ephemeronIterationDone(typename Allocator::Visitor* visitor, void* closure)
     {
-        typedef HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> HashTableType;
         HashTableType* table = reinterpret_cast<HashTableType*>(closure);
         ASSERT(Allocator::weakTableRegistered(visitor, table));
         table->clearEnqueued();
@@ -1366,31 +1365,31 @@
         // cases). However, it shouldn't cause any issue.
         Allocator::registerWeakMembers(visitor, this, m_table, WeakProcessingHashTableHelper<Traits::weakHandlingFlag, Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::process);
     }
-    if (NeedsTracingTrait<Traits>::value) {
-        if (Traits::weakHandlingFlag == WeakHandlingInCollections) {
-            // If we have both strong and weak pointers in the collection then
-            // we queue up the collection for fixed point iteration a la
-            // Ephemerons:
-            // http://dl.acm.org/citation.cfm?doid=263698.263733 - see also
-            // http://www.jucs.org/jucs_14_21/eliminating_cycles_in_weak
-            ASSERT(!enqueued() || Allocator::weakTableRegistered(visitor, this));
-            if (!enqueued()) {
-                Allocator::registerWeakTable(visitor, this,
-                    WeakProcessingHashTableHelper<Traits::weakHandlingFlag, Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::ephemeronIteration,
-                    WeakProcessingHashTableHelper<Traits::weakHandlingFlag, Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::ephemeronIterationDone);
-                setEnqueued();
-            }
-            // We don't need to trace the elements here, since registering as a
-            // weak table above will cause them to be traced (perhaps several
-            // times). It's better to wait until everything else is traced
-            // before tracing the elements for the first time; this may reduce
-            // (by one) the number of iterations needed to get to a fixed point.
-            return;
+    if (!NeedsTracingTrait<Traits>::value)
+        return;
+    if (Traits::weakHandlingFlag == WeakHandlingInCollections) {
+        // If we have both strong and weak pointers in the collection then
+        // we queue up the collection for fixed point iteration a la
+        // Ephemerons:
+        // http://dl.acm.org/citation.cfm?doid=263698.263733 - see also
+        // http://www.jucs.org/jucs_14_21/eliminating_cycles_in_weak
+        ASSERT(!enqueued() || Allocator::weakTableRegistered(visitor, this));
+        if (!enqueued()) {
+            Allocator::registerWeakTable(visitor, this,
+                WeakProcessingHashTableHelper<Traits::weakHandlingFlag, Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::ephemeronIteration,
+                WeakProcessingHashTableHelper<Traits::weakHandlingFlag, Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::ephemeronIterationDone);
+            setEnqueued();
         }
-        for (ValueType* element = m_table + m_tableSize - 1; element >= m_table; element--) {
-            if (!isEmptyOrDeletedBucket(*element))
-                Allocator::template trace<VisitorDispatcher, ValueType, Traits>(visitor, *element);
-        }
+        // We don't need to trace the elements here, since registering as a
+        // weak table above will cause them to be traced (perhaps several
+        // times). It's better to wait until everything else is traced
+        // before tracing the elements for the first time; this may reduce
+        // (by one) the number of iterations needed to get to a fixed point.
+        return;
+    }
+    for (ValueType* element = m_table + m_tableSize - 1; element >= m_table; element--) {
+        if (!isEmptyOrDeletedBucket(*element))
+            Allocator::template trace<VisitorDispatcher, ValueType, Traits>(visitor, *element);
     }
 }
 
diff --git a/third_party/blimp_fonts/.gitignore b/third_party/blimp_fonts/.gitignore
deleted file mode 100644
index 70994af4..0000000
--- a/third_party/blimp_fonts/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-*.otf
-*.ttf
diff --git a/third_party/blimp_fonts/AndroidClock.ttf.sha1 b/third_party/blimp_fonts/AndroidClock.ttf.sha1
deleted file mode 100644
index ab7fba0..0000000
--- a/third_party/blimp_fonts/AndroidClock.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-c2a20ced561bb57426484d8de4136817b4edcdfb
\ No newline at end of file
diff --git a/third_party/blimp_fonts/AndroidClock_Highlight.ttf.sha1 b/third_party/blimp_fonts/AndroidClock_Highlight.ttf.sha1
deleted file mode 100644
index 4abd6d36..0000000
--- a/third_party/blimp_fonts/AndroidClock_Highlight.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-6a7bba11c859c6698addcab7052c257caa762774
\ No newline at end of file
diff --git a/third_party/blimp_fonts/AndroidClock_Solid.ttf.sha1 b/third_party/blimp_fonts/AndroidClock_Solid.ttf.sha1
deleted file mode 100644
index 4abd6d36..0000000
--- a/third_party/blimp_fonts/AndroidClock_Solid.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-6a7bba11c859c6698addcab7052c257caa762774
\ No newline at end of file
diff --git a/third_party/blimp_fonts/BUILD.gn b/third_party/blimp_fonts/BUILD.gn
deleted file mode 100644
index 0d3154f..0000000
--- a/third_party/blimp_fonts/BUILD.gn
+++ /dev/null
@@ -1,217 +0,0 @@
-# Copyright 2016 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-copy("blimp_fonts") {
-  sources = [
-    "AndroidClock.ttf",
-    "AndroidClock_Highlight.ttf",
-    "AndroidClock_Solid.ttf",
-    "CarroisGothicSC-Regular.ttf",
-    "Clockopia.ttf",
-    "ComingSoon.ttf",
-    "CutiveMono.ttf",
-    "DancingScript-Bold.ttf",
-    "DancingScript-Regular.ttf",
-    "DroidSansFallback.ttf",
-    "DroidSansFallbackFull.ttf",
-    "DroidSansMono.ttf",
-    "LICENSE",
-    "LICENSE.Apache",
-    "LICENSE.OFL",
-    "MTLc3m.ttf",
-    "MTLmr3m.ttf",
-    "NanumGothic.ttf",
-    "NanumGothicBold.ttf",
-    "NotoColorEmoji.ttf",
-    "NotoKufiArabic-Bold.ttf",
-    "NotoKufiArabic-Regular.ttf",
-    "NotoNaskhArabic-Bold.ttf",
-    "NotoNaskhArabic-Regular.ttf",
-    "NotoNaskhArabicUI-Bold.ttf",
-    "NotoNaskhArabicUI-Regular.ttf",
-    "NotoSans-Bold.ttf",
-    "NotoSans-BoldItalic.ttf",
-    "NotoSans-Italic.ttf",
-    "NotoSans-Regular.ttf",
-    "NotoSansArmenian-Bold.ttf",
-    "NotoSansArmenian-Regular.ttf",
-    "NotoSansAvestan-Regular.ttf",
-    "NotoSansBalinese-Regular.ttf",
-    "NotoSansBamum-Regular.ttf",
-    "NotoSansBatak-Regular.ttf",
-    "NotoSansBengali-Bold.ttf",
-    "NotoSansBengali-Regular.ttf",
-    "NotoSansBengaliUI-Bold.ttf",
-    "NotoSansBengaliUI-Regular.ttf",
-    "NotoSansBrahmi-Regular.ttf",
-    "NotoSansBuginese-Regular.ttf",
-    "NotoSansBuhid-Regular.ttf",
-    "NotoSansCanadianAboriginal-Regular.ttf",
-    "NotoSansCarian-Regular.ttf",
-    "NotoSansCham-Bold.ttf",
-    "NotoSansCham-Regular.ttf",
-    "NotoSansCherokee-Regular.ttf",
-    "NotoSansCoptic-Regular.ttf",
-    "NotoSansCuneiform-Regular.ttf",
-    "NotoSansCypriot-Regular.ttf",
-    "NotoSansDeseret-Regular.ttf",
-    "NotoSansDevanagari-Bold.ttf",
-    "NotoSansDevanagari-Regular.ttf",
-    "NotoSansDevanagariUI-Bold.ttf",
-    "NotoSansDevanagariUI-Regular.ttf",
-    "NotoSansEgyptianHieroglyphs-Regular.ttf",
-    "NotoSansEthiopic-Bold.ttf",
-    "NotoSansEthiopic-Regular.ttf",
-    "NotoSansGeorgian-Bold.ttf",
-    "NotoSansGeorgian-Regular.ttf",
-    "NotoSansGlagolitic-Regular.ttf",
-    "NotoSansGothic-Regular.ttf",
-    "NotoSansGujarati-Bold.ttf",
-    "NotoSansGujarati-Regular.ttf",
-    "NotoSansGujaratiUI-Bold.ttf",
-    "NotoSansGujaratiUI-Regular.ttf",
-    "NotoSansGurmukhi-Bold.ttf",
-    "NotoSansGurmukhi-Regular.ttf",
-    "NotoSansGurmukhiUI-Bold.ttf",
-    "NotoSansGurmukhiUI-Regular.ttf",
-    "NotoSansHanunoo-Regular.ttf",
-    "NotoSansHebrew-Bold.ttf",
-    "NotoSansHebrew-Regular.ttf",
-    "NotoSansImperialAramaic-Regular.ttf",
-    "NotoSansInscriptionalPahlavi-Regular.ttf",
-    "NotoSansInscriptionalParthian-Regular.ttf",
-    "NotoSansJP-Regular-Subsetted.otf",
-    "NotoSansJP-Regular.otf",
-    "NotoSansJavanese-Regular.ttf",
-    "NotoSansKR-Regular.otf",
-    "NotoSansKaithi-Regular.ttf",
-    "NotoSansKannada-Bold.ttf",
-    "NotoSansKannada-Regular.ttf",
-    "NotoSansKannadaUI-Bold.ttf",
-    "NotoSansKannadaUI-Regular.ttf",
-    "NotoSansKayahLi-Regular.ttf",
-    "NotoSansKharoshthi-Regular.ttf",
-    "NotoSansKhmer-Bold.ttf",
-    "NotoSansKhmer-Regular.ttf",
-    "NotoSansKhmerUI-Bold.ttf",
-    "NotoSansKhmerUI-Regular.ttf",
-    "NotoSansLao-Bold.ttf",
-    "NotoSansLao-Regular.ttf",
-    "NotoSansLaoUI-Bold.ttf",
-    "NotoSansLaoUI-Regular.ttf",
-    "NotoSansLepcha-Regular.ttf",
-    "NotoSansLimbu-Regular.ttf",
-    "NotoSansLinearB-Regular.ttf",
-    "NotoSansLisu-Regular.ttf",
-    "NotoSansLycian-Regular.ttf",
-    "NotoSansLydian-Regular.ttf",
-    "NotoSansMalayalam-Bold.ttf",
-    "NotoSansMalayalam-Regular.ttf",
-    "NotoSansMalayalamUI-Bold.ttf",
-    "NotoSansMalayalamUI-Regular.ttf",
-    "NotoSansMandaic-Regular.ttf",
-    "NotoSansMeeteiMayek-Regular.ttf",
-    "NotoSansMongolian-Regular.ttf",
-    "NotoSansMyanmar-Bold.ttf",
-    "NotoSansMyanmar-Regular.ttf",
-    "NotoSansMyanmarUI-Bold.ttf",
-    "NotoSansMyanmarUI-Regular.ttf",
-    "NotoSansNKo-Regular.ttf",
-    "NotoSansNewTaiLue-Regular.ttf",
-    "NotoSansOgham-Regular.ttf",
-    "NotoSansOlChiki-Regular.ttf",
-    "NotoSansOldItalic-Regular.ttf",
-    "NotoSansOldPersian-Regular.ttf",
-    "NotoSansOldSouthArabian-Regular.ttf",
-    "NotoSansOldTurkic-Regular.ttf",
-    "NotoSansOriya-Bold.ttf",
-    "NotoSansOriya-Regular.ttf",
-    "NotoSansOriyaUI-Bold.ttf",
-    "NotoSansOriyaUI-Regular.ttf",
-    "NotoSansOsmanya-Regular.ttf",
-    "NotoSansPhagsPa-Regular.ttf",
-    "NotoSansPhoenician-Regular.ttf",
-    "NotoSansRejang-Regular.ttf",
-    "NotoSansRunic-Regular.ttf",
-    "NotoSansSC-Regular.otf",
-    "NotoSansSamaritan-Regular.ttf",
-    "NotoSansSaurashtra-Regular.ttf",
-    "NotoSansShavian-Regular.ttf",
-    "NotoSansSinhala-Bold.ttf",
-    "NotoSansSinhala-Regular.ttf",
-    "NotoSansSundanese-Regular.ttf",
-    "NotoSansSylotiNagri-Regular.ttf",
-    "NotoSansSymbols-Regular-Subsetted.ttf",
-    "NotoSansSymbols-Regular.ttf",
-    "NotoSansSyriacEastern-Regular.ttf",
-    "NotoSansSyriacEstrangela-Regular.ttf",
-    "NotoSansSyriacWestern-Regular.ttf",
-    "NotoSansTC-Regular.otf",
-    "NotoSansTagalog-Regular.ttf",
-    "NotoSansTagbanwa-Regular.ttf",
-    "NotoSansTaiLe-Regular.ttf",
-    "NotoSansTaiTham-Regular.ttf",
-    "NotoSansTaiViet-Regular.ttf",
-    "NotoSansTamil-Bold.ttf",
-    "NotoSansTamil-Regular.ttf",
-    "NotoSansTamilUI-Bold.ttf",
-    "NotoSansTamilUI-Regular.ttf",
-    "NotoSansTelugu-Bold.ttf",
-    "NotoSansTelugu-Regular.ttf",
-    "NotoSansTeluguUI-Bold.ttf",
-    "NotoSansTeluguUI-Regular.ttf",
-    "NotoSansThaana-Bold.ttf",
-    "NotoSansThaana-Regular.ttf",
-    "NotoSansThai-Bold.ttf",
-    "NotoSansThai-Regular.ttf",
-    "NotoSansThaiUI-Bold.ttf",
-    "NotoSansThaiUI-Regular.ttf",
-    "NotoSansTibetan-Regular.ttf",
-    "NotoSansTifinagh-Regular.ttf",
-    "NotoSansUI-Bold.ttf",
-    "NotoSansUI-BoldItalic.ttf",
-    "NotoSansUI-Italic.ttf",
-    "NotoSansUI-Regular.ttf",
-    "NotoSansUgaritic-Regular.ttf",
-    "NotoSansVai-Regular.ttf",
-    "NotoSansYi-Regular.ttf",
-    "NotoSerif-Bold.ttf",
-    "NotoSerif-BoldItalic.ttf",
-    "NotoSerif-Italic.ttf",
-    "NotoSerif-Regular.ttf",
-    "NotoSerifArmenian-Bold.ttf",
-    "NotoSerifArmenian-Regular.ttf",
-    "NotoSerifGeorgian-Bold.ttf",
-    "NotoSerifGeorgian-Regular.ttf",
-    "NotoSerifKhmer-Bold.ttf",
-    "NotoSerifKhmer-Regular.ttf",
-    "NotoSerifLao-Bold.ttf",
-    "NotoSerifLao-Regular.ttf",
-    "NotoSerifThai-Bold.ttf",
-    "NotoSerifThai-Regular.ttf",
-    "Roboto-Black.ttf",
-    "Roboto-BlackItalic.ttf",
-    "Roboto-Bold.ttf",
-    "Roboto-BoldItalic.ttf",
-    "Roboto-Italic.ttf",
-    "Roboto-Light.ttf",
-    "Roboto-LightItalic.ttf",
-    "Roboto-Medium.ttf",
-    "Roboto-MediumItalic.ttf",
-    "Roboto-Regular.ttf",
-    "Roboto-Thin.ttf",
-    "Roboto-ThinItalic.ttf",
-    "RobotoCondensed-Bold.ttf",
-    "RobotoCondensed-BoldItalic.ttf",
-    "RobotoCondensed-Italic.ttf",
-    "RobotoCondensed-Light.ttf",
-    "RobotoCondensed-LightItalic.ttf",
-    "RobotoCondensed-Regular.ttf",
-    "fonts.xml",
-  ]
-
-  outputs = [
-    "$target_gen_dir/{{source_file_part}}",
-  ]
-}
diff --git a/third_party/blimp_fonts/CarroisGothicSC-Regular.ttf.sha1 b/third_party/blimp_fonts/CarroisGothicSC-Regular.ttf.sha1
deleted file mode 100644
index f9120e0..0000000
--- a/third_party/blimp_fonts/CarroisGothicSC-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-009d2696ba2ceb4d58dca2a6535b7c74f252caf2
\ No newline at end of file
diff --git a/third_party/blimp_fonts/Clockopia.ttf.sha1 b/third_party/blimp_fonts/Clockopia.ttf.sha1
deleted file mode 100644
index ca93d0fd..0000000
--- a/third_party/blimp_fonts/Clockopia.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-8175e3bc43ae590f513e5bf38baa5860c81458a1
\ No newline at end of file
diff --git a/third_party/blimp_fonts/ComingSoon.ttf.sha1 b/third_party/blimp_fonts/ComingSoon.ttf.sha1
deleted file mode 100644
index f93b6c9..0000000
--- a/third_party/blimp_fonts/ComingSoon.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-a6fc4d9e7339c7d9c6dd9b994a00e4a965c91df4
\ No newline at end of file
diff --git a/third_party/blimp_fonts/CutiveMono.ttf.sha1 b/third_party/blimp_fonts/CutiveMono.ttf.sha1
deleted file mode 100644
index 428ebc7..0000000
--- a/third_party/blimp_fonts/CutiveMono.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-e4837f21d7581c3f0418a02b2bedf15909df7569
\ No newline at end of file
diff --git a/third_party/blimp_fonts/DancingScript-Bold.ttf.sha1 b/third_party/blimp_fonts/DancingScript-Bold.ttf.sha1
deleted file mode 100644
index 9f007c3..0000000
--- a/third_party/blimp_fonts/DancingScript-Bold.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-489aa561aca5ef5a8e9884b183cad31a2e52bd9f
\ No newline at end of file
diff --git a/third_party/blimp_fonts/DancingScript-Regular.ttf.sha1 b/third_party/blimp_fonts/DancingScript-Regular.ttf.sha1
deleted file mode 100644
index 5a0a8f6..0000000
--- a/third_party/blimp_fonts/DancingScript-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-1298686a3510db5dc99a1a73872e0454112a626e
\ No newline at end of file
diff --git a/third_party/blimp_fonts/DroidSansFallback.ttf.sha1 b/third_party/blimp_fonts/DroidSansFallback.ttf.sha1
deleted file mode 100644
index 7cbbc30..0000000
--- a/third_party/blimp_fonts/DroidSansFallback.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-408db827c9555c10618707d47314083ebf496f59
\ No newline at end of file
diff --git a/third_party/blimp_fonts/DroidSansFallbackFull.ttf.sha1 b/third_party/blimp_fonts/DroidSansFallbackFull.ttf.sha1
deleted file mode 100644
index 9b18446..0000000
--- a/third_party/blimp_fonts/DroidSansFallbackFull.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-53c637979f023ea3933cd09befb6518aef5baa92
\ No newline at end of file
diff --git a/third_party/blimp_fonts/DroidSansMono.ttf.sha1 b/third_party/blimp_fonts/DroidSansMono.ttf.sha1
deleted file mode 100644
index 536bde4..0000000
--- a/third_party/blimp_fonts/DroidSansMono.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-0b75601f8ef8e111babb6ed11de6573f7178ce44
\ No newline at end of file
diff --git a/third_party/blimp_fonts/LICENSE b/third_party/blimp_fonts/LICENSE
deleted file mode 100644
index 78d4582..0000000
--- a/third_party/blimp_fonts/LICENSE
+++ /dev/null
@@ -1,230 +0,0 @@
-Fonts under Apache License Version 2.0 license:
-
-AndroidClock.ttf
-AndroidClock_Highlight.ttf
-AndroidClock_Solid.ttf
-Clockopia.ttf
-ComingSoon.ttf
-DroidSansFallback.ttf
-DroidSansFallbackFull.ttf
-DroidSansMono.ttf
-MTLc3m.ttf
-MTLmr3m.ttf
-NotoColorEmoji.ttf
-NotoKufiArabic-Bold.ttf
-NotoKufiArabic-Regular.ttf
-NotoNaskhArabic-Bold.ttf
-NotoNaskhArabic-Regular.ttf
-NotoNaskhArabicUI-Bold.ttf
-NotoNaskhArabicUI-Regular.ttf
-NotoSansArmenian-Bold.ttf
-NotoSansArmenian-Regular.ttf
-NotoSansAvestan-Regular.ttf
-NotoSansBalinese-Regular.ttf
-NotoSansBamum-Regular.ttf
-NotoSansBatak-Regular.ttf
-NotoSansBengali-Bold.ttf
-NotoSansBengali-Regular.ttf
-NotoSansBengaliUI-Bold.ttf
-NotoSansBengaliUI-Regular.ttf
-NotoSans-BoldItalic.ttf
-NotoSans-Bold.ttf
-NotoSansBrahmi-Regular.ttf
-NotoSansBuginese-Regular.ttf
-NotoSansBuhid-Regular.ttf
-NotoSansCanadianAboriginal-Regular.ttf
-NotoSansCarian-Regular.ttf
-NotoSansCham-Bold.ttf
-NotoSansCham-Regular.ttf
-NotoSansCherokee-Regular.ttf
-NotoSansCoptic-Regular.ttf
-NotoSansCuneiform-Regular.ttf
-NotoSansCypriot-Regular.ttf
-NotoSansDeseret-Regular.ttf
-NotoSansDevanagari-Bold.ttf
-NotoSansDevanagari-Regular.ttf
-NotoSansDevanagariUI-Bold.ttf
-NotoSansDevanagariUI-Regular.ttf
-NotoSansEgyptianHieroglyphs-Regular.ttf
-NotoSansEthiopic-Bold.ttf
-NotoSansEthiopic-Regular.ttf
-NotoSansGeorgian-Bold.ttf
-NotoSansGeorgian-Regular.ttf
-NotoSansGlagolitic-Regular.ttf
-NotoSansGothic-Regular.ttf
-NotoSansGujarati-Bold.ttf
-NotoSansGujarati-Regular.ttf
-NotoSansGujaratiUI-Bold.ttf
-NotoSansGujaratiUI-Regular.ttf
-NotoSansGurmukhi-Bold.ttf
-NotoSansGurmukhi-Regular.ttf
-NotoSansGurmukhiUI-Bold.ttf
-NotoSansGurmukhiUI-Regular.ttf
-NotoSansHanunoo-Regular.ttf
-NotoSansHebrew-Bold.ttf
-NotoSansHebrew-Regular.ttf
-NotoSansImperialAramaic-Regular.ttf
-NotoSansInscriptionalPahlavi-Regular.ttf
-NotoSansInscriptionalParthian-Regular.ttf
-NotoSans-Italic.ttf
-NotoSansJavanese-Regular.ttf
-NotoSansKaithi-Regular.ttf
-NotoSansKannada-Bold.ttf
-NotoSansKannada-Regular.ttf
-NotoSansKannadaUI-Bold.ttf
-NotoSansKannadaUI-Regular.ttf
-NotoSansKayahLi-Regular.ttf
-NotoSansKharoshthi-Regular.ttf
-NotoSansKhmer-Bold.ttf
-NotoSansKhmer-Regular.ttf
-NotoSansKhmerUI-Bold.ttf
-NotoSansKhmerUI-Regular.ttf
-NotoSansLao-Bold.ttf
-NotoSansLao-Regular.ttf
-NotoSansLaoUI-Bold.ttf
-NotoSansLaoUI-Regular.ttf
-NotoSansLepcha-Regular.ttf
-NotoSansLimbu-Regular.ttf
-NotoSansLinearB-Regular.ttf
-NotoSansLisu-Regular.ttf
-NotoSansLycian-Regular.ttf
-NotoSansLydian-Regular.ttf
-NotoSansMalayalam-Bold.ttf
-NotoSansMalayalam-Regular.ttf
-NotoSansMalayalamUI-Bold.ttf
-NotoSansMalayalamUI-Regular.ttf
-NotoSansMandaic-Regular.ttf
-NotoSansMeeteiMayek-Regular.ttf
-NotoSansMongolian-Regular.ttf
-NotoSansMyanmar-Bold.ttf
-NotoSansMyanmar-Regular.ttf
-NotoSansMyanmarUI-Bold.ttf
-NotoSansMyanmarUI-Regular.ttf
-NotoSansNewTaiLue-Regular.ttf
-NotoSansNKo-Regular.ttf
-NotoSansOgham-Regular.ttf
-NotoSansOlChiki-Regular.ttf
-NotoSansOldItalic-Regular.ttf
-NotoSansOldPersian-Regular.ttf
-NotoSansOldSouthArabian-Regular.ttf
-NotoSansOldTurkic-Regular.ttf
-NotoSansOriya-Bold.ttf
-NotoSansOriya-Regular.ttf
-NotoSansOriyaUI-Bold.ttf
-NotoSansOriyaUI-Regular.ttf
-NotoSansOsmanya-Regular.ttf
-NotoSansPhagsPa-Regular.ttf
-NotoSansPhoenician-Regular.ttf
-NotoSans-Regular.ttf
-NotoSansRejang-Regular.ttf
-NotoSansRunic-Regular.ttf
-NotoSansSamaritan-Regular.ttf
-NotoSansSaurashtra-Regular.ttf
-NotoSansShavian-Regular.ttf
-NotoSansSinhala-Bold.ttf
-NotoSansSinhala-Regular.ttf
-NotoSansSundanese-Regular.ttf
-NotoSansSylotiNagri-Regular.ttf
-NotoSansSymbols-Regular-Subsetted.ttf
-NotoSansSymbols-Regular.ttf
-NotoSansSyriacEastern-Regular.ttf
-NotoSansSyriacEstrangela-Regular.ttf
-NotoSansSyriacWestern-Regular.ttf
-NotoSansTagalog-Regular.ttf
-NotoSansTagbanwa-Regular.ttf
-NotoSansTaiLe-Regular.ttf
-NotoSansTaiTham-Regular.ttf
-NotoSansTaiViet-Regular.ttf
-NotoSansTamil-Bold.ttf
-NotoSansTamil-Regular.ttf
-NotoSansTamilUI-Bold.ttf
-NotoSansTamilUI-Regular.ttf
-NotoSansTelugu-Bold.ttf
-NotoSansTelugu-Regular.ttf
-NotoSansTeluguUI-Bold.ttf
-NotoSansTeluguUI-Regular.ttf
-NotoSansThaana-Bold.ttf
-NotoSansThaana-Regular.ttf
-NotoSansThai-Bold.ttf
-NotoSansThai-Regular.ttf
-NotoSansThaiUI-Bold.ttf
-NotoSansThaiUI-Regular.ttf
-NotoSansTibetan-Regular.ttf
-NotoSansTifinagh-Regular.ttf
-NotoSansUgaritic-Regular.ttf
-NotoSansUI-BoldItalic.ttf
-NotoSansUI-Bold.ttf
-NotoSansUI-Italic.ttf
-NotoSansUI-Regular.ttf
-NotoSansVai-Regular.ttf
-NotoSansYi-Regular.ttf
-NotoSerifArmenian-Bold.ttf
-NotoSerifArmenian-Regular.ttf
-NotoSerif-BoldItalic.ttf
-NotoSerif-Bold.ttf
-NotoSerifGeorgian-Bold.ttf
-NotoSerifGeorgian-Regular.ttf
-NotoSerif-Italic.ttf
-NotoSerifKhmer-Bold.ttf
-NotoSerifKhmer-Regular.ttf
-NotoSerifLao-Bold.ttf
-NotoSerifLao-Regular.ttf
-NotoSerif-Regular.ttf
-NotoSerifThai-Bold.ttf
-NotoSerifThai-Regular.ttf
-Roboto-BlackItalic.ttf
-Roboto-Black.ttf
-Roboto-BoldItalic.ttf
-Roboto-Bold.ttf
-RobotoCondensed-BoldItalic.ttf
-RobotoCondensed-Bold.ttf
-RobotoCondensed-Italic.ttf
-RobotoCondensed-LightItalic.ttf
-RobotoCondensed-Light.ttf
-RobotoCondensed-Regular.ttf
-Roboto-Italic.ttf
-Roboto-LightItalic.ttf
-Roboto-Light.ttf
-Roboto-MediumItalic.ttf
-Roboto-Medium.ttf
-Roboto-Regular.ttf
-Roboto-ThinItalic.ttf
-Roboto-Thin.ttf
-
-
-Fonts under SIL Open Font License, Version 1.1:
-(Full license in LICENSE.OFL)
-
-NotoSansJP-Regular.otf
-NotoSansJP-Regular-Subsetted.otf
-NotoSansKR-Regular.otf
-NotoSansSC-Regular.otf
-NotoSansTC-Regular.otf
-
-
-Copyright (c) 2011 by Ralph du Carrois, with Reserved Font Name 'Carrois'
-This Font Software is licensed under the SIL Open Font License, Version 1.1
-(Full license in LICENSE.OFL)
-CarroisGothicSC-Regular.ttf
-
-
-Copyright (c) 2010, Pablo Impallari (www.impallari.com|impallari@gmail.com),
-Copyright (c) 2010, Igino Marini. (www.ikern.com|mail@iginomarini.com),
-with Reserved Font Name Dancing Script.
-This Font Software is licensed under the SIL Open Font License, Version 1.1.
-(Full license in LICENSE.OFL)
-
-DancingScript-Bold.ttf
-DancingScript-Regular.ttf
-CutiveMono.ttf
-
-
-Copyright (c) 2010, NHN Corporation (http://www.nhncorp.com),
-  (http://hangeul.naver.com/font)
-with Reserved Font Name Nanum, Naver Nanum, NanumGothic, Naver NanumGothic, NanumMyeongjo, Naver NanumMyeongjo, NanumBrush, Naver NanumBrush, NanumPen, Naver NanumPen, Naver NanumGothicEco, NanumGothicEco, Naver NanumMyeongjoEco, NanumMyeongjoEco, Naver NanumGothicLight, NanumGothicLight
-
-This Font Software is licensed under the SIL Open Font License, Version 1.1.
-(Full license in LICENSE.OFL)
-
-NanumGothicBold.ttf
-NanumGothic.ttf
diff --git a/third_party/blimp_fonts/LICENSE.Apache b/third_party/blimp_fonts/LICENSE.Apache
deleted file mode 100644
index a3711ba6..0000000
--- a/third_party/blimp_fonts/LICENSE.Apache
+++ /dev/null
@@ -1,201 +0,0 @@
-                             Apache License
-                       Version 2.0, January 2004
-                    http://www.apache.org/licenses/
-
-TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-1. Definitions.
-
-  "License" shall mean the terms and conditions for use, reproduction,
-  and distribution as defined by Sections 1 through 9 of this document.
-
-  "Licensor" shall mean the copyright owner or entity authorized by
-  the copyright owner that is granting the License.
-
-  "Legal Entity" shall mean the union of the acting entity and all
-  other entities that control, are controlled by, or are under common
-  control with that entity. For the purposes of this definition,
-  "control" means (i) the power, direct or indirect, to cause the
-  direction or management of such entity, whether by contract or
-  otherwise, or (ii) ownership of fifty percent (50%) or more of the
-  outstanding shares, or (iii) beneficial ownership of such entity.
-
-  "You" (or "Your") shall mean an individual or Legal Entity
-  exercising permissions granted by this License.
-
-  "Source" form shall mean the preferred form for making modifications,
-  including but not limited to software source code, documentation
-  source, and configuration files.
-
-  "Object" form shall mean any form resulting from mechanical
-  transformation or translation of a Source form, including but
-  not limited to compiled object code, generated documentation,
-  and conversions to other media types.
-
-  "Work" shall mean the work of authorship, whether in Source or
-  Object form, made available under the License, as indicated by a
-  copyright notice that is included in or attached to the work
-  (an example is provided in the Appendix below).
-
-  "Derivative Works" shall mean any work, whether in Source or Object
-  form, that is based on (or derived from) the Work and for which the
-  editorial revisions, annotations, elaborations, or other modifications
-  represent, as a whole, an original work of authorship. For the purposes
-  of this License, Derivative Works shall not include works that remain
-  separable from, or merely link (or bind by name) to the interfaces of,
-  the Work and Derivative Works thereof.
-
-  "Contribution" shall mean any work of authorship, including
-  the original version of the Work and any modifications or additions
-  to that Work or Derivative Works thereof, that is intentionally
-  submitted to Licensor for inclusion in the Work by the copyright owner
-  or by an individual or Legal Entity authorized to submit on behalf of
-  the copyright owner. For the purposes of this definition, "submitted"
-  means any form of electronic, verbal, or written communication sent
-  to the Licensor or its representatives, including but not limited to
-  communication on electronic mailing lists, source code control systems,
-  and issue tracking systems that are managed by, or on behalf of, the
-  Licensor for the purpose of discussing and improving the Work, but
-  excluding communication that is conspicuously marked or otherwise
-  designated in writing by the copyright owner as "Not a Contribution."
-
-  "Contributor" shall mean Licensor and any individual or Legal Entity
-  on behalf of whom a Contribution has been received by Licensor and
-  subsequently incorporated within the Work.
-
-2. Grant of Copyright License. Subject to the terms and conditions of
-  this License, each Contributor hereby grants to You a perpetual,
-  worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-  copyright license to reproduce, prepare Derivative Works of,
-  publicly display, publicly perform, sublicense, and distribute the
-  Work and such Derivative Works in Source or Object form.
-
-3. Grant of Patent License. Subject to the terms and conditions of
-  this License, each Contributor hereby grants to You a perpetual,
-  worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-  (except as stated in this section) patent license to make, have made,
-  use, offer to sell, sell, import, and otherwise transfer the Work,
-  where such license applies only to those patent claims licensable
-  by such Contributor that are necessarily infringed by their
-  Contribution(s) alone or by combination of their Contribution(s)
-  with the Work to which such Contribution(s) was submitted. If You
-  institute patent litigation against any entity (including a
-  cross-claim or counterclaim in a lawsuit) alleging that the Work
-  or a Contribution incorporated within the Work constitutes direct
-  or contributory patent infringement, then any patent licenses
-  granted to You under this License for that Work shall terminate
-  as of the date such litigation is filed.
-
-4. Redistribution. You may reproduce and distribute copies of the
-  Work or Derivative Works thereof in any medium, with or without
-  modifications, and in Source or Object form, provided that You
-  meet the following conditions:
-
-  (a) You must give any other recipients of the Work or
-      Derivative Works a copy of this License; and
-
-  (b) You must cause any modified files to carry prominent notices
-      stating that You changed the files; and
-
-  (c) You must retain, in the Source form of any Derivative Works
-      that You distribute, all copyright, patent, trademark, and
-      attribution notices from the Source form of the Work,
-      excluding those notices that do not pertain to any part of
-      the Derivative Works; and
-
-  (d) If the Work includes a "NOTICE" text file as part of its
-      distribution, then any Derivative Works that You distribute must
-      include a readable copy of the attribution notices contained
-      within such NOTICE file, excluding those notices that do not
-      pertain to any part of the Derivative Works, in at least one
-      of the following places: within a NOTICE text file distributed
-      as part of the Derivative Works; within the Source form or
-      documentation, if provided along with the Derivative Works; or,
-      within a display generated by the Derivative Works, if and
-      wherever such third-party notices normally appear. The contents
-      of the NOTICE file are for informational purposes only and
-      do not modify the License. You may add Your own attribution
-      notices within Derivative Works that You distribute, alongside
-      or as an addendum to the NOTICE text from the Work, provided
-      that such additional attribution notices cannot be construed
-      as modifying the License.
-
-  You may add Your own copyright statement to Your modifications and
-  may provide additional or different license terms and conditions
-  for use, reproduction, or distribution of Your modifications, or
-  for any such Derivative Works as a whole, provided Your use,
-  reproduction, and distribution of the Work otherwise complies with
-  the conditions stated in this License.
-
-5. Submission of Contributions. Unless You explicitly state otherwise,
-  any Contribution intentionally submitted for inclusion in the Work
-  by You to the Licensor shall be under the terms and conditions of
-  this License, without any additional terms or conditions.
-  Notwithstanding the above, nothing herein shall supersede or modify
-  the terms of any separate license agreement you may have executed
-  with Licensor regarding such Contributions.
-
-6. Trademarks. This License does not grant permission to use the trade
-  names, trademarks, service marks, or product names of the Licensor,
-  except as required for reasonable and customary use in describing the
-  origin of the Work and reproducing the content of the NOTICE file.
-
-7. Disclaimer of Warranty. Unless required by applicable law or
-  agreed to in writing, Licensor provides the Work (and each
-  Contributor provides its Contributions) on an "AS IS" BASIS,
-  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-  implied, including, without limitation, any warranties or conditions
-  of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-  PARTICULAR PURPOSE. You are solely responsible for determining the
-  appropriateness of using or redistributing the Work and assume any
-  risks associated with Your exercise of permissions under this License.
-
-8. Limitation of Liability. In no event and under no legal theory,
-  whether in tort (including negligence), contract, or otherwise,
-  unless required by applicable law (such as deliberate and grossly
-  negligent acts) or agreed to in writing, shall any Contributor be
-  liable to You for damages, including any direct, indirect, special,
-  incidental, or consequential damages of any character arising as a
-  result of this License or out of the use or inability to use the
-  Work (including but not limited to damages for loss of goodwill,
-  work stoppage, computer failure or malfunction, or any and all
-  other commercial damages or losses), even if such Contributor
-  has been advised of the possibility of such damages.
-
-9. Accepting Warranty or Additional Liability. While redistributing
-  the Work or Derivative Works thereof, You may choose to offer,
-  and charge a fee for, acceptance of support, warranty, indemnity,
-  or other liability obligations and/or rights consistent with this
-  License. However, in accepting such obligations, You may act only
-  on Your own behalf and on Your sole responsibility, not on behalf
-  of any other Contributor, and only if You agree to indemnify,
-  defend, and hold each Contributor harmless for any liability
-  incurred by, or claims asserted against, such Contributor by reason
-  of your accepting any such warranty or additional liability.
-
-END OF TERMS AND CONDITIONS
-
-APPENDIX: How to apply the Apache License to your work.
-
-  To apply the Apache License to your work, attach the following
-  boilerplate notice, with the fields enclosed by brackets "[]"
-  replaced with your own identifying information. (Don't include
-  the brackets!)  The text should be enclosed in the appropriate
-  comment syntax for the file format. We also recommend that a
-  file or class name and description of purpose be included on the
-  same "printed page" as the copyright notice for easier
-  identification within third-party archives.
-
-Copyright [yyyy] [name of copyright owner]
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-   http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
diff --git a/third_party/blimp_fonts/LICENSE.OFL b/third_party/blimp_fonts/LICENSE.OFL
deleted file mode 100644
index d952d62..0000000
--- a/third_party/blimp_fonts/LICENSE.OFL
+++ /dev/null
@@ -1,92 +0,0 @@
-This Font Software is licensed under the SIL Open Font License,
-Version 1.1.
-
-This license is copied below, and is also available with a FAQ at:
-http://scripts.sil.org/OFL
-
------------------------------------------------------------
-SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
------------------------------------------------------------
-
-PREAMBLE
-The goals of the Open Font License (OFL) are to stimulate worldwide
-development of collaborative font projects, to support the font
-creation efforts of academic and linguistic communities, and to
-provide a free and open framework in which fonts may be shared and
-improved in partnership with others.
-
-The OFL allows the licensed fonts to be used, studied, modified and
-redistributed freely as long as they are not sold by themselves. The
-fonts, including any derivative works, can be bundled, embedded,
-redistributed and/or sold with any software provided that any reserved
-names are not used by derivative works. The fonts and derivatives,
-however, cannot be released under any other type of license. The
-requirement for fonts to remain under this license does not apply to
-any document created using the fonts or their derivatives.
-
-DEFINITIONS
-"Font Software" refers to the set of files released by the Copyright
-Holder(s) under this license and clearly marked as such. This may
-include source files, build scripts and documentation.
-
-"Reserved Font Name" refers to any names specified as such after the
-copyright statement(s).
-
-"Original Version" refers to the collection of Font Software
-components as distributed by the Copyright Holder(s).
-
-"Modified Version" refers to any derivative made by adding to,
-deleting, or substituting -- in part or in whole -- any of the
-components of the Original Version, by changing formats or by porting
-the Font Software to a new environment.
-
-"Author" refers to any designer, engineer, programmer, technical
-writer or other person who contributed to the Font Software.
-
-PERMISSION & CONDITIONS
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of the Font Software, to use, study, copy, merge, embed,
-modify, redistribute, and sell modified and unmodified copies of the
-Font Software, subject to the following conditions:
-
-1) Neither the Font Software nor any of its individual components, in
-Original or Modified Versions, may be sold by itself.
-
-2) Original or Modified Versions of the Font Software may be bundled,
-redistributed and/or sold with any software, provided that each copy
-contains the above copyright notice and this license. These can be
-included either as stand-alone text files, human-readable headers or
-in the appropriate machine-readable metadata fields within text or
-binary files as long as those fields can be easily viewed by the user.
-
-3) No Modified Version of the Font Software may use the Reserved Font
-Name(s) unless explicit written permission is granted by the
-corresponding Copyright Holder. This restriction only applies to the
-primary font name as presented to the users.
-
-4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
-Software shall not be used to promote, endorse or advertise any
-Modified Version, except to acknowledge the contribution(s) of the
-Copyright Holder(s) and the Author(s) or with their explicit written
-permission.
-
-5) The Font Software, modified or unmodified, in part or in whole,
-must be distributed entirely under this license, and must not be
-distributed under any other license. The requirement for fonts to
-remain under this license does not apply to any document created using
-the Font Software.
-
-TERMINATION
-This license becomes null and void if any of the above conditions are
-not met.
-
-DISCLAIMER
-THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
-OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
-COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
-DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
-OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/third_party/blimp_fonts/MTLc3m.ttf.sha1 b/third_party/blimp_fonts/MTLc3m.ttf.sha1
deleted file mode 100644
index fe44a8d..0000000
--- a/third_party/blimp_fonts/MTLc3m.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-3c204b67777ea8d9a5b68b1c10eb606bb72cb5ab
\ No newline at end of file
diff --git a/third_party/blimp_fonts/MTLmr3m.ttf.sha1 b/third_party/blimp_fonts/MTLmr3m.ttf.sha1
deleted file mode 100644
index fe932746..0000000
--- a/third_party/blimp_fonts/MTLmr3m.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-6084cd39578214d7a4dec3fe46b10fdb7d335e50
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NanumGothic.ttf.sha1 b/third_party/blimp_fonts/NanumGothic.ttf.sha1
deleted file mode 100644
index f523180..0000000
--- a/third_party/blimp_fonts/NanumGothic.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-f6844b0169c0a453778980b65b28fa4b15014246
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NanumGothicBold.ttf.sha1 b/third_party/blimp_fonts/NanumGothicBold.ttf.sha1
deleted file mode 100644
index c453c733d..0000000
--- a/third_party/blimp_fonts/NanumGothicBold.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-da02b0bb41d80957c8ffdde238b2c85c21f02361
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoColorEmoji.ttf.sha1 b/third_party/blimp_fonts/NotoColorEmoji.ttf.sha1
deleted file mode 100644
index f9073838..0000000
--- a/third_party/blimp_fonts/NotoColorEmoji.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-d4af84777101e3083886decc94a87b7ab8c370e5
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoKufiArabic-Bold.ttf.sha1 b/third_party/blimp_fonts/NotoKufiArabic-Bold.ttf.sha1
deleted file mode 100644
index 7d430f8..0000000
--- a/third_party/blimp_fonts/NotoKufiArabic-Bold.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-1e586ea25cf9ab4fd959280e1248f8a44c4a59d9
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoKufiArabic-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoKufiArabic-Regular.ttf.sha1
deleted file mode 100644
index b1753b7..0000000
--- a/third_party/blimp_fonts/NotoKufiArabic-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-3a3f060aaf35f60e543d5e762a33c6ea66d80c9c
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoNaskhArabic-Bold.ttf.sha1 b/third_party/blimp_fonts/NotoNaskhArabic-Bold.ttf.sha1
deleted file mode 100644
index 87386afb..0000000
--- a/third_party/blimp_fonts/NotoNaskhArabic-Bold.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-b81530fa957843ba04e9c91dd1ee5cba8e737345
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoNaskhArabic-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoNaskhArabic-Regular.ttf.sha1
deleted file mode 100644
index cffe28e..0000000
--- a/third_party/blimp_fonts/NotoNaskhArabic-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-651752e1b267194a463b4fb211ee8579576e9c0f
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoNaskhArabicUI-Bold.ttf.sha1 b/third_party/blimp_fonts/NotoNaskhArabicUI-Bold.ttf.sha1
deleted file mode 100644
index fdaa035..0000000
--- a/third_party/blimp_fonts/NotoNaskhArabicUI-Bold.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-43c827c0770e68d211b2f64f7796e4773665439f
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoNaskhArabicUI-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoNaskhArabicUI-Regular.ttf.sha1
deleted file mode 100644
index 909aa1f..0000000
--- a/third_party/blimp_fonts/NotoNaskhArabicUI-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-4dfe8336947e6e52502f2f8156371e85553ab600
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSans-Bold.ttf.sha1 b/third_party/blimp_fonts/NotoSans-Bold.ttf.sha1
deleted file mode 100644
index bfeded8..0000000
--- a/third_party/blimp_fonts/NotoSans-Bold.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-64b897dfb0a6cc8fd573e0793b85028b73dfb4a0
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSans-BoldItalic.ttf.sha1 b/third_party/blimp_fonts/NotoSans-BoldItalic.ttf.sha1
deleted file mode 100644
index f6f4b8b..0000000
--- a/third_party/blimp_fonts/NotoSans-BoldItalic.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-0ef56b3baa79415191519532e1c4a9325bb4f5ea
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSans-Italic.ttf.sha1 b/third_party/blimp_fonts/NotoSans-Italic.ttf.sha1
deleted file mode 100644
index bc30332..0000000
--- a/third_party/blimp_fonts/NotoSans-Italic.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-0d572e04d5d48ce3819ac78e0e2dbe1a6bcb1d47
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSans-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSans-Regular.ttf.sha1
deleted file mode 100644
index 9b89352..0000000
--- a/third_party/blimp_fonts/NotoSans-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-b0c0c510fbf942d63745dc5248d23f1fe1859c1f
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansArmenian-Bold.ttf.sha1 b/third_party/blimp_fonts/NotoSansArmenian-Bold.ttf.sha1
deleted file mode 100644
index 4a057fe6..0000000
--- a/third_party/blimp_fonts/NotoSansArmenian-Bold.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-eaecc6acfe8e40321429b503e1f4aa55e67b15e7
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansArmenian-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansArmenian-Regular.ttf.sha1
deleted file mode 100644
index 2450a07..0000000
--- a/third_party/blimp_fonts/NotoSansArmenian-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-bb1d0b181ee7a3dfd2570be4e29052e2eeb4c4a8
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansAvestan-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansAvestan-Regular.ttf.sha1
deleted file mode 100644
index 9dee971e..0000000
--- a/third_party/blimp_fonts/NotoSansAvestan-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-97993a74daa52ff59031f5c5541dc37459563f77
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansBalinese-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansBalinese-Regular.ttf.sha1
deleted file mode 100644
index 528d2d45..0000000
--- a/third_party/blimp_fonts/NotoSansBalinese-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-48a782222ccbc6e67036a83dd8ccfef75b766b8c
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansBamum-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansBamum-Regular.ttf.sha1
deleted file mode 100644
index 0849897..0000000
--- a/third_party/blimp_fonts/NotoSansBamum-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-7d3d14ac5ae5df87d7dc9243df011a6220023d30
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansBatak-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansBatak-Regular.ttf.sha1
deleted file mode 100644
index 68996230..0000000
--- a/third_party/blimp_fonts/NotoSansBatak-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-113c277988592dcd935fad584164814a0c39987c
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansBengali-Bold.ttf.sha1 b/third_party/blimp_fonts/NotoSansBengali-Bold.ttf.sha1
deleted file mode 100644
index db8c39a4..0000000
--- a/third_party/blimp_fonts/NotoSansBengali-Bold.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-3ba5b31be8e6715cabe7eb3f6948dad3936a54f6
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansBengali-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansBengali-Regular.ttf.sha1
deleted file mode 100644
index 8a26e7e..0000000
--- a/third_party/blimp_fonts/NotoSansBengali-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-28e762ed4a3b29dddb1cbd591f264f6e6471f0f2
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansBengaliUI-Bold.ttf.sha1 b/third_party/blimp_fonts/NotoSansBengaliUI-Bold.ttf.sha1
deleted file mode 100644
index 45745ab..0000000
--- a/third_party/blimp_fonts/NotoSansBengaliUI-Bold.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-1ca4e43f7a865f21890f5a6f2258bbad758ba021
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansBengaliUI-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansBengaliUI-Regular.ttf.sha1
deleted file mode 100644
index 9b91c21d..0000000
--- a/third_party/blimp_fonts/NotoSansBengaliUI-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-efb13bb61802b122deb2e9445c855a008dd7d6fa
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansBrahmi-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansBrahmi-Regular.ttf.sha1
deleted file mode 100644
index 97086ff..0000000
--- a/third_party/blimp_fonts/NotoSansBrahmi-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-4cedf2d8ca231b81a44d984d04dd920360da4509
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansBuginese-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansBuginese-Regular.ttf.sha1
deleted file mode 100644
index 56cd4fe..0000000
--- a/third_party/blimp_fonts/NotoSansBuginese-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-bc56fb49234be9e7eddbaa35fc3e8965cde61155
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansBuhid-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansBuhid-Regular.ttf.sha1
deleted file mode 100644
index 0909c2f..0000000
--- a/third_party/blimp_fonts/NotoSansBuhid-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-7b6bc1c7b6444090b45ba5400bd16fedd3f1f310
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansCanadianAboriginal-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansCanadianAboriginal-Regular.ttf.sha1
deleted file mode 100644
index 4f2b208..0000000
--- a/third_party/blimp_fonts/NotoSansCanadianAboriginal-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-d3977d0e5345ccb2cc7ca1d93d2420f31b4eb558
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansCarian-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansCarian-Regular.ttf.sha1
deleted file mode 100644
index 3ae06b4..0000000
--- a/third_party/blimp_fonts/NotoSansCarian-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-0b51a8b392db852e640393ec34e7c07c10587fa5
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansCham-Bold.ttf.sha1 b/third_party/blimp_fonts/NotoSansCham-Bold.ttf.sha1
deleted file mode 100644
index 2d123d0..0000000
--- a/third_party/blimp_fonts/NotoSansCham-Bold.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-4ad98c588ef2214aca74f6634278e58aec681fcd
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansCham-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansCham-Regular.ttf.sha1
deleted file mode 100644
index bef04f6..0000000
--- a/third_party/blimp_fonts/NotoSansCham-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-18cd6f3b26410a70c1a00bf52ef26d6376874ab0
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansCherokee-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansCherokee-Regular.ttf.sha1
deleted file mode 100644
index 9d98d2a1..0000000
--- a/third_party/blimp_fonts/NotoSansCherokee-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-5be65ab8dc89fcdca48018ba3c863620ce95ac37
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansCoptic-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansCoptic-Regular.ttf.sha1
deleted file mode 100644
index 64df8346..0000000
--- a/third_party/blimp_fonts/NotoSansCoptic-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-08f262f76db5a9a53ac48c62b03d0dcefef0f5a7
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansCuneiform-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansCuneiform-Regular.ttf.sha1
deleted file mode 100644
index c6535d2..0000000
--- a/third_party/blimp_fonts/NotoSansCuneiform-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-1731ae2d4b5b363efe9e86f9b6d4e77d590ceac2
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansCypriot-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansCypriot-Regular.ttf.sha1
deleted file mode 100644
index f9d715e5..0000000
--- a/third_party/blimp_fonts/NotoSansCypriot-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-1e61adaf72b89c8b2c640c5deb3166048b9935ab
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansDeseret-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansDeseret-Regular.ttf.sha1
deleted file mode 100644
index feb1fb6d..0000000
--- a/third_party/blimp_fonts/NotoSansDeseret-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-12610cd362930ce2bf2464d71391df11fa05e041
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansDevanagari-Bold.ttf.sha1 b/third_party/blimp_fonts/NotoSansDevanagari-Bold.ttf.sha1
deleted file mode 100644
index 1db540a5..0000000
--- a/third_party/blimp_fonts/NotoSansDevanagari-Bold.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-7d2e8e7960e6e74507e974c1abb60c7118c5ec70
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansDevanagari-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansDevanagari-Regular.ttf.sha1
deleted file mode 100644
index 6f19fe39..0000000
--- a/third_party/blimp_fonts/NotoSansDevanagari-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-e043644bd7ca723c03a6482a472b8da6e7a6d87b
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansDevanagariUI-Bold.ttf.sha1 b/third_party/blimp_fonts/NotoSansDevanagariUI-Bold.ttf.sha1
deleted file mode 100644
index 0201754..0000000
--- a/third_party/blimp_fonts/NotoSansDevanagariUI-Bold.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-d2cb268c25df9f8f6f834aeb5cd823603be1d202
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansDevanagariUI-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansDevanagariUI-Regular.ttf.sha1
deleted file mode 100644
index 794a5d7..0000000
--- a/third_party/blimp_fonts/NotoSansDevanagariUI-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-167c6949556960b8dd779baf68a9a6be51e788de
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansEgyptianHieroglyphs-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansEgyptianHieroglyphs-Regular.ttf.sha1
deleted file mode 100644
index d75145b..0000000
--- a/third_party/blimp_fonts/NotoSansEgyptianHieroglyphs-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-f751cc4b4b0cf4c97f608ae4f7741a36fe9ff66c
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansEthiopic-Bold.ttf.sha1 b/third_party/blimp_fonts/NotoSansEthiopic-Bold.ttf.sha1
deleted file mode 100644
index 62e8a19..0000000
--- a/third_party/blimp_fonts/NotoSansEthiopic-Bold.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-514908c4ec5afc786ebf6979b654a48649cd0eca
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansEthiopic-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansEthiopic-Regular.ttf.sha1
deleted file mode 100644
index d64850d..0000000
--- a/third_party/blimp_fonts/NotoSansEthiopic-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-b4e7246f78ff5d94de75c9fd5c6aec7c0540ee34
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansGeorgian-Bold.ttf.sha1 b/third_party/blimp_fonts/NotoSansGeorgian-Bold.ttf.sha1
deleted file mode 100644
index 590f36a..0000000
--- a/third_party/blimp_fonts/NotoSansGeorgian-Bold.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-f5ef0c389a715449de4cfc75d188cee902ceab54
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansGeorgian-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansGeorgian-Regular.ttf.sha1
deleted file mode 100644
index c862c47..0000000
--- a/third_party/blimp_fonts/NotoSansGeorgian-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-0bc21a4a8df1a38699ca008b0771da770bbe4fd2
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansGlagolitic-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansGlagolitic-Regular.ttf.sha1
deleted file mode 100644
index 5e29582..0000000
--- a/third_party/blimp_fonts/NotoSansGlagolitic-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-254597fab20087221158855f58d1ce97653f746f
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansGothic-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansGothic-Regular.ttf.sha1
deleted file mode 100644
index eb4f3996..0000000
--- a/third_party/blimp_fonts/NotoSansGothic-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-3e4ca5caf1c40d5b7509269b57319f5542338d46
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansGujarati-Bold.ttf.sha1 b/third_party/blimp_fonts/NotoSansGujarati-Bold.ttf.sha1
deleted file mode 100644
index 70f57bbe..0000000
--- a/third_party/blimp_fonts/NotoSansGujarati-Bold.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-8c8fb46985f818e921ffedb9a9bde0fcf7828911
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansGujarati-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansGujarati-Regular.ttf.sha1
deleted file mode 100644
index 8f4ac71..0000000
--- a/third_party/blimp_fonts/NotoSansGujarati-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-24c133d6352b25c120bcf33d989bf26723e24279
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansGujaratiUI-Bold.ttf.sha1 b/third_party/blimp_fonts/NotoSansGujaratiUI-Bold.ttf.sha1
deleted file mode 100644
index 8d4f7d5..0000000
--- a/third_party/blimp_fonts/NotoSansGujaratiUI-Bold.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-fbe9d746123474703345067ad016aa1f14cf6dc9
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansGujaratiUI-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansGujaratiUI-Regular.ttf.sha1
deleted file mode 100644
index 2002b08..0000000
--- a/third_party/blimp_fonts/NotoSansGujaratiUI-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-a1ba64256d731eb3bdbf31446bbeedaa6c6d905e
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansGurmukhi-Bold.ttf.sha1 b/third_party/blimp_fonts/NotoSansGurmukhi-Bold.ttf.sha1
deleted file mode 100644
index eb08537..0000000
--- a/third_party/blimp_fonts/NotoSansGurmukhi-Bold.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-66b46c24dd6ece64d41283f0734ec23380bb6417
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansGurmukhi-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansGurmukhi-Regular.ttf.sha1
deleted file mode 100644
index 42f69e9..0000000
--- a/third_party/blimp_fonts/NotoSansGurmukhi-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-329adf9d083e73e6e0393dae62e281a991c8b103
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansGurmukhiUI-Bold.ttf.sha1 b/third_party/blimp_fonts/NotoSansGurmukhiUI-Bold.ttf.sha1
deleted file mode 100644
index 3eaf4b4..0000000
--- a/third_party/blimp_fonts/NotoSansGurmukhiUI-Bold.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-2410178072dcc690b52acc6897e778a0bffff452
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansGurmukhiUI-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansGurmukhiUI-Regular.ttf.sha1
deleted file mode 100644
index e0ea527..0000000
--- a/third_party/blimp_fonts/NotoSansGurmukhiUI-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-0eae03dbbad4d205e039651899ea9a5310736c6e
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansHanunoo-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansHanunoo-Regular.ttf.sha1
deleted file mode 100644
index 799bed7..0000000
--- a/third_party/blimp_fonts/NotoSansHanunoo-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-fe0cca164f425b39f8540da5b6463ce77bee640c
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansHebrew-Bold.ttf.sha1 b/third_party/blimp_fonts/NotoSansHebrew-Bold.ttf.sha1
deleted file mode 100644
index 87e69d1..0000000
--- a/third_party/blimp_fonts/NotoSansHebrew-Bold.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-d981044b3ff2607b13ad0051d3b3db7f88007748
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansHebrew-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansHebrew-Regular.ttf.sha1
deleted file mode 100644
index ae16cc0..0000000
--- a/third_party/blimp_fonts/NotoSansHebrew-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-083d168f4d033ce85bdc3919081e3880a6136578
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansImperialAramaic-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansImperialAramaic-Regular.ttf.sha1
deleted file mode 100644
index 240ff2f..0000000
--- a/third_party/blimp_fonts/NotoSansImperialAramaic-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-660288815e06bf6fb63f746012ca739958135bab
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansInscriptionalPahlavi-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansInscriptionalPahlavi-Regular.ttf.sha1
deleted file mode 100644
index e43ac54..0000000
--- a/third_party/blimp_fonts/NotoSansInscriptionalPahlavi-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-296c6ba342b1937b6c98ef7428a3bfbd9fed2df3
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansInscriptionalParthian-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansInscriptionalParthian-Regular.ttf.sha1
deleted file mode 100644
index e1e8f95..0000000
--- a/third_party/blimp_fonts/NotoSansInscriptionalParthian-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-097d726c7477b9261fb5bf01dc4686610a3fbc97
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansJP-Regular-Subsetted.otf.sha1 b/third_party/blimp_fonts/NotoSansJP-Regular-Subsetted.otf.sha1
deleted file mode 100644
index 7d4fce5..0000000
--- a/third_party/blimp_fonts/NotoSansJP-Regular-Subsetted.otf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-8afcd909334ce92647a82c2e4aaac408a93bf8ef
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansJP-Regular.otf.sha1 b/third_party/blimp_fonts/NotoSansJP-Regular.otf.sha1
deleted file mode 100644
index 2ad4564..0000000
--- a/third_party/blimp_fonts/NotoSansJP-Regular.otf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-685c52a8ad0b41098e85c099a6e5be0d09ef2f02
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansJavanese-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansJavanese-Regular.ttf.sha1
deleted file mode 100644
index 6eee177..0000000
--- a/third_party/blimp_fonts/NotoSansJavanese-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-2542883c305f0121e332c658aa8ee22813952fd2
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansKR-Regular.otf.sha1 b/third_party/blimp_fonts/NotoSansKR-Regular.otf.sha1
deleted file mode 100644
index b5396b3..0000000
--- a/third_party/blimp_fonts/NotoSansKR-Regular.otf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-82e49c4d7e4eced8a0bce49ef901a86459547d8c
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansKaithi-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansKaithi-Regular.ttf.sha1
deleted file mode 100644
index 277134f..0000000
--- a/third_party/blimp_fonts/NotoSansKaithi-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-7b6c562b4b0ed7891791a39e1a115eb363ac133f
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansKannada-Bold.ttf.sha1 b/third_party/blimp_fonts/NotoSansKannada-Bold.ttf.sha1
deleted file mode 100644
index 2d30174..0000000
--- a/third_party/blimp_fonts/NotoSansKannada-Bold.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-709a295c58dee0715dbb3c5d797006281afa6f87
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansKannada-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansKannada-Regular.ttf.sha1
deleted file mode 100644
index c000026..0000000
--- a/third_party/blimp_fonts/NotoSansKannada-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-d9293ef195260469a8b3e284e9e6c6e919381c19
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansKannadaUI-Bold.ttf.sha1 b/third_party/blimp_fonts/NotoSansKannadaUI-Bold.ttf.sha1
deleted file mode 100644
index 20a8884..0000000
--- a/third_party/blimp_fonts/NotoSansKannadaUI-Bold.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-0803c674ee4f28199fca9c9624886f3c899a6d1c
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansKannadaUI-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansKannadaUI-Regular.ttf.sha1
deleted file mode 100644
index 9e6e64f6..0000000
--- a/third_party/blimp_fonts/NotoSansKannadaUI-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-d053741efb996673ba31f1322734148fc95ee13c
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansKayahLi-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansKayahLi-Regular.ttf.sha1
deleted file mode 100644
index ba70921..0000000
--- a/third_party/blimp_fonts/NotoSansKayahLi-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-870b4a50663afb8af3f661ebc3e18ca7a6dda8d3
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansKharoshthi-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansKharoshthi-Regular.ttf.sha1
deleted file mode 100644
index 4587667..0000000
--- a/third_party/blimp_fonts/NotoSansKharoshthi-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-4e09bd089479532dd29d222ad958e58497038b86
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansKhmer-Bold.ttf.sha1 b/third_party/blimp_fonts/NotoSansKhmer-Bold.ttf.sha1
deleted file mode 100644
index 9876e5b..0000000
--- a/third_party/blimp_fonts/NotoSansKhmer-Bold.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-680eddbf617b19705a0e067e582da240281b599e
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansKhmer-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansKhmer-Regular.ttf.sha1
deleted file mode 100644
index d77a6ac..0000000
--- a/third_party/blimp_fonts/NotoSansKhmer-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-0b7a86319c4f2e19b861d0a9acc92b7670245da2
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansKhmerUI-Bold.ttf.sha1 b/third_party/blimp_fonts/NotoSansKhmerUI-Bold.ttf.sha1
deleted file mode 100644
index 036cb9d..0000000
--- a/third_party/blimp_fonts/NotoSansKhmerUI-Bold.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-377f97bb928e4634e779d30c2791dec8416ea49f
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansKhmerUI-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansKhmerUI-Regular.ttf.sha1
deleted file mode 100644
index 626c7f0..0000000
--- a/third_party/blimp_fonts/NotoSansKhmerUI-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-cea1075973e5f15a4a5073ef2f46679e62e6e6a1
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansLao-Bold.ttf.sha1 b/third_party/blimp_fonts/NotoSansLao-Bold.ttf.sha1
deleted file mode 100644
index ff05d6e..0000000
--- a/third_party/blimp_fonts/NotoSansLao-Bold.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-4fc0c98ee2c4942f44ce6b48b58a49c5cb0c8be0
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansLao-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansLao-Regular.ttf.sha1
deleted file mode 100644
index 6c3c40e..0000000
--- a/third_party/blimp_fonts/NotoSansLao-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-ad401524474b290c3ae2703e5310e37ef604b58b
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansLaoUI-Bold.ttf.sha1 b/third_party/blimp_fonts/NotoSansLaoUI-Bold.ttf.sha1
deleted file mode 100644
index 60d9cd5..0000000
--- a/third_party/blimp_fonts/NotoSansLaoUI-Bold.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-c8e61bb2c6484c32f3a6f7a9dc5af6b550f78baf
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansLaoUI-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansLaoUI-Regular.ttf.sha1
deleted file mode 100644
index 46d37b2..0000000
--- a/third_party/blimp_fonts/NotoSansLaoUI-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-d417ad2d7239079958c786123b885e483d771b26
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansLepcha-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansLepcha-Regular.ttf.sha1
deleted file mode 100644
index a6b40a7..0000000
--- a/third_party/blimp_fonts/NotoSansLepcha-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-fdb5fad01f714ad8f84637a2a31db004e6e670c8
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansLimbu-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansLimbu-Regular.ttf.sha1
deleted file mode 100644
index 54accd2c..0000000
--- a/third_party/blimp_fonts/NotoSansLimbu-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-5a13f322a26cd1247dc8b88056952faad256b6c9
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansLinearB-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansLinearB-Regular.ttf.sha1
deleted file mode 100644
index f73226f..0000000
--- a/third_party/blimp_fonts/NotoSansLinearB-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-df9cba01d31a0309b9c2a0e9f01f2aec5ffe70da
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansLisu-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansLisu-Regular.ttf.sha1
deleted file mode 100644
index bb0e9b4..0000000
--- a/third_party/blimp_fonts/NotoSansLisu-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-bf95b975fb4f961167c71c5836ea7a4660931b03
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansLycian-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansLycian-Regular.ttf.sha1
deleted file mode 100644
index e069c167..0000000
--- a/third_party/blimp_fonts/NotoSansLycian-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-da92da0f24ad080c36190c2f18f942daaad2868e
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansLydian-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansLydian-Regular.ttf.sha1
deleted file mode 100644
index ee5710b..0000000
--- a/third_party/blimp_fonts/NotoSansLydian-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-a2f852b9b962d07e72af6304299ef0d435f05bd1
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansMalayalam-Bold.ttf.sha1 b/third_party/blimp_fonts/NotoSansMalayalam-Bold.ttf.sha1
deleted file mode 100644
index 6d6fb1d..0000000
--- a/third_party/blimp_fonts/NotoSansMalayalam-Bold.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-e020a0103265f2c1dd71261bb6dfdd0ad18bbeab
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansMalayalam-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansMalayalam-Regular.ttf.sha1
deleted file mode 100644
index 3c93dd9..0000000
--- a/third_party/blimp_fonts/NotoSansMalayalam-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-0e3b4ad160c5e8ffdbe262492b33d2f425e836dc
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansMalayalamUI-Bold.ttf.sha1 b/third_party/blimp_fonts/NotoSansMalayalamUI-Bold.ttf.sha1
deleted file mode 100644
index 8108cdb..0000000
--- a/third_party/blimp_fonts/NotoSansMalayalamUI-Bold.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-00d98bf5b71b2c2715f9fb04168129b7b19d9385
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansMalayalamUI-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansMalayalamUI-Regular.ttf.sha1
deleted file mode 100644
index 713700a..0000000
--- a/third_party/blimp_fonts/NotoSansMalayalamUI-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-67d3ad87a313ae88628c67c89b03624aa9b6649f
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansMandaic-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansMandaic-Regular.ttf.sha1
deleted file mode 100644
index 6a8c1984..0000000
--- a/third_party/blimp_fonts/NotoSansMandaic-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-370382717a5a166f90343f68f365d5c932f768f5
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansMeeteiMayek-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansMeeteiMayek-Regular.ttf.sha1
deleted file mode 100644
index 9fd61668..0000000
--- a/third_party/blimp_fonts/NotoSansMeeteiMayek-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-0e3e035dcb6244602125b17e3f374e79583088b7
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansMongolian-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansMongolian-Regular.ttf.sha1
deleted file mode 100644
index 8c3bea8..0000000
--- a/third_party/blimp_fonts/NotoSansMongolian-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-514c23daa829d986fb83ce1db7e0db97b6983a72
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansMyanmar-Bold.ttf.sha1 b/third_party/blimp_fonts/NotoSansMyanmar-Bold.ttf.sha1
deleted file mode 100644
index a77727e..0000000
--- a/third_party/blimp_fonts/NotoSansMyanmar-Bold.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-eb1bc4722a6e4c62b2d746a6d6a2f90de480821f
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansMyanmar-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansMyanmar-Regular.ttf.sha1
deleted file mode 100644
index b3056c0..0000000
--- a/third_party/blimp_fonts/NotoSansMyanmar-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-0469de145d807dc3a7565f2d7da1867042ec8e7a
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansMyanmarUI-Bold.ttf.sha1 b/third_party/blimp_fonts/NotoSansMyanmarUI-Bold.ttf.sha1
deleted file mode 100644
index c9f06d0..0000000
--- a/third_party/blimp_fonts/NotoSansMyanmarUI-Bold.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-594b7d3d54bfe2edbf073f044bcba39b9a75a8bf
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansMyanmarUI-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansMyanmarUI-Regular.ttf.sha1
deleted file mode 100644
index a48da98..0000000
--- a/third_party/blimp_fonts/NotoSansMyanmarUI-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-42a45af174c35216b596085e646425a768717952
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansNKo-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansNKo-Regular.ttf.sha1
deleted file mode 100644
index 29bbdf5..0000000
--- a/third_party/blimp_fonts/NotoSansNKo-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-335ea7c2d3be7d88a1ebfaa0de41336037ec2595
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansNewTaiLue-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansNewTaiLue-Regular.ttf.sha1
deleted file mode 100644
index 3c52e91..0000000
--- a/third_party/blimp_fonts/NotoSansNewTaiLue-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-81a9a9c1d9a4c29b41bca01418108d52216b5559
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansOgham-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansOgham-Regular.ttf.sha1
deleted file mode 100644
index abec25e..0000000
--- a/third_party/blimp_fonts/NotoSansOgham-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-18f2332625c8aadb2e0359164a23ea60bf3bb306
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansOlChiki-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansOlChiki-Regular.ttf.sha1
deleted file mode 100644
index 6cdd6d60..0000000
--- a/third_party/blimp_fonts/NotoSansOlChiki-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-0ece2465241ff335139f95589d55f0e42274f81b
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansOldItalic-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansOldItalic-Regular.ttf.sha1
deleted file mode 100644
index f53ed579..0000000
--- a/third_party/blimp_fonts/NotoSansOldItalic-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-e92907af55b187bb9ebb1e2fbbb1341c07d9f01f
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansOldPersian-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansOldPersian-Regular.ttf.sha1
deleted file mode 100644
index c24c8e3b..0000000
--- a/third_party/blimp_fonts/NotoSansOldPersian-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-f3169cd736266f67a6909d588de7dc77389cb219
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansOldSouthArabian-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansOldSouthArabian-Regular.ttf.sha1
deleted file mode 100644
index ff115366..0000000
--- a/third_party/blimp_fonts/NotoSansOldSouthArabian-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-a858eff985bb1b94112bc38ce783594c4f2678a7
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansOldTurkic-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansOldTurkic-Regular.ttf.sha1
deleted file mode 100644
index 149144a1..0000000
--- a/third_party/blimp_fonts/NotoSansOldTurkic-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-65662c0178078729fec1dd0e74549e687ea09ed7
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansOriya-Bold.ttf.sha1 b/third_party/blimp_fonts/NotoSansOriya-Bold.ttf.sha1
deleted file mode 100644
index 7e7e7c7..0000000
--- a/third_party/blimp_fonts/NotoSansOriya-Bold.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-05f5bae5d05f853a6cc4b3a24849aec652c90718
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansOriya-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansOriya-Regular.ttf.sha1
deleted file mode 100644
index 712235d..0000000
--- a/third_party/blimp_fonts/NotoSansOriya-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-b0635a39a23b71f88085c403b3aef269bf7b58c4
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansOriyaUI-Bold.ttf.sha1 b/third_party/blimp_fonts/NotoSansOriyaUI-Bold.ttf.sha1
deleted file mode 100644
index 98c0488..0000000
--- a/third_party/blimp_fonts/NotoSansOriyaUI-Bold.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-541170c878075daadfcf1d2a792b6a7312fd4096
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansOriyaUI-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansOriyaUI-Regular.ttf.sha1
deleted file mode 100644
index c0e2598a..0000000
--- a/third_party/blimp_fonts/NotoSansOriyaUI-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-931f507e2ed32d87284c8109ffe027f1e795aaed
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansOsmanya-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansOsmanya-Regular.ttf.sha1
deleted file mode 100644
index 0c6e3681..0000000
--- a/third_party/blimp_fonts/NotoSansOsmanya-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-ec7b494463ee46dffae8e7d4e234c43dc004ec60
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansPhagsPa-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansPhagsPa-Regular.ttf.sha1
deleted file mode 100644
index 6fba4c3..0000000
--- a/third_party/blimp_fonts/NotoSansPhagsPa-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-feead638b84c697d770d49c18e6e0a8fdfa62ce9
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansPhoenician-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansPhoenician-Regular.ttf.sha1
deleted file mode 100644
index 3dead6e..0000000
--- a/third_party/blimp_fonts/NotoSansPhoenician-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-59f539be1b6bc8b4e86be3437e1693cc896948c0
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansRejang-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansRejang-Regular.ttf.sha1
deleted file mode 100644
index f917711..0000000
--- a/third_party/blimp_fonts/NotoSansRejang-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-34c7b71548c9b532167b08facb1c871bb4196056
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansRunic-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansRunic-Regular.ttf.sha1
deleted file mode 100644
index ca2daa76..0000000
--- a/third_party/blimp_fonts/NotoSansRunic-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-78e7364b4d720528c62ef2038154c78e92c17444
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansSC-Regular.otf.sha1 b/third_party/blimp_fonts/NotoSansSC-Regular.otf.sha1
deleted file mode 100644
index e74636c..0000000
--- a/third_party/blimp_fonts/NotoSansSC-Regular.otf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-fd0e99f14fe21661a0d528fb9882c833979f3386
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansSamaritan-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansSamaritan-Regular.ttf.sha1
deleted file mode 100644
index 5172b5d..0000000
--- a/third_party/blimp_fonts/NotoSansSamaritan-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-91bbc172f85eb4f3ae37a8b98128d3ea5dc0e7cf
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansSaurashtra-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansSaurashtra-Regular.ttf.sha1
deleted file mode 100644
index b677b37..0000000
--- a/third_party/blimp_fonts/NotoSansSaurashtra-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-6e338de732880469c09e61f5de509189f05225f3
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansShavian-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansShavian-Regular.ttf.sha1
deleted file mode 100644
index bdaf32b..0000000
--- a/third_party/blimp_fonts/NotoSansShavian-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-eb7afe2ae1fd731c6d7e061403589a48df76da0d
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansSinhala-Bold.ttf.sha1 b/third_party/blimp_fonts/NotoSansSinhala-Bold.ttf.sha1
deleted file mode 100644
index 0be0a3d..0000000
--- a/third_party/blimp_fonts/NotoSansSinhala-Bold.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-ff78425befdaf0bdd24b97a075e66819665ab257
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansSinhala-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansSinhala-Regular.ttf.sha1
deleted file mode 100644
index 08a75bb2..0000000
--- a/third_party/blimp_fonts/NotoSansSinhala-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-c3dcca37adf3b98add716876f93e30e7d28d5730
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansSundanese-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansSundanese-Regular.ttf.sha1
deleted file mode 100644
index 74936e46..0000000
--- a/third_party/blimp_fonts/NotoSansSundanese-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-b8990d9647be086ff2ef3c2eeae53536ec3cd98f
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansSylotiNagri-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansSylotiNagri-Regular.ttf.sha1
deleted file mode 100644
index 133b5f5..0000000
--- a/third_party/blimp_fonts/NotoSansSylotiNagri-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-a862f457f067fde48161f6865d9418643b37c029
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansSymbols-Regular-Subsetted.ttf.sha1 b/third_party/blimp_fonts/NotoSansSymbols-Regular-Subsetted.ttf.sha1
deleted file mode 100644
index 1f18c96..0000000
--- a/third_party/blimp_fonts/NotoSansSymbols-Regular-Subsetted.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-e5e8d7c88162df4cfe8cd6405bafa3d3b1cc3166
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansSymbols-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansSymbols-Regular.ttf.sha1
deleted file mode 100644
index 7cd8f19..0000000
--- a/third_party/blimp_fonts/NotoSansSymbols-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-8b4ac8bf6c801dd39ccadde9f12bade82615f35a
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansSyriacEastern-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansSyriacEastern-Regular.ttf.sha1
deleted file mode 100644
index 35096cb..0000000
--- a/third_party/blimp_fonts/NotoSansSyriacEastern-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-fdba9e07d99e4a95d248fa7ef9eb96e969859e62
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansSyriacEstrangela-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansSyriacEstrangela-Regular.ttf.sha1
deleted file mode 100644
index e54fa50..0000000
--- a/third_party/blimp_fonts/NotoSansSyriacEstrangela-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-7834dfb6bfd02a0b35bcbc23b6ab1d0caa681af6
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansSyriacWestern-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansSyriacWestern-Regular.ttf.sha1
deleted file mode 100644
index 511afba4..0000000
--- a/third_party/blimp_fonts/NotoSansSyriacWestern-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-15443875b09c934e251da0c8653a12a44264278a
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansTC-Regular.otf.sha1 b/third_party/blimp_fonts/NotoSansTC-Regular.otf.sha1
deleted file mode 100644
index 4cb9f878..0000000
--- a/third_party/blimp_fonts/NotoSansTC-Regular.otf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-2c4bf5559ca000201c572fc05d46d7b9b4ac9de4
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansTagalog-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansTagalog-Regular.ttf.sha1
deleted file mode 100644
index 1b6b6db..0000000
--- a/third_party/blimp_fonts/NotoSansTagalog-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-c11711b924f9c0b20716cb82625e4fada3d0c33b
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansTagbanwa-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansTagbanwa-Regular.ttf.sha1
deleted file mode 100644
index 082e917..0000000
--- a/third_party/blimp_fonts/NotoSansTagbanwa-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-e933217646423187bac1196bd2c1ab3ba48adf4d
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansTaiLe-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansTaiLe-Regular.ttf.sha1
deleted file mode 100644
index ea0a2fe..0000000
--- a/third_party/blimp_fonts/NotoSansTaiLe-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-155df213be34c45269925ea1581354ec02179c03
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansTaiTham-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansTaiTham-Regular.ttf.sha1
deleted file mode 100644
index fd3c0a0..0000000
--- a/third_party/blimp_fonts/NotoSansTaiTham-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-0d1bf0f83c66ea3b92deaaeafa3bd5466a54ee7f
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansTaiViet-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansTaiViet-Regular.ttf.sha1
deleted file mode 100644
index b79c3d4..0000000
--- a/third_party/blimp_fonts/NotoSansTaiViet-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-508064c86453713ed578ab1428b2686a813501f7
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansTamil-Bold.ttf.sha1 b/third_party/blimp_fonts/NotoSansTamil-Bold.ttf.sha1
deleted file mode 100644
index ef28710..0000000
--- a/third_party/blimp_fonts/NotoSansTamil-Bold.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-8f3644c86def39f6bb79631b28ef1174108a63fa
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansTamil-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansTamil-Regular.ttf.sha1
deleted file mode 100644
index feb6fc8..0000000
--- a/third_party/blimp_fonts/NotoSansTamil-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-49635e1da5596cd05c764398dfb347dc6ae81ea0
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansTamilUI-Bold.ttf.sha1 b/third_party/blimp_fonts/NotoSansTamilUI-Bold.ttf.sha1
deleted file mode 100644
index f334b54c..0000000
--- a/third_party/blimp_fonts/NotoSansTamilUI-Bold.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-89142481ceb5891f31f5e56420299e32ffd466a2
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansTamilUI-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansTamilUI-Regular.ttf.sha1
deleted file mode 100644
index 44a87b7..0000000
--- a/third_party/blimp_fonts/NotoSansTamilUI-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-7a05209d7198ca0b0a324770f74998e312e5a57f
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansTelugu-Bold.ttf.sha1 b/third_party/blimp_fonts/NotoSansTelugu-Bold.ttf.sha1
deleted file mode 100644
index 70cf710..0000000
--- a/third_party/blimp_fonts/NotoSansTelugu-Bold.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-14a8d5b42b1670b0b1673ef92e562f16b6b4d5f5
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansTelugu-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansTelugu-Regular.ttf.sha1
deleted file mode 100644
index d45d2091..0000000
--- a/third_party/blimp_fonts/NotoSansTelugu-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-439d61e6aacbf4ce5826b863d5075ce9bbbdae34
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansTeluguUI-Bold.ttf.sha1 b/third_party/blimp_fonts/NotoSansTeluguUI-Bold.ttf.sha1
deleted file mode 100644
index c2187e21..0000000
--- a/third_party/blimp_fonts/NotoSansTeluguUI-Bold.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-5af88b54631e6b70162ae063903955bbe3cd2f8b
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansTeluguUI-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansTeluguUI-Regular.ttf.sha1
deleted file mode 100644
index 5d7b35b5..0000000
--- a/third_party/blimp_fonts/NotoSansTeluguUI-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-923e09cbca1ad94f2c0ac9932d9b5db784fcfa25
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansThaana-Bold.ttf.sha1 b/third_party/blimp_fonts/NotoSansThaana-Bold.ttf.sha1
deleted file mode 100644
index 103cea2..0000000
--- a/third_party/blimp_fonts/NotoSansThaana-Bold.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-9585cb2672e485f86216870a450e22ef9125fd33
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansThaana-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansThaana-Regular.ttf.sha1
deleted file mode 100644
index e475a9d..0000000
--- a/third_party/blimp_fonts/NotoSansThaana-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-bc685050058ca472fdd67f8a7a43699252bbf3ef
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansThai-Bold.ttf.sha1 b/third_party/blimp_fonts/NotoSansThai-Bold.ttf.sha1
deleted file mode 100644
index f97107a..0000000
--- a/third_party/blimp_fonts/NotoSansThai-Bold.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-f9332a74751a1c9a8ae5915a094279e8a716387f
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansThai-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansThai-Regular.ttf.sha1
deleted file mode 100644
index c91bff1e..0000000
--- a/third_party/blimp_fonts/NotoSansThai-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-c4fa534578248260321cc8da6a090dc021c47126
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansThaiUI-Bold.ttf.sha1 b/third_party/blimp_fonts/NotoSansThaiUI-Bold.ttf.sha1
deleted file mode 100644
index b6962b8..0000000
--- a/third_party/blimp_fonts/NotoSansThaiUI-Bold.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-a3d4349b3cf5e8b737ebad1eea37f86f3274749d
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansThaiUI-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansThaiUI-Regular.ttf.sha1
deleted file mode 100644
index 7b7a483..0000000
--- a/third_party/blimp_fonts/NotoSansThaiUI-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-947be6d319b4a67796fe3410d64d365ff1bc5d7c
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansTibetan-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansTibetan-Regular.ttf.sha1
deleted file mode 100644
index dc5c23c..0000000
--- a/third_party/blimp_fonts/NotoSansTibetan-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-4b769855dc15edebf6d6e13afdc044c96c98c680
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansTifinagh-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansTifinagh-Regular.ttf.sha1
deleted file mode 100644
index 42d4b27bb..0000000
--- a/third_party/blimp_fonts/NotoSansTifinagh-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-e8600002e8d4e60a43c9c4084b527aa25d8ed1c4
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansUI-Bold.ttf.sha1 b/third_party/blimp_fonts/NotoSansUI-Bold.ttf.sha1
deleted file mode 100644
index 488e798..0000000
--- a/third_party/blimp_fonts/NotoSansUI-Bold.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-f8c365a95bdd3a4d60bdb6c43995660223afaee0
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansUI-BoldItalic.ttf.sha1 b/third_party/blimp_fonts/NotoSansUI-BoldItalic.ttf.sha1
deleted file mode 100644
index 0601892..0000000
--- a/third_party/blimp_fonts/NotoSansUI-BoldItalic.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-efe7c88a6fb0c7711cc29ec4206c93dba319150b
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansUI-Italic.ttf.sha1 b/third_party/blimp_fonts/NotoSansUI-Italic.ttf.sha1
deleted file mode 100644
index 84f7ac5..0000000
--- a/third_party/blimp_fonts/NotoSansUI-Italic.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-9cf96f38e211a21d71a2c21f2c5e6e2ee34024eb
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansUI-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansUI-Regular.ttf.sha1
deleted file mode 100644
index ef4bb52..0000000
--- a/third_party/blimp_fonts/NotoSansUI-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-6930143f0077b8e43b0677df8739e7a3c30caa69
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansUgaritic-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansUgaritic-Regular.ttf.sha1
deleted file mode 100644
index 6cf0e7d..0000000
--- a/third_party/blimp_fonts/NotoSansUgaritic-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-8f8ebc30c66a06dbe2997b1a07e0668e105ed067
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansVai-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansVai-Regular.ttf.sha1
deleted file mode 100644
index 1502e6a..0000000
--- a/third_party/blimp_fonts/NotoSansVai-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-4ce9208384bfb5a21767ab85311837277d8b9978
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSansYi-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSansYi-Regular.ttf.sha1
deleted file mode 100644
index 66d1962..0000000
--- a/third_party/blimp_fonts/NotoSansYi-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-ea20e1e87a943b37262ab10e3003525861d95d60
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSerif-Bold.ttf.sha1 b/third_party/blimp_fonts/NotoSerif-Bold.ttf.sha1
deleted file mode 100644
index f9bf271..0000000
--- a/third_party/blimp_fonts/NotoSerif-Bold.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-82b243fd7bdba883b5a6a73ac6d68b3da1b3b97b
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSerif-BoldItalic.ttf.sha1 b/third_party/blimp_fonts/NotoSerif-BoldItalic.ttf.sha1
deleted file mode 100644
index 6800f8f9..0000000
--- a/third_party/blimp_fonts/NotoSerif-BoldItalic.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-39141b42604ed41d8a6d85366c775cded1d6752c
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSerif-Italic.ttf.sha1 b/third_party/blimp_fonts/NotoSerif-Italic.ttf.sha1
deleted file mode 100644
index fccb33ec..0000000
--- a/third_party/blimp_fonts/NotoSerif-Italic.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-2e2e8b537d7d86e1f5c2e0d3338720d0d853c09f
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSerif-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSerif-Regular.ttf.sha1
deleted file mode 100644
index d77fdd1..0000000
--- a/third_party/blimp_fonts/NotoSerif-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-8608d1f96bb9482ea8942ebd6545cdb9e2921ed9
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSerifArmenian-Bold.ttf.sha1 b/third_party/blimp_fonts/NotoSerifArmenian-Bold.ttf.sha1
deleted file mode 100644
index 12b87be..0000000
--- a/third_party/blimp_fonts/NotoSerifArmenian-Bold.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-d9952506333e6076a6ad1fe237b590d3a124e3da
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSerifArmenian-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSerifArmenian-Regular.ttf.sha1
deleted file mode 100644
index e511251..0000000
--- a/third_party/blimp_fonts/NotoSerifArmenian-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-54fffecfd5fb8f33fa0b88d752a532dd767b8d90
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSerifGeorgian-Bold.ttf.sha1 b/third_party/blimp_fonts/NotoSerifGeorgian-Bold.ttf.sha1
deleted file mode 100644
index 7a018ab..0000000
--- a/third_party/blimp_fonts/NotoSerifGeorgian-Bold.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-fd2cc6de838f77ac7692725d249e29443560a8bc
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSerifGeorgian-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSerifGeorgian-Regular.ttf.sha1
deleted file mode 100644
index f7247c43..0000000
--- a/third_party/blimp_fonts/NotoSerifGeorgian-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-16c1f30c13622a6a080d910ea5db3fa7815c11e8
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSerifKhmer-Bold.ttf.sha1 b/third_party/blimp_fonts/NotoSerifKhmer-Bold.ttf.sha1
deleted file mode 100644
index 31bc23f..0000000
--- a/third_party/blimp_fonts/NotoSerifKhmer-Bold.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-fcb63dfd57dc35d81eef4d9b91598f6e7e93000c
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSerifKhmer-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSerifKhmer-Regular.ttf.sha1
deleted file mode 100644
index e778e05..0000000
--- a/third_party/blimp_fonts/NotoSerifKhmer-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-a4000457e9f5db03fd4161ed420b9e426bdb0d87
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSerifLao-Bold.ttf.sha1 b/third_party/blimp_fonts/NotoSerifLao-Bold.ttf.sha1
deleted file mode 100644
index 911d2960..0000000
--- a/third_party/blimp_fonts/NotoSerifLao-Bold.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-ab67b00c5092b0094af2ad54cfdb9018b8299ab4
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSerifLao-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSerifLao-Regular.ttf.sha1
deleted file mode 100644
index a809edda..0000000
--- a/third_party/blimp_fonts/NotoSerifLao-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-cca411f1874c4a03386078b0712ca849e8a7f9bf
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSerifThai-Bold.ttf.sha1 b/third_party/blimp_fonts/NotoSerifThai-Bold.ttf.sha1
deleted file mode 100644
index 668c5a31..0000000
--- a/third_party/blimp_fonts/NotoSerifThai-Bold.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-ced1a6c362d127948b5a4d36548732f9de033c1d
\ No newline at end of file
diff --git a/third_party/blimp_fonts/NotoSerifThai-Regular.ttf.sha1 b/third_party/blimp_fonts/NotoSerifThai-Regular.ttf.sha1
deleted file mode 100644
index c5831fcc..0000000
--- a/third_party/blimp_fonts/NotoSerifThai-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-8db9bbb5f1d3f71829a4130d953b676c8bdf0625
\ No newline at end of file
diff --git a/third_party/blimp_fonts/OWNERS b/third_party/blimp_fonts/OWNERS
deleted file mode 100644
index d7dfb92..0000000
--- a/third_party/blimp_fonts/OWNERS
+++ /dev/null
@@ -1,5 +0,0 @@
-dtrainor@chromium.org
-haibinlu@chromium.org
-kmarshall@chromium.org
-nyquist@chromium.org
-wez@chromium.org
diff --git a/third_party/blimp_fonts/README.chromium b/third_party/blimp_fonts/README.chromium
deleted file mode 100644
index 380be7c8..0000000
--- a/third_party/blimp_fonts/README.chromium
+++ /dev/null
@@ -1,49 +0,0 @@
-Name: blimp_fonts
-URL: See below
-Version: unknown
-License: Apache Version 2.0 and SIL Open Font License, Version 1.1
-Security Critical: yes
-
-Description:
-A collection of fonts that are necessary to bundle with the blimp engine to be
-able to render the correct fonts for different clients.
-
-How to update:
-See //blimp/docs/fonts.md.
-
-Local Modifications:
-Not all files from the external repositories are used.
-- *.otf, *.ttf: From the various repositories.
-- .gitignore:   Added.
-- BUILD.gn:     Added.
-- LICENSE:      Added.
-- LICENSE.*:    Extracted from license files in the various repositories.
-- README.md:    Added.
-- fonts.xml:    From this repository:
-                https://android.googlesource.com/platform/frameworks/base.git
-
-Fonts are pulled from the following repositories:
-- Git repo: https://android.googlesource.com/platform/frameworks/base.git
-  Commit: 6a278db4c4a144829353e81420f28dcf2105f767
-  Directory: data/fonts/
-- Git repo: https://android.googlesource.com/platform/external/noto-fonts.git
-  Commit: eb0883544dd538edbfb52cce9a2481509ca5ee9f
-  Directory: cjk/, other/
-- Git repo: https://android.googlesource.com/platform/external/roboto-fonts.git
-  Commit: f5cf79102af594c746627b392b4f98eedd254571
-  Directory: .
-- Git repo: https://android.googlesource.com/platform/external/google-fonts/dancing-script.git
-  Commit: 7b6623bd54cee3e48ae8a4f477f616366643cc78
-  Directory: .
-- Git repo: https://android.googlesource.com/platform/external/google-fonts/cutive-mono.git
-  Commit: bce2136662854076023066602526ba299e6556b2
-  Directory: .
-- Git repo: https://android.googlesource.com/platform/external/google-fonts/coming-soon.git
-  Commit: 2c5cb418c690815545bbb0316eae5fd33b9fc859
-  Directory: .
-- Git repo: https://android.googlesource.com/platform/external/google-fonts/carrois-gothic-sc.git
-  Commit: 0062a10458d4c357f3082d66bcb129d11913aaae
-  Directory: .
-- Git repo: https://android.googlesource.com/platform/external/naver-fonts.git
-  Commit: 91e6e9f94d1d769a8f742649674149ba98ce7d45
-  Directory: .
diff --git a/third_party/blimp_fonts/Roboto-Black.ttf.sha1 b/third_party/blimp_fonts/Roboto-Black.ttf.sha1
deleted file mode 100644
index 6ee8a62..0000000
--- a/third_party/blimp_fonts/Roboto-Black.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-d3ecadec65a1ed2765a0f6b47b6bf2000e8491d5
\ No newline at end of file
diff --git a/third_party/blimp_fonts/Roboto-BlackItalic.ttf.sha1 b/third_party/blimp_fonts/Roboto-BlackItalic.ttf.sha1
deleted file mode 100644
index 9b159021..0000000
--- a/third_party/blimp_fonts/Roboto-BlackItalic.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-82960419d7bdadc88fa3a94a016bd93538666769
\ No newline at end of file
diff --git a/third_party/blimp_fonts/Roboto-Bold.ttf.sha1 b/third_party/blimp_fonts/Roboto-Bold.ttf.sha1
deleted file mode 100644
index 59a0f18a..0000000
--- a/third_party/blimp_fonts/Roboto-Bold.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-ce209e7a825828599429bf4d0d134272d20adf3d
\ No newline at end of file
diff --git a/third_party/blimp_fonts/Roboto-BoldItalic.ttf.sha1 b/third_party/blimp_fonts/Roboto-BoldItalic.ttf.sha1
deleted file mode 100644
index 20dad84..0000000
--- a/third_party/blimp_fonts/Roboto-BoldItalic.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-0982eed1d138c584407ac6dd04448eb643bef2b0
\ No newline at end of file
diff --git a/third_party/blimp_fonts/Roboto-Italic.ttf.sha1 b/third_party/blimp_fonts/Roboto-Italic.ttf.sha1
deleted file mode 100644
index c875f750..0000000
--- a/third_party/blimp_fonts/Roboto-Italic.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-d701e916ba7ef08efef9b924b0e220ac0623a75a
\ No newline at end of file
diff --git a/third_party/blimp_fonts/Roboto-Light.ttf.sha1 b/third_party/blimp_fonts/Roboto-Light.ttf.sha1
deleted file mode 100644
index c62d9d0..0000000
--- a/third_party/blimp_fonts/Roboto-Light.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-1ce31afef046a5f38dbcb6e212d827eb69d56569
\ No newline at end of file
diff --git a/third_party/blimp_fonts/Roboto-LightItalic.ttf.sha1 b/third_party/blimp_fonts/Roboto-LightItalic.ttf.sha1
deleted file mode 100644
index 5aac8f52..0000000
--- a/third_party/blimp_fonts/Roboto-LightItalic.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-a2ec190ac6d148c53128eb1ed61c638b3006ed5d
\ No newline at end of file
diff --git a/third_party/blimp_fonts/Roboto-Medium.ttf.sha1 b/third_party/blimp_fonts/Roboto-Medium.ttf.sha1
deleted file mode 100644
index ebce56d..0000000
--- a/third_party/blimp_fonts/Roboto-Medium.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-92d678bb9f3c07deabfaa4e62b9de0aeab45888a
\ No newline at end of file
diff --git a/third_party/blimp_fonts/Roboto-MediumItalic.ttf.sha1 b/third_party/blimp_fonts/Roboto-MediumItalic.ttf.sha1
deleted file mode 100644
index 943de92..0000000
--- a/third_party/blimp_fonts/Roboto-MediumItalic.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-4bc89e68bb659347904cae4543e9e22eb06e43dc
\ No newline at end of file
diff --git a/third_party/blimp_fonts/Roboto-Regular.ttf.sha1 b/third_party/blimp_fonts/Roboto-Regular.ttf.sha1
deleted file mode 100644
index ce967ad..0000000
--- a/third_party/blimp_fonts/Roboto-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-9475dcae6d4d43961baecbe3049d70eaef1ba2e2
\ No newline at end of file
diff --git a/third_party/blimp_fonts/Roboto-Thin.ttf.sha1 b/third_party/blimp_fonts/Roboto-Thin.ttf.sha1
deleted file mode 100644
index 2c13ddc..0000000
--- a/third_party/blimp_fonts/Roboto-Thin.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-a1d984651a0481e5232ee925e2c37895a375d11c
\ No newline at end of file
diff --git a/third_party/blimp_fonts/Roboto-ThinItalic.ttf.sha1 b/third_party/blimp_fonts/Roboto-ThinItalic.ttf.sha1
deleted file mode 100644
index dfdff321..0000000
--- a/third_party/blimp_fonts/Roboto-ThinItalic.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-e828ca5fede8ae7dc78a09a718506412fe8851a7
\ No newline at end of file
diff --git a/third_party/blimp_fonts/RobotoCondensed-Bold.ttf.sha1 b/third_party/blimp_fonts/RobotoCondensed-Bold.ttf.sha1
deleted file mode 100644
index a28bd78..0000000
--- a/third_party/blimp_fonts/RobotoCondensed-Bold.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-ddd594ab7c3b7e2a0a36fd812afe2ec40c509fce
\ No newline at end of file
diff --git a/third_party/blimp_fonts/RobotoCondensed-BoldItalic.ttf.sha1 b/third_party/blimp_fonts/RobotoCondensed-BoldItalic.ttf.sha1
deleted file mode 100644
index 7987f563..0000000
--- a/third_party/blimp_fonts/RobotoCondensed-BoldItalic.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-ca1359cb1d5d82a8d7956e4b469bd031e63b5ab3
\ No newline at end of file
diff --git a/third_party/blimp_fonts/RobotoCondensed-Italic.ttf.sha1 b/third_party/blimp_fonts/RobotoCondensed-Italic.ttf.sha1
deleted file mode 100644
index 00db36f..0000000
--- a/third_party/blimp_fonts/RobotoCondensed-Italic.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-fd09eff1019edb33d3d3a4af9c9e8efd109eff06
\ No newline at end of file
diff --git a/third_party/blimp_fonts/RobotoCondensed-Light.ttf.sha1 b/third_party/blimp_fonts/RobotoCondensed-Light.ttf.sha1
deleted file mode 100644
index 6038de8..0000000
--- a/third_party/blimp_fonts/RobotoCondensed-Light.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-810a20524f675f6633de3a6ee0a5cdd5741c5139
\ No newline at end of file
diff --git a/third_party/blimp_fonts/RobotoCondensed-LightItalic.ttf.sha1 b/third_party/blimp_fonts/RobotoCondensed-LightItalic.ttf.sha1
deleted file mode 100644
index af7a5747..0000000
--- a/third_party/blimp_fonts/RobotoCondensed-LightItalic.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-66891ba5c00b998aa4796f95191b2d3864e7d07a
\ No newline at end of file
diff --git a/third_party/blimp_fonts/RobotoCondensed-Regular.ttf.sha1 b/third_party/blimp_fonts/RobotoCondensed-Regular.ttf.sha1
deleted file mode 100644
index 4cb0246..0000000
--- a/third_party/blimp_fonts/RobotoCondensed-Regular.ttf.sha1
+++ /dev/null
@@ -1 +0,0 @@
-fb9c9c896f5cc2b6b90a8359ce213144bb0716f1
\ No newline at end of file
diff --git a/third_party/blimp_fonts/fonts.xml b/third_party/blimp_fonts/fonts.xml
deleted file mode 100644
index dbe81fa..0000000
--- a/third_party/blimp_fonts/fonts.xml
+++ /dev/null
@@ -1,371 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-    NOTE: this is the newer (L) version of the system font configuration,
-    supporting richer weight selection. Some apps will expect the older
-    version, so please keep system_fonts.xml and fallback_fonts.xml in sync
-    with any changes, even though framework will only read this file.
-
-    All fonts withohut names are added to the default list. Fonts are chosen
-    based on a match: full BCP-47 language tag including script, then just
-    language, and finally order (the first font containing the glyph).
-
-    Order of appearance is also the tiebreaker for weight matching. This is
-    the reason why the 900 weights of Roboto precede the 700 weights - we
-    prefer the former when an 800 weight is requested. Since bold spans
-    effectively add 300 to the weight, this ensures that 900 is the bold
-    paired with the 500 weight, ensuring adequate contrast.
--->
-<familyset version="22">
-    <!-- first font is default -->
-    <family name="sans-serif">
-        <font weight="100" style="normal">Roboto-Thin.ttf</font>
-        <font weight="100" style="italic">Roboto-ThinItalic.ttf</font>
-        <font weight="300" style="normal">Roboto-Light.ttf</font>
-        <font weight="300" style="italic">Roboto-LightItalic.ttf</font>
-        <font weight="400" style="normal">Roboto-Regular.ttf</font>
-        <font weight="400" style="italic">Roboto-Italic.ttf</font>
-        <font weight="500" style="normal">Roboto-Medium.ttf</font>
-        <font weight="500" style="italic">Roboto-MediumItalic.ttf</font>
-        <font weight="900" style="normal">Roboto-Black.ttf</font>
-        <font weight="900" style="italic">Roboto-BlackItalic.ttf</font>
-        <font weight="700" style="normal">Roboto-Bold.ttf</font>
-        <font weight="700" style="italic">Roboto-BoldItalic.ttf</font>
-    </family>
-
-    <!-- Note that aliases must come after the fonts they reference. -->
-    <alias name="sans-serif-thin" to="sans-serif" weight="100" />
-    <alias name="sans-serif-light" to="sans-serif" weight="300" />
-    <alias name="sans-serif-medium" to="sans-serif" weight="500" />
-    <alias name="sans-serif-black" to="sans-serif" weight="900" />
-    <alias name="arial" to="sans-serif" />
-    <alias name="helvetica" to="sans-serif" />
-    <alias name="tahoma" to="sans-serif" />
-    <alias name="verdana" to="sans-serif" />
-
-    <family name="sans-serif-condensed">
-        <font weight="300" style="normal">RobotoCondensed-Light.ttf</font>
-        <font weight="300" style="italic">RobotoCondensed-LightItalic.ttf</font>
-        <font weight="400" style="normal">RobotoCondensed-Regular.ttf</font>
-        <font weight="400" style="italic">RobotoCondensed-Italic.ttf</font>
-        <font weight="700" style="normal">RobotoCondensed-Bold.ttf</font>
-        <font weight="700" style="italic">RobotoCondensed-BoldItalic.ttf</font>
-    </family>
-    <alias name="sans-serif-condensed-light" to="sans-serif-condensed" weight="300" />
-
-    <family name="serif">
-        <font weight="400" style="normal">NotoSerif-Regular.ttf</font>
-        <font weight="700" style="normal">NotoSerif-Bold.ttf</font>
-        <font weight="400" style="italic">NotoSerif-Italic.ttf</font>
-        <font weight="700" style="italic">NotoSerif-BoldItalic.ttf</font>
-    </family>
-    <alias name="times" to="serif" />
-    <alias name="times new roman" to="serif" />
-    <alias name="palatino" to="serif" />
-    <alias name="georgia" to="serif" />
-    <alias name="baskerville" to="serif" />
-    <alias name="goudy" to="serif" />
-    <alias name="fantasy" to="serif" />
-    <alias name="ITC Stone Serif" to="serif" />
-
-    <family name="monospace">
-        <font weight="400" style="normal">DroidSansMono.ttf</font>
-    </family>
-    <alias name="sans-serif-monospace" to="monospace" />
-    <alias name="monaco" to="monospace" />
-
-    <family name="serif-monospace">
-        <font weight="400" style="normal">CutiveMono.ttf</font>
-    </family>
-    <alias name="courier" to="serif-monospace" />
-    <alias name="courier new" to="serif-monospace" />
-
-    <family name="casual">
-        <font weight="400" style="normal">ComingSoon.ttf</font>
-    </family>
-
-    <family name="cursive">
-        <font weight="400" style="normal">DancingScript-Regular.ttf</font>
-        <font weight="700" style="normal">DancingScript-Bold.ttf</font>
-    </family>
-
-    <family name="sans-serif-smallcaps">
-        <font weight="400" style="normal">CarroisGothicSC-Regular.ttf</font>
-    </family>
-
-    <!-- fallback fonts -->
-    <family variant="elegant">
-        <font weight="400" style="normal">NotoNaskhArabic-Regular.ttf</font>
-        <font weight="700" style="normal">NotoNaskhArabic-Bold.ttf</font>
-    </family>
-    <family variant="compact">
-        <font weight="400" style="normal">NotoNaskhArabicUI-Regular.ttf</font>
-        <font weight="700" style="normal">NotoNaskhArabicUI-Bold.ttf</font>
-    </family>
-    <family>
-        <font weight="400" style="normal">NotoSansEthiopic-Regular.ttf</font>
-        <font weight="700" style="normal">NotoSansEthiopic-Bold.ttf</font>
-    </family>
-    <family>
-        <font weight="400" style="normal">NotoSansHebrew-Regular.ttf</font>
-        <font weight="700" style="normal">NotoSansHebrew-Bold.ttf</font>
-    </family>
-    <family variant="elegant">
-        <font weight="400" style="normal">NotoSansThai-Regular.ttf</font>
-        <font weight="700" style="normal">NotoSansThai-Bold.ttf</font>
-    </family>
-    <family variant="compact">
-        <font weight="400" style="normal">NotoSansThaiUI-Regular.ttf</font>
-        <font weight="700" style="normal">NotoSansThaiUI-Bold.ttf</font>
-    </family>
-    <family>
-        <font weight="400" style="normal">NotoSansArmenian-Regular.ttf</font>
-        <font weight="700" style="normal">NotoSansArmenian-Bold.ttf</font>
-    </family>
-    <family>
-        <font weight="400" style="normal">NotoSansGeorgian-Regular.ttf</font>
-        <font weight="700" style="normal">NotoSansGeorgian-Bold.ttf</font>
-    </family>
-    <family variant="elegant">
-        <font weight="400" style="normal">NotoSansDevanagari-Regular.ttf</font>
-        <font weight="700" style="normal">NotoSansDevanagari-Bold.ttf</font>
-    </family>
-    <family variant="compact">
-        <font weight="400" style="normal">NotoSansDevanagariUI-Regular.ttf</font>
-        <font weight="700" style="normal">NotoSansDevanagariUI-Bold.ttf</font>
-    </family>
-    <!-- Gujarati should come after Devanagari -->
-    <family variant="elegant">
-        <font weight="400" style="normal">NotoSansGujarati-Regular.ttf</font>
-        <font weight="700" style="normal">NotoSansGujarati-Bold.ttf</font>
-    </family>
-    <family variant="compact">
-        <font weight="400" style="normal">NotoSansGujaratiUI-Regular.ttf</font>
-        <font weight="700" style="normal">NotoSansGujaratiUI-Bold.ttf</font>
-    </family>
-    <!-- Gurmukhi should come after Devanagari -->
-    <family variant="elegant">
-        <font weight="400" style="normal">NotoSansGurmukhi-Regular.ttf</font>
-        <font weight="700" style="normal">NotoSansGurmukhi-Bold.ttf</font>
-    </family>
-    <family variant="compact">
-        <font weight="400" style="normal">NotoSansGurmukhiUI-Regular.ttf</font>
-        <font weight="700" style="normal">NotoSansGurmukhiUI-Bold.ttf</font>
-    </family>
-    <family variant="elegant">
-        <font weight="400" style="normal">NotoSansTamil-Regular.ttf</font>
-        <font weight="700" style="normal">NotoSansTamil-Bold.ttf</font>
-    </family>
-    <family variant="compact">
-        <font weight="400" style="normal">NotoSansTamilUI-Regular.ttf</font>
-        <font weight="700" style="normal">NotoSansTamilUI-Bold.ttf</font>
-    </family>
-    <family variant="elegant">
-        <font weight="400" style="normal">NotoSansMalayalam-Regular.ttf</font>
-        <font weight="700" style="normal">NotoSansMalayalam-Bold.ttf</font>
-    </family>
-    <family variant="compact">
-        <font weight="400" style="normal">NotoSansMalayalamUI-Regular.ttf</font>
-        <font weight="700" style="normal">NotoSansMalayalamUI-Bold.ttf</font>
-    </family>
-    <family variant="elegant">
-        <font weight="400" style="normal">NotoSansBengali-Regular.ttf</font>
-        <font weight="700" style="normal">NotoSansBengali-Bold.ttf</font>
-    </family>
-    <family variant="compact">
-        <font weight="400" style="normal">NotoSansBengaliUI-Regular.ttf</font>
-        <font weight="700" style="normal">NotoSansBengaliUI-Bold.ttf</font>
-    </family>
-    <family variant="elegant">
-        <font weight="400" style="normal">NotoSansTelugu-Regular.ttf</font>
-        <font weight="700" style="normal">NotoSansTelugu-Bold.ttf</font>
-    </family>
-    <family variant="compact">
-        <font weight="400" style="normal">NotoSansTeluguUI-Regular.ttf</font>
-        <font weight="700" style="normal">NotoSansTeluguUI-Bold.ttf</font>
-    </family>
-    <family variant="elegant">
-        <font weight="400" style="normal">NotoSansKannada-Regular.ttf</font>
-        <font weight="700" style="normal">NotoSansKannada-Bold.ttf</font>
-    </family>
-    <family variant="compact">
-        <font weight="400" style="normal">NotoSansKannadaUI-Regular.ttf</font>
-        <font weight="700" style="normal">NotoSansKannadaUI-Bold.ttf</font>
-    </family>
-    <family variant="elegant">
-        <font weight="400" style="normal">NotoSansOriya-Regular.ttf</font>
-        <font weight="700" style="normal">NotoSansOriya-Bold.ttf</font>
-    </family>
-    <family variant="compact">
-        <font weight="400" style="normal">NotoSansOriyaUI-Regular.ttf</font>
-        <font weight="700" style="normal">NotoSansOriyaUI-Bold.ttf</font>
-    </family>
-    <family>
-        <font weight="400" style="normal">NotoSansSinhala-Regular.ttf</font>
-        <font weight="700" style="normal">NotoSansSinhala-Bold.ttf</font>
-    </family>
-    <family variant="elegant">
-        <font weight="400" style="normal">NotoSansKhmer-Regular.ttf</font>
-        <font weight="700" style="normal">NotoSansKhmer-Bold.ttf</font>
-    </family>
-    <family variant="compact">
-        <font weight="400" style="normal">NotoSansKhmerUI-Regular.ttf</font>
-        <font weight="700" style="normal">NotoSansKhmerUI-Bold.ttf</font>
-    </family>
-    <family variant="elegant">
-        <font weight="400" style="normal">NotoSansLao-Regular.ttf</font>
-        <font weight="700" style="normal">NotoSansLao-Bold.ttf</font>
-    </family>
-    <family variant="compact">
-        <font weight="400" style="normal">NotoSansLaoUI-Regular.ttf</font>
-        <font weight="700" style="normal">NotoSansLaoUI-Bold.ttf</font>
-    </family>
-    <family variant="elegant">
-        <font weight="400" style="normal">NotoSansMyanmar-Regular.ttf</font>
-        <font weight="700" style="normal">NotoSansMyanmar-Bold.ttf</font>
-    </family>
-    <family variant="compact">
-        <font weight="400" style="normal">NotoSansMyanmarUI-Regular.ttf</font>
-        <font weight="700" style="normal">NotoSansMyanmarUI-Bold.ttf</font>
-    </family>
-    <family>
-        <font weight="400" style="normal">NotoSansThaana-Regular.ttf</font>
-        <font weight="700" style="normal">NotoSansThaana-Bold.ttf</font>
-    </family>
-    <family>
-        <font weight="400" style="normal">NotoSansCham-Regular.ttf</font>
-        <font weight="700" style="normal">NotoSansCham-Bold.ttf</font>
-    </family>
-    <family>
-        <font weight="400" style="normal">NotoSansBalinese-Regular.ttf</font>
-    </family>
-    <family>
-        <font weight="400" style="normal">NotoSansBamum-Regular.ttf</font>
-    </family>
-    <family>
-        <font weight="400" style="normal">NotoSansBatak-Regular.ttf</font>
-    </family>
-    <family>
-        <font weight="400" style="normal">NotoSansBuginese-Regular.ttf</font>
-    </family>
-    <family>
-        <font weight="400" style="normal">NotoSansBuhid-Regular.ttf</font>
-    </family>
-    <family>
-        <font weight="400" style="normal">NotoSansCanadianAboriginal-Regular.ttf</font>
-    </family>
-    <family>
-        <font weight="400" style="normal">NotoSansCherokee-Regular.ttf</font>
-    </family>
-    <family>
-        <font weight="400" style="normal">NotoSansCoptic-Regular.ttf</font>
-    </family>
-    <family>
-        <font weight="400" style="normal">NotoSansGlagolitic-Regular.ttf</font>
-    </family>
-    <family>
-        <font weight="400" style="normal">NotoSansHanunoo-Regular.ttf</font>
-    </family>
-    <family>
-        <font weight="400" style="normal">NotoSansJavanese-Regular.ttf</font>
-    </family>
-    <family>
-        <font weight="400" style="normal">NotoSansKayahLi-Regular.ttf</font>
-    </family>
-    <family>
-        <font weight="400" style="normal">NotoSansLepcha-Regular.ttf</font>
-    </family>
-    <family>
-        <font weight="400" style="normal">NotoSansLimbu-Regular.ttf</font>
-    </family>
-    <family>
-        <font weight="400" style="normal">NotoSansLisu-Regular.ttf</font>
-    </family>
-    <family>
-        <font weight="400" style="normal">NotoSansMandaic-Regular.ttf</font>
-    </family>
-    <family>
-        <font weight="400" style="normal">NotoSansMeeteiMayek-Regular.ttf</font>
-    </family>
-    <family>
-        <font weight="400" style="normal">NotoSansNewTaiLue-Regular.ttf</font>
-    </family>
-    <family>
-        <font weight="400" style="normal">NotoSansNKo-Regular.ttf</font>
-    </family>
-    <family>
-        <font weight="400" style="normal">NotoSansOlChiki-Regular.ttf</font>
-    </family>
-    <family>
-        <font weight="400" style="normal">NotoSansRejang-Regular.ttf</font>
-    </family>
-    <family>
-        <font weight="400" style="normal">NotoSansSaurashtra-Regular.ttf</font>
-    </family>
-    <family>
-        <font weight="400" style="normal">NotoSansSundanese-Regular.ttf</font>
-    </family>
-    <family>
-        <font weight="400" style="normal">NotoSansSylotiNagri-Regular.ttf</font>
-    </family>
-    <family>
-        <font weight="400" style="normal">NotoSansSyriacEstrangela-Regular.ttf</font>
-    </family>
-    <family>
-        <font weight="400" style="normal">NotoSansTagbanwa-Regular.ttf</font>
-    </family>
-    <family>
-        <font weight="400" style="normal">NotoSansTaiTham-Regular.ttf</font>
-    </family>
-    <family>
-        <font weight="400" style="normal">NotoSansTaiViet-Regular.ttf</font>
-    </family>
-    <family>
-        <font weight="400" style="normal">NotoSansTibetan-Regular.ttf</font>
-    </family>
-    <family>
-        <font weight="400" style="normal">NotoSansTifinagh-Regular.ttf</font>
-    </family>
-    <family>
-        <font weight="400" style="normal">NotoSansVai-Regular.ttf</font>
-    </family>
-    <family>
-        <font weight="400" style="normal">NotoSansYi-Regular.ttf</font>
-    </family>
-    <family>
-        <font weight="400" style="normal">NotoSansSymbols-Regular-Subsetted.ttf</font>
-    </family>
-    <family lang="zh-Hans">
-        <font weight="400" style="normal">NotoSansSC-Regular.otf</font>
-    </family>
-    <family lang="zh-Hant">
-        <font weight="400" style="normal">NotoSansTC-Regular.otf</font>
-    </family>
-    <family lang="ja">
-        <font weight="400" style="normal">NotoSansJP-Regular.otf</font>
-    </family>
-    <family lang="ko">
-        <font weight="400" style="normal">NotoSansKR-Regular.otf</font>
-    </family>
-    <family>
-        <font weight="400" style="normal">NanumGothic.ttf</font>
-    </family>
-    <family>
-        <font weight="400" style="normal">NotoColorEmoji.ttf</font>
-    </family>
-    <family>
-        <font weight="400" style="normal">DroidSansFallback.ttf</font>
-    </family>
-    <family lang="ja">
-        <font weight="400" style="normal">MTLmr3m.ttf</font>
-    </family>
-    <!--
-        Tai Le and Mongolian are intentionally kept last, to make sure they don't override
-        the East Asian punctuation for Chinese.
-    -->
-    <family>
-        <font weight="400" style="normal">NotoSansTaiLe-Regular.ttf</font>
-    </family>
-    <family>
-        <font weight="400" style="normal">NotoSansMongolian-Regular.ttf</font>
-    </family>
-</familyset>
diff --git a/third_party/libvpx/README.chromium b/third_party/libvpx/README.chromium
index 79f63e2..de87aeb 100644
--- a/third_party/libvpx/README.chromium
+++ b/third_party/libvpx/README.chromium
@@ -5,9 +5,9 @@
 License File: source/libvpx/LICENSE
 Security Critical: yes
 
-Date: Tuesday February 16 2016
+Date: Friday March 04 2016
 Branch: master
-Commit: 89cc68252846478fa7f2d570d96ff93776cefac6
+Commit: 9aa083d164e0d39086aa0c83f0d1a0d0f0d1ba61
 
 Description:
 Contains the sources used to compile libvpx binaries used by Google Chrome and
diff --git a/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vpx_dsp_rtcd.h
index de16e83..7680d3a 100644
--- a/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vpx_dsp_rtcd.h
+++ b/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vpx_dsp_rtcd.h
@@ -372,26 +372,30 @@
 void vpx_iwht4x4_1_add_c(const tran_low_t *input, uint8_t *dest, int dest_stride);
 #define vpx_iwht4x4_1_add vpx_iwht4x4_1_add_c
 
-void vpx_lpf_horizontal_16_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-void vpx_lpf_horizontal_16_neon(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-RTCD_EXTERN void (*vpx_lpf_horizontal_16)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-
-void vpx_lpf_horizontal_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-void vpx_lpf_horizontal_4_neon(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-RTCD_EXTERN void (*vpx_lpf_horizontal_4)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_horizontal_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_horizontal_4_neon(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+RTCD_EXTERN void (*vpx_lpf_horizontal_4)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 
 void vpx_lpf_horizontal_4_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 void vpx_lpf_horizontal_4_dual_neon(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 RTCD_EXTERN void (*vpx_lpf_horizontal_4_dual)(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 
-void vpx_lpf_horizontal_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-void vpx_lpf_horizontal_8_neon(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-RTCD_EXTERN void (*vpx_lpf_horizontal_8)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_horizontal_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_horizontal_8_neon(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+RTCD_EXTERN void (*vpx_lpf_horizontal_8)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 
 void vpx_lpf_horizontal_8_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 void vpx_lpf_horizontal_8_dual_neon(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 RTCD_EXTERN void (*vpx_lpf_horizontal_8_dual)(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 
+void vpx_lpf_horizontal_edge_16_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_horizontal_edge_16_neon(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+RTCD_EXTERN void (*vpx_lpf_horizontal_edge_16)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+
+void vpx_lpf_horizontal_edge_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_horizontal_edge_8_neon(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+RTCD_EXTERN void (*vpx_lpf_horizontal_edge_8)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+
 void vpx_lpf_vertical_16_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 void vpx_lpf_vertical_16_neon(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 RTCD_EXTERN void (*vpx_lpf_vertical_16)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
@@ -400,17 +404,17 @@
 void vpx_lpf_vertical_16_dual_neon(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 RTCD_EXTERN void (*vpx_lpf_vertical_16_dual)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 
-void vpx_lpf_vertical_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-void vpx_lpf_vertical_4_neon(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-RTCD_EXTERN void (*vpx_lpf_vertical_4)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_vertical_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_vertical_4_neon(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+RTCD_EXTERN void (*vpx_lpf_vertical_4)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 
 void vpx_lpf_vertical_4_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 void vpx_lpf_vertical_4_dual_neon(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 RTCD_EXTERN void (*vpx_lpf_vertical_4_dual)(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 
-void vpx_lpf_vertical_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-void vpx_lpf_vertical_8_neon(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-RTCD_EXTERN void (*vpx_lpf_vertical_8)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_vertical_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_vertical_8_neon(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+RTCD_EXTERN void (*vpx_lpf_vertical_8)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 
 void vpx_lpf_vertical_8_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 void vpx_lpf_vertical_8_dual_neon(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
@@ -943,8 +947,6 @@
     if (flags & HAS_NEON) vpx_int_pro_col = vpx_int_pro_col_neon;
     vpx_int_pro_row = vpx_int_pro_row_c;
     if (flags & HAS_NEON) vpx_int_pro_row = vpx_int_pro_row_neon;
-    vpx_lpf_horizontal_16 = vpx_lpf_horizontal_16_c;
-    if (flags & HAS_NEON) vpx_lpf_horizontal_16 = vpx_lpf_horizontal_16_neon;
     vpx_lpf_horizontal_4 = vpx_lpf_horizontal_4_c;
     if (flags & HAS_NEON) vpx_lpf_horizontal_4 = vpx_lpf_horizontal_4_neon;
     vpx_lpf_horizontal_4_dual = vpx_lpf_horizontal_4_dual_c;
@@ -953,6 +955,10 @@
     if (flags & HAS_NEON) vpx_lpf_horizontal_8 = vpx_lpf_horizontal_8_neon;
     vpx_lpf_horizontal_8_dual = vpx_lpf_horizontal_8_dual_c;
     if (flags & HAS_NEON) vpx_lpf_horizontal_8_dual = vpx_lpf_horizontal_8_dual_neon;
+    vpx_lpf_horizontal_edge_16 = vpx_lpf_horizontal_edge_16_c;
+    if (flags & HAS_NEON) vpx_lpf_horizontal_edge_16 = vpx_lpf_horizontal_edge_16_neon;
+    vpx_lpf_horizontal_edge_8 = vpx_lpf_horizontal_edge_8_c;
+    if (flags & HAS_NEON) vpx_lpf_horizontal_edge_8 = vpx_lpf_horizontal_edge_8_neon;
     vpx_lpf_vertical_16 = vpx_lpf_vertical_16_c;
     if (flags & HAS_NEON) vpx_lpf_vertical_16 = vpx_lpf_vertical_16_neon;
     vpx_lpf_vertical_16_dual = vpx_lpf_vertical_16_dual_c;
diff --git a/third_party/libvpx/source/config/linux/arm-neon/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/linux/arm-neon/vpx_dsp_rtcd.h
index f6d699a5..30233f9 100644
--- a/third_party/libvpx/source/config/linux/arm-neon/vpx_dsp_rtcd.h
+++ b/third_party/libvpx/source/config/linux/arm-neon/vpx_dsp_rtcd.h
@@ -372,26 +372,30 @@
 void vpx_iwht4x4_1_add_c(const tran_low_t *input, uint8_t *dest, int dest_stride);
 #define vpx_iwht4x4_1_add vpx_iwht4x4_1_add_c
 
-void vpx_lpf_horizontal_16_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-void vpx_lpf_horizontal_16_neon(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-#define vpx_lpf_horizontal_16 vpx_lpf_horizontal_16_neon
-
-void vpx_lpf_horizontal_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-void vpx_lpf_horizontal_4_neon(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_horizontal_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_horizontal_4_neon(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_horizontal_4 vpx_lpf_horizontal_4_neon
 
 void vpx_lpf_horizontal_4_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 void vpx_lpf_horizontal_4_dual_neon(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 #define vpx_lpf_horizontal_4_dual vpx_lpf_horizontal_4_dual_neon
 
-void vpx_lpf_horizontal_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-void vpx_lpf_horizontal_8_neon(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_horizontal_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_horizontal_8_neon(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_horizontal_8 vpx_lpf_horizontal_8_neon
 
 void vpx_lpf_horizontal_8_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 void vpx_lpf_horizontal_8_dual_neon(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 #define vpx_lpf_horizontal_8_dual vpx_lpf_horizontal_8_dual_neon
 
+void vpx_lpf_horizontal_edge_16_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_horizontal_edge_16_neon(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+#define vpx_lpf_horizontal_edge_16 vpx_lpf_horizontal_edge_16_neon
+
+void vpx_lpf_horizontal_edge_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_horizontal_edge_8_neon(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+#define vpx_lpf_horizontal_edge_8 vpx_lpf_horizontal_edge_8_neon
+
 void vpx_lpf_vertical_16_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 void vpx_lpf_vertical_16_neon(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_vertical_16 vpx_lpf_vertical_16_neon
@@ -400,16 +404,16 @@
 void vpx_lpf_vertical_16_dual_neon(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_vertical_16_dual vpx_lpf_vertical_16_dual_neon
 
-void vpx_lpf_vertical_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-void vpx_lpf_vertical_4_neon(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_vertical_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_vertical_4_neon(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_vertical_4 vpx_lpf_vertical_4_neon
 
 void vpx_lpf_vertical_4_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 void vpx_lpf_vertical_4_dual_neon(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 #define vpx_lpf_vertical_4_dual vpx_lpf_vertical_4_dual_neon
 
-void vpx_lpf_vertical_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-void vpx_lpf_vertical_8_neon(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_vertical_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_vertical_8_neon(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_vertical_8 vpx_lpf_vertical_8_neon
 
 void vpx_lpf_vertical_8_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
diff --git a/third_party/libvpx/source/config/linux/arm/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/linux/arm/vpx_dsp_rtcd.h
index 117c0fd9..b83359b 100644
--- a/third_party/libvpx/source/config/linux/arm/vpx_dsp_rtcd.h
+++ b/third_party/libvpx/source/config/linux/arm/vpx_dsp_rtcd.h
@@ -319,34 +319,37 @@
 void vpx_iwht4x4_1_add_c(const tran_low_t *input, uint8_t *dest, int dest_stride);
 #define vpx_iwht4x4_1_add vpx_iwht4x4_1_add_c
 
-void vpx_lpf_horizontal_16_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-#define vpx_lpf_horizontal_16 vpx_lpf_horizontal_16_c
-
-void vpx_lpf_horizontal_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_horizontal_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_horizontal_4 vpx_lpf_horizontal_4_c
 
 void vpx_lpf_horizontal_4_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 #define vpx_lpf_horizontal_4_dual vpx_lpf_horizontal_4_dual_c
 
-void vpx_lpf_horizontal_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_horizontal_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_horizontal_8 vpx_lpf_horizontal_8_c
 
 void vpx_lpf_horizontal_8_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 #define vpx_lpf_horizontal_8_dual vpx_lpf_horizontal_8_dual_c
 
+void vpx_lpf_horizontal_edge_16_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+#define vpx_lpf_horizontal_edge_16 vpx_lpf_horizontal_edge_16_c
+
+void vpx_lpf_horizontal_edge_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+#define vpx_lpf_horizontal_edge_8 vpx_lpf_horizontal_edge_8_c
+
 void vpx_lpf_vertical_16_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_vertical_16 vpx_lpf_vertical_16_c
 
 void vpx_lpf_vertical_16_dual_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_vertical_16_dual vpx_lpf_vertical_16_dual_c
 
-void vpx_lpf_vertical_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_vertical_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_vertical_4 vpx_lpf_vertical_4_c
 
 void vpx_lpf_vertical_4_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 #define vpx_lpf_vertical_4_dual vpx_lpf_vertical_4_dual_c
 
-void vpx_lpf_vertical_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_vertical_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_vertical_8 vpx_lpf_vertical_8_c
 
 void vpx_lpf_vertical_8_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
diff --git a/third_party/libvpx/source/config/linux/arm64/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/linux/arm64/vpx_dsp_rtcd.h
index 7171ec56..122debd 100644
--- a/third_party/libvpx/source/config/linux/arm64/vpx_dsp_rtcd.h
+++ b/third_party/libvpx/source/config/linux/arm64/vpx_dsp_rtcd.h
@@ -371,40 +371,43 @@
 void vpx_iwht4x4_1_add_c(const tran_low_t *input, uint8_t *dest, int dest_stride);
 #define vpx_iwht4x4_1_add vpx_iwht4x4_1_add_c
 
-void vpx_lpf_horizontal_16_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-#define vpx_lpf_horizontal_16 vpx_lpf_horizontal_16_c
-
-void vpx_lpf_horizontal_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-void vpx_lpf_horizontal_4_neon(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_horizontal_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_horizontal_4_neon(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_horizontal_4 vpx_lpf_horizontal_4_neon
 
 void vpx_lpf_horizontal_4_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 void vpx_lpf_horizontal_4_dual_neon(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 #define vpx_lpf_horizontal_4_dual vpx_lpf_horizontal_4_dual_neon
 
-void vpx_lpf_horizontal_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-void vpx_lpf_horizontal_8_neon(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_horizontal_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_horizontal_8_neon(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_horizontal_8 vpx_lpf_horizontal_8_neon
 
 void vpx_lpf_horizontal_8_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 #define vpx_lpf_horizontal_8_dual vpx_lpf_horizontal_8_dual_c
 
+void vpx_lpf_horizontal_edge_16_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+#define vpx_lpf_horizontal_edge_16 vpx_lpf_horizontal_edge_16_c
+
+void vpx_lpf_horizontal_edge_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+#define vpx_lpf_horizontal_edge_8 vpx_lpf_horizontal_edge_8_c
+
 void vpx_lpf_vertical_16_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_vertical_16 vpx_lpf_vertical_16_c
 
 void vpx_lpf_vertical_16_dual_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_vertical_16_dual vpx_lpf_vertical_16_dual_c
 
-void vpx_lpf_vertical_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-void vpx_lpf_vertical_4_neon(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_vertical_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_vertical_4_neon(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_vertical_4 vpx_lpf_vertical_4_neon
 
 void vpx_lpf_vertical_4_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 void vpx_lpf_vertical_4_dual_neon(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 #define vpx_lpf_vertical_4_dual vpx_lpf_vertical_4_dual_neon
 
-void vpx_lpf_vertical_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-void vpx_lpf_vertical_8_neon(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_vertical_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_vertical_8_neon(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_vertical_8 vpx_lpf_vertical_8_neon
 
 void vpx_lpf_vertical_8_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
diff --git a/third_party/libvpx/source/config/linux/generic/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/linux/generic/vpx_dsp_rtcd.h
index fe17035..b76c67a 100644
--- a/third_party/libvpx/source/config/linux/generic/vpx_dsp_rtcd.h
+++ b/third_party/libvpx/source/config/linux/generic/vpx_dsp_rtcd.h
@@ -319,34 +319,37 @@
 void vpx_iwht4x4_1_add_c(const tran_low_t *input, uint8_t *dest, int dest_stride);
 #define vpx_iwht4x4_1_add vpx_iwht4x4_1_add_c
 
-void vpx_lpf_horizontal_16_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-#define vpx_lpf_horizontal_16 vpx_lpf_horizontal_16_c
-
-void vpx_lpf_horizontal_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_horizontal_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_horizontal_4 vpx_lpf_horizontal_4_c
 
 void vpx_lpf_horizontal_4_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 #define vpx_lpf_horizontal_4_dual vpx_lpf_horizontal_4_dual_c
 
-void vpx_lpf_horizontal_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_horizontal_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_horizontal_8 vpx_lpf_horizontal_8_c
 
 void vpx_lpf_horizontal_8_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 #define vpx_lpf_horizontal_8_dual vpx_lpf_horizontal_8_dual_c
 
+void vpx_lpf_horizontal_edge_16_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+#define vpx_lpf_horizontal_edge_16 vpx_lpf_horizontal_edge_16_c
+
+void vpx_lpf_horizontal_edge_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+#define vpx_lpf_horizontal_edge_8 vpx_lpf_horizontal_edge_8_c
+
 void vpx_lpf_vertical_16_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_vertical_16 vpx_lpf_vertical_16_c
 
 void vpx_lpf_vertical_16_dual_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_vertical_16_dual vpx_lpf_vertical_16_dual_c
 
-void vpx_lpf_vertical_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_vertical_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_vertical_4 vpx_lpf_vertical_4_c
 
 void vpx_lpf_vertical_4_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 #define vpx_lpf_vertical_4_dual vpx_lpf_vertical_4_dual_c
 
-void vpx_lpf_vertical_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_vertical_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_vertical_8 vpx_lpf_vertical_8_c
 
 void vpx_lpf_vertical_8_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
diff --git a/third_party/libvpx/source/config/linux/ia32/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/linux/ia32/vpx_dsp_rtcd.h
index a2aaf695..9c7f50b1 100644
--- a/third_party/libvpx/source/config/linux/ia32/vpx_dsp_rtcd.h
+++ b/third_party/libvpx/source/config/linux/ia32/vpx_dsp_rtcd.h
@@ -408,27 +408,32 @@
 void vpx_iwht4x4_1_add_c(const tran_low_t *input, uint8_t *dest, int dest_stride);
 #define vpx_iwht4x4_1_add vpx_iwht4x4_1_add_c
 
-void vpx_lpf_horizontal_16_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-void vpx_lpf_horizontal_16_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-void vpx_lpf_horizontal_16_avx2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-RTCD_EXTERN void (*vpx_lpf_horizontal_16)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-
-void vpx_lpf_horizontal_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-void vpx_lpf_horizontal_4_mmx(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-RTCD_EXTERN void (*vpx_lpf_horizontal_4)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_horizontal_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_horizontal_4_mmx(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+RTCD_EXTERN void (*vpx_lpf_horizontal_4)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 
 void vpx_lpf_horizontal_4_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 void vpx_lpf_horizontal_4_dual_sse2(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 RTCD_EXTERN void (*vpx_lpf_horizontal_4_dual)(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 
-void vpx_lpf_horizontal_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-void vpx_lpf_horizontal_8_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-RTCD_EXTERN void (*vpx_lpf_horizontal_8)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_horizontal_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_horizontal_8_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+RTCD_EXTERN void (*vpx_lpf_horizontal_8)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 
 void vpx_lpf_horizontal_8_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 void vpx_lpf_horizontal_8_dual_sse2(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 RTCD_EXTERN void (*vpx_lpf_horizontal_8_dual)(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 
+void vpx_lpf_horizontal_edge_16_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_horizontal_edge_16_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_horizontal_edge_16_avx2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+RTCD_EXTERN void (*vpx_lpf_horizontal_edge_16)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+
+void vpx_lpf_horizontal_edge_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_horizontal_edge_8_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_horizontal_edge_8_avx2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+RTCD_EXTERN void (*vpx_lpf_horizontal_edge_8)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+
 void vpx_lpf_vertical_16_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 void vpx_lpf_vertical_16_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 RTCD_EXTERN void (*vpx_lpf_vertical_16)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
@@ -437,17 +442,17 @@
 void vpx_lpf_vertical_16_dual_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 RTCD_EXTERN void (*vpx_lpf_vertical_16_dual)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 
-void vpx_lpf_vertical_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-void vpx_lpf_vertical_4_mmx(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-RTCD_EXTERN void (*vpx_lpf_vertical_4)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_vertical_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_vertical_4_mmx(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+RTCD_EXTERN void (*vpx_lpf_vertical_4)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 
 void vpx_lpf_vertical_4_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 void vpx_lpf_vertical_4_dual_sse2(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 RTCD_EXTERN void (*vpx_lpf_vertical_4_dual)(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 
-void vpx_lpf_vertical_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-void vpx_lpf_vertical_8_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-RTCD_EXTERN void (*vpx_lpf_vertical_8)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_vertical_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_vertical_8_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+RTCD_EXTERN void (*vpx_lpf_vertical_8)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 
 void vpx_lpf_vertical_8_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 void vpx_lpf_vertical_8_dual_sse2(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
@@ -1171,9 +1176,6 @@
     if (flags & HAS_SSE2) vpx_int_pro_row = vpx_int_pro_row_sse2;
     vpx_iwht4x4_16_add = vpx_iwht4x4_16_add_c;
     if (flags & HAS_SSE2) vpx_iwht4x4_16_add = vpx_iwht4x4_16_add_sse2;
-    vpx_lpf_horizontal_16 = vpx_lpf_horizontal_16_c;
-    if (flags & HAS_SSE2) vpx_lpf_horizontal_16 = vpx_lpf_horizontal_16_sse2;
-    if (flags & HAS_AVX2) vpx_lpf_horizontal_16 = vpx_lpf_horizontal_16_avx2;
     vpx_lpf_horizontal_4 = vpx_lpf_horizontal_4_c;
     if (flags & HAS_MMX) vpx_lpf_horizontal_4 = vpx_lpf_horizontal_4_mmx;
     vpx_lpf_horizontal_4_dual = vpx_lpf_horizontal_4_dual_c;
@@ -1182,6 +1184,12 @@
     if (flags & HAS_SSE2) vpx_lpf_horizontal_8 = vpx_lpf_horizontal_8_sse2;
     vpx_lpf_horizontal_8_dual = vpx_lpf_horizontal_8_dual_c;
     if (flags & HAS_SSE2) vpx_lpf_horizontal_8_dual = vpx_lpf_horizontal_8_dual_sse2;
+    vpx_lpf_horizontal_edge_16 = vpx_lpf_horizontal_edge_16_c;
+    if (flags & HAS_SSE2) vpx_lpf_horizontal_edge_16 = vpx_lpf_horizontal_edge_16_sse2;
+    if (flags & HAS_AVX2) vpx_lpf_horizontal_edge_16 = vpx_lpf_horizontal_edge_16_avx2;
+    vpx_lpf_horizontal_edge_8 = vpx_lpf_horizontal_edge_8_c;
+    if (flags & HAS_SSE2) vpx_lpf_horizontal_edge_8 = vpx_lpf_horizontal_edge_8_sse2;
+    if (flags & HAS_AVX2) vpx_lpf_horizontal_edge_8 = vpx_lpf_horizontal_edge_8_avx2;
     vpx_lpf_vertical_16 = vpx_lpf_vertical_16_c;
     if (flags & HAS_SSE2) vpx_lpf_vertical_16 = vpx_lpf_vertical_16_sse2;
     vpx_lpf_vertical_16_dual = vpx_lpf_vertical_16_dual_c;
diff --git a/third_party/libvpx/source/config/linux/mips64el/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/linux/mips64el/vpx_dsp_rtcd.h
index fe17035..b76c67a 100644
--- a/third_party/libvpx/source/config/linux/mips64el/vpx_dsp_rtcd.h
+++ b/third_party/libvpx/source/config/linux/mips64el/vpx_dsp_rtcd.h
@@ -319,34 +319,37 @@
 void vpx_iwht4x4_1_add_c(const tran_low_t *input, uint8_t *dest, int dest_stride);
 #define vpx_iwht4x4_1_add vpx_iwht4x4_1_add_c
 
-void vpx_lpf_horizontal_16_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-#define vpx_lpf_horizontal_16 vpx_lpf_horizontal_16_c
-
-void vpx_lpf_horizontal_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_horizontal_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_horizontal_4 vpx_lpf_horizontal_4_c
 
 void vpx_lpf_horizontal_4_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 #define vpx_lpf_horizontal_4_dual vpx_lpf_horizontal_4_dual_c
 
-void vpx_lpf_horizontal_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_horizontal_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_horizontal_8 vpx_lpf_horizontal_8_c
 
 void vpx_lpf_horizontal_8_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 #define vpx_lpf_horizontal_8_dual vpx_lpf_horizontal_8_dual_c
 
+void vpx_lpf_horizontal_edge_16_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+#define vpx_lpf_horizontal_edge_16 vpx_lpf_horizontal_edge_16_c
+
+void vpx_lpf_horizontal_edge_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+#define vpx_lpf_horizontal_edge_8 vpx_lpf_horizontal_edge_8_c
+
 void vpx_lpf_vertical_16_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_vertical_16 vpx_lpf_vertical_16_c
 
 void vpx_lpf_vertical_16_dual_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_vertical_16_dual vpx_lpf_vertical_16_dual_c
 
-void vpx_lpf_vertical_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_vertical_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_vertical_4 vpx_lpf_vertical_4_c
 
 void vpx_lpf_vertical_4_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 #define vpx_lpf_vertical_4_dual vpx_lpf_vertical_4_dual_c
 
-void vpx_lpf_vertical_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_vertical_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_vertical_8 vpx_lpf_vertical_8_c
 
 void vpx_lpf_vertical_8_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
diff --git a/third_party/libvpx/source/config/linux/mipsel/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/linux/mipsel/vpx_dsp_rtcd.h
index fe17035..b76c67a 100644
--- a/third_party/libvpx/source/config/linux/mipsel/vpx_dsp_rtcd.h
+++ b/third_party/libvpx/source/config/linux/mipsel/vpx_dsp_rtcd.h
@@ -319,34 +319,37 @@
 void vpx_iwht4x4_1_add_c(const tran_low_t *input, uint8_t *dest, int dest_stride);
 #define vpx_iwht4x4_1_add vpx_iwht4x4_1_add_c
 
-void vpx_lpf_horizontal_16_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-#define vpx_lpf_horizontal_16 vpx_lpf_horizontal_16_c
-
-void vpx_lpf_horizontal_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_horizontal_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_horizontal_4 vpx_lpf_horizontal_4_c
 
 void vpx_lpf_horizontal_4_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 #define vpx_lpf_horizontal_4_dual vpx_lpf_horizontal_4_dual_c
 
-void vpx_lpf_horizontal_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_horizontal_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_horizontal_8 vpx_lpf_horizontal_8_c
 
 void vpx_lpf_horizontal_8_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 #define vpx_lpf_horizontal_8_dual vpx_lpf_horizontal_8_dual_c
 
+void vpx_lpf_horizontal_edge_16_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+#define vpx_lpf_horizontal_edge_16 vpx_lpf_horizontal_edge_16_c
+
+void vpx_lpf_horizontal_edge_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+#define vpx_lpf_horizontal_edge_8 vpx_lpf_horizontal_edge_8_c
+
 void vpx_lpf_vertical_16_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_vertical_16 vpx_lpf_vertical_16_c
 
 void vpx_lpf_vertical_16_dual_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_vertical_16_dual vpx_lpf_vertical_16_dual_c
 
-void vpx_lpf_vertical_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_vertical_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_vertical_4 vpx_lpf_vertical_4_c
 
 void vpx_lpf_vertical_4_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 #define vpx_lpf_vertical_4_dual vpx_lpf_vertical_4_dual_c
 
-void vpx_lpf_vertical_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_vertical_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_vertical_8 vpx_lpf_vertical_8_c
 
 void vpx_lpf_vertical_8_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
diff --git a/third_party/libvpx/source/config/linux/x64/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/linux/x64/vpx_dsp_rtcd.h
index f249241..7eab80a 100644
--- a/third_party/libvpx/source/config/linux/x64/vpx_dsp_rtcd.h
+++ b/third_party/libvpx/source/config/linux/x64/vpx_dsp_rtcd.h
@@ -415,27 +415,32 @@
 void vpx_iwht4x4_1_add_c(const tran_low_t *input, uint8_t *dest, int dest_stride);
 #define vpx_iwht4x4_1_add vpx_iwht4x4_1_add_c
 
-void vpx_lpf_horizontal_16_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-void vpx_lpf_horizontal_16_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-void vpx_lpf_horizontal_16_avx2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-RTCD_EXTERN void (*vpx_lpf_horizontal_16)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-
-void vpx_lpf_horizontal_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-void vpx_lpf_horizontal_4_mmx(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_horizontal_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_horizontal_4_mmx(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_horizontal_4 vpx_lpf_horizontal_4_mmx
 
 void vpx_lpf_horizontal_4_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 void vpx_lpf_horizontal_4_dual_sse2(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 #define vpx_lpf_horizontal_4_dual vpx_lpf_horizontal_4_dual_sse2
 
-void vpx_lpf_horizontal_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-void vpx_lpf_horizontal_8_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_horizontal_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_horizontal_8_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_horizontal_8 vpx_lpf_horizontal_8_sse2
 
 void vpx_lpf_horizontal_8_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 void vpx_lpf_horizontal_8_dual_sse2(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 #define vpx_lpf_horizontal_8_dual vpx_lpf_horizontal_8_dual_sse2
 
+void vpx_lpf_horizontal_edge_16_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_horizontal_edge_16_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_horizontal_edge_16_avx2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+RTCD_EXTERN void (*vpx_lpf_horizontal_edge_16)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+
+void vpx_lpf_horizontal_edge_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_horizontal_edge_8_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_horizontal_edge_8_avx2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+RTCD_EXTERN void (*vpx_lpf_horizontal_edge_8)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+
 void vpx_lpf_vertical_16_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 void vpx_lpf_vertical_16_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_vertical_16 vpx_lpf_vertical_16_sse2
@@ -444,16 +449,16 @@
 void vpx_lpf_vertical_16_dual_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_vertical_16_dual vpx_lpf_vertical_16_dual_sse2
 
-void vpx_lpf_vertical_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-void vpx_lpf_vertical_4_mmx(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_vertical_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_vertical_4_mmx(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_vertical_4 vpx_lpf_vertical_4_mmx
 
 void vpx_lpf_vertical_4_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 void vpx_lpf_vertical_4_dual_sse2(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 #define vpx_lpf_vertical_4_dual vpx_lpf_vertical_4_dual_sse2
 
-void vpx_lpf_vertical_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-void vpx_lpf_vertical_8_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_vertical_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_vertical_8_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_vertical_8 vpx_lpf_vertical_8_sse2
 
 void vpx_lpf_vertical_8_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
@@ -1085,8 +1090,10 @@
     if (flags & HAS_SSSE3) vpx_idct8x8_12_add = vpx_idct8x8_12_add_ssse3;
     vpx_idct8x8_64_add = vpx_idct8x8_64_add_sse2;
     if (flags & HAS_SSSE3) vpx_idct8x8_64_add = vpx_idct8x8_64_add_ssse3;
-    vpx_lpf_horizontal_16 = vpx_lpf_horizontal_16_sse2;
-    if (flags & HAS_AVX2) vpx_lpf_horizontal_16 = vpx_lpf_horizontal_16_avx2;
+    vpx_lpf_horizontal_edge_16 = vpx_lpf_horizontal_edge_16_sse2;
+    if (flags & HAS_AVX2) vpx_lpf_horizontal_edge_16 = vpx_lpf_horizontal_edge_16_avx2;
+    vpx_lpf_horizontal_edge_8 = vpx_lpf_horizontal_edge_8_sse2;
+    if (flags & HAS_AVX2) vpx_lpf_horizontal_edge_8 = vpx_lpf_horizontal_edge_8_avx2;
     vpx_mse16x16 = vpx_mse16x16_sse2;
     if (flags & HAS_AVX2) vpx_mse16x16 = vpx_mse16x16_avx2;
     vpx_quantize_b = vpx_quantize_b_sse2;
diff --git a/third_party/libvpx/source/config/mac/ia32/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/mac/ia32/vpx_dsp_rtcd.h
index a2aaf695..9c7f50b1 100644
--- a/third_party/libvpx/source/config/mac/ia32/vpx_dsp_rtcd.h
+++ b/third_party/libvpx/source/config/mac/ia32/vpx_dsp_rtcd.h
@@ -408,27 +408,32 @@
 void vpx_iwht4x4_1_add_c(const tran_low_t *input, uint8_t *dest, int dest_stride);
 #define vpx_iwht4x4_1_add vpx_iwht4x4_1_add_c
 
-void vpx_lpf_horizontal_16_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-void vpx_lpf_horizontal_16_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-void vpx_lpf_horizontal_16_avx2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-RTCD_EXTERN void (*vpx_lpf_horizontal_16)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-
-void vpx_lpf_horizontal_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-void vpx_lpf_horizontal_4_mmx(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-RTCD_EXTERN void (*vpx_lpf_horizontal_4)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_horizontal_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_horizontal_4_mmx(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+RTCD_EXTERN void (*vpx_lpf_horizontal_4)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 
 void vpx_lpf_horizontal_4_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 void vpx_lpf_horizontal_4_dual_sse2(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 RTCD_EXTERN void (*vpx_lpf_horizontal_4_dual)(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 
-void vpx_lpf_horizontal_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-void vpx_lpf_horizontal_8_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-RTCD_EXTERN void (*vpx_lpf_horizontal_8)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_horizontal_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_horizontal_8_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+RTCD_EXTERN void (*vpx_lpf_horizontal_8)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 
 void vpx_lpf_horizontal_8_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 void vpx_lpf_horizontal_8_dual_sse2(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 RTCD_EXTERN void (*vpx_lpf_horizontal_8_dual)(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 
+void vpx_lpf_horizontal_edge_16_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_horizontal_edge_16_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_horizontal_edge_16_avx2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+RTCD_EXTERN void (*vpx_lpf_horizontal_edge_16)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+
+void vpx_lpf_horizontal_edge_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_horizontal_edge_8_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_horizontal_edge_8_avx2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+RTCD_EXTERN void (*vpx_lpf_horizontal_edge_8)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+
 void vpx_lpf_vertical_16_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 void vpx_lpf_vertical_16_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 RTCD_EXTERN void (*vpx_lpf_vertical_16)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
@@ -437,17 +442,17 @@
 void vpx_lpf_vertical_16_dual_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 RTCD_EXTERN void (*vpx_lpf_vertical_16_dual)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 
-void vpx_lpf_vertical_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-void vpx_lpf_vertical_4_mmx(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-RTCD_EXTERN void (*vpx_lpf_vertical_4)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_vertical_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_vertical_4_mmx(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+RTCD_EXTERN void (*vpx_lpf_vertical_4)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 
 void vpx_lpf_vertical_4_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 void vpx_lpf_vertical_4_dual_sse2(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 RTCD_EXTERN void (*vpx_lpf_vertical_4_dual)(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 
-void vpx_lpf_vertical_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-void vpx_lpf_vertical_8_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-RTCD_EXTERN void (*vpx_lpf_vertical_8)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_vertical_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_vertical_8_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+RTCD_EXTERN void (*vpx_lpf_vertical_8)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 
 void vpx_lpf_vertical_8_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 void vpx_lpf_vertical_8_dual_sse2(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
@@ -1171,9 +1176,6 @@
     if (flags & HAS_SSE2) vpx_int_pro_row = vpx_int_pro_row_sse2;
     vpx_iwht4x4_16_add = vpx_iwht4x4_16_add_c;
     if (flags & HAS_SSE2) vpx_iwht4x4_16_add = vpx_iwht4x4_16_add_sse2;
-    vpx_lpf_horizontal_16 = vpx_lpf_horizontal_16_c;
-    if (flags & HAS_SSE2) vpx_lpf_horizontal_16 = vpx_lpf_horizontal_16_sse2;
-    if (flags & HAS_AVX2) vpx_lpf_horizontal_16 = vpx_lpf_horizontal_16_avx2;
     vpx_lpf_horizontal_4 = vpx_lpf_horizontal_4_c;
     if (flags & HAS_MMX) vpx_lpf_horizontal_4 = vpx_lpf_horizontal_4_mmx;
     vpx_lpf_horizontal_4_dual = vpx_lpf_horizontal_4_dual_c;
@@ -1182,6 +1184,12 @@
     if (flags & HAS_SSE2) vpx_lpf_horizontal_8 = vpx_lpf_horizontal_8_sse2;
     vpx_lpf_horizontal_8_dual = vpx_lpf_horizontal_8_dual_c;
     if (flags & HAS_SSE2) vpx_lpf_horizontal_8_dual = vpx_lpf_horizontal_8_dual_sse2;
+    vpx_lpf_horizontal_edge_16 = vpx_lpf_horizontal_edge_16_c;
+    if (flags & HAS_SSE2) vpx_lpf_horizontal_edge_16 = vpx_lpf_horizontal_edge_16_sse2;
+    if (flags & HAS_AVX2) vpx_lpf_horizontal_edge_16 = vpx_lpf_horizontal_edge_16_avx2;
+    vpx_lpf_horizontal_edge_8 = vpx_lpf_horizontal_edge_8_c;
+    if (flags & HAS_SSE2) vpx_lpf_horizontal_edge_8 = vpx_lpf_horizontal_edge_8_sse2;
+    if (flags & HAS_AVX2) vpx_lpf_horizontal_edge_8 = vpx_lpf_horizontal_edge_8_avx2;
     vpx_lpf_vertical_16 = vpx_lpf_vertical_16_c;
     if (flags & HAS_SSE2) vpx_lpf_vertical_16 = vpx_lpf_vertical_16_sse2;
     vpx_lpf_vertical_16_dual = vpx_lpf_vertical_16_dual_c;
diff --git a/third_party/libvpx/source/config/mac/x64/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/mac/x64/vpx_dsp_rtcd.h
index f249241..7eab80a 100644
--- a/third_party/libvpx/source/config/mac/x64/vpx_dsp_rtcd.h
+++ b/third_party/libvpx/source/config/mac/x64/vpx_dsp_rtcd.h
@@ -415,27 +415,32 @@
 void vpx_iwht4x4_1_add_c(const tran_low_t *input, uint8_t *dest, int dest_stride);
 #define vpx_iwht4x4_1_add vpx_iwht4x4_1_add_c
 
-void vpx_lpf_horizontal_16_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-void vpx_lpf_horizontal_16_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-void vpx_lpf_horizontal_16_avx2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-RTCD_EXTERN void (*vpx_lpf_horizontal_16)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-
-void vpx_lpf_horizontal_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-void vpx_lpf_horizontal_4_mmx(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_horizontal_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_horizontal_4_mmx(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_horizontal_4 vpx_lpf_horizontal_4_mmx
 
 void vpx_lpf_horizontal_4_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 void vpx_lpf_horizontal_4_dual_sse2(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 #define vpx_lpf_horizontal_4_dual vpx_lpf_horizontal_4_dual_sse2
 
-void vpx_lpf_horizontal_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-void vpx_lpf_horizontal_8_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_horizontal_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_horizontal_8_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_horizontal_8 vpx_lpf_horizontal_8_sse2
 
 void vpx_lpf_horizontal_8_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 void vpx_lpf_horizontal_8_dual_sse2(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 #define vpx_lpf_horizontal_8_dual vpx_lpf_horizontal_8_dual_sse2
 
+void vpx_lpf_horizontal_edge_16_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_horizontal_edge_16_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_horizontal_edge_16_avx2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+RTCD_EXTERN void (*vpx_lpf_horizontal_edge_16)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+
+void vpx_lpf_horizontal_edge_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_horizontal_edge_8_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_horizontal_edge_8_avx2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+RTCD_EXTERN void (*vpx_lpf_horizontal_edge_8)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+
 void vpx_lpf_vertical_16_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 void vpx_lpf_vertical_16_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_vertical_16 vpx_lpf_vertical_16_sse2
@@ -444,16 +449,16 @@
 void vpx_lpf_vertical_16_dual_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_vertical_16_dual vpx_lpf_vertical_16_dual_sse2
 
-void vpx_lpf_vertical_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-void vpx_lpf_vertical_4_mmx(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_vertical_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_vertical_4_mmx(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_vertical_4 vpx_lpf_vertical_4_mmx
 
 void vpx_lpf_vertical_4_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 void vpx_lpf_vertical_4_dual_sse2(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 #define vpx_lpf_vertical_4_dual vpx_lpf_vertical_4_dual_sse2
 
-void vpx_lpf_vertical_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-void vpx_lpf_vertical_8_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_vertical_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_vertical_8_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_vertical_8 vpx_lpf_vertical_8_sse2
 
 void vpx_lpf_vertical_8_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
@@ -1085,8 +1090,10 @@
     if (flags & HAS_SSSE3) vpx_idct8x8_12_add = vpx_idct8x8_12_add_ssse3;
     vpx_idct8x8_64_add = vpx_idct8x8_64_add_sse2;
     if (flags & HAS_SSSE3) vpx_idct8x8_64_add = vpx_idct8x8_64_add_ssse3;
-    vpx_lpf_horizontal_16 = vpx_lpf_horizontal_16_sse2;
-    if (flags & HAS_AVX2) vpx_lpf_horizontal_16 = vpx_lpf_horizontal_16_avx2;
+    vpx_lpf_horizontal_edge_16 = vpx_lpf_horizontal_edge_16_sse2;
+    if (flags & HAS_AVX2) vpx_lpf_horizontal_edge_16 = vpx_lpf_horizontal_edge_16_avx2;
+    vpx_lpf_horizontal_edge_8 = vpx_lpf_horizontal_edge_8_sse2;
+    if (flags & HAS_AVX2) vpx_lpf_horizontal_edge_8 = vpx_lpf_horizontal_edge_8_avx2;
     vpx_mse16x16 = vpx_mse16x16_sse2;
     if (flags & HAS_AVX2) vpx_mse16x16 = vpx_mse16x16_avx2;
     vpx_quantize_b = vpx_quantize_b_sse2;
diff --git a/third_party/libvpx/source/config/nacl/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/nacl/vpx_dsp_rtcd.h
index fe17035..b76c67a 100644
--- a/third_party/libvpx/source/config/nacl/vpx_dsp_rtcd.h
+++ b/third_party/libvpx/source/config/nacl/vpx_dsp_rtcd.h
@@ -319,34 +319,37 @@
 void vpx_iwht4x4_1_add_c(const tran_low_t *input, uint8_t *dest, int dest_stride);
 #define vpx_iwht4x4_1_add vpx_iwht4x4_1_add_c
 
-void vpx_lpf_horizontal_16_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-#define vpx_lpf_horizontal_16 vpx_lpf_horizontal_16_c
-
-void vpx_lpf_horizontal_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_horizontal_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_horizontal_4 vpx_lpf_horizontal_4_c
 
 void vpx_lpf_horizontal_4_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 #define vpx_lpf_horizontal_4_dual vpx_lpf_horizontal_4_dual_c
 
-void vpx_lpf_horizontal_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_horizontal_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_horizontal_8 vpx_lpf_horizontal_8_c
 
 void vpx_lpf_horizontal_8_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 #define vpx_lpf_horizontal_8_dual vpx_lpf_horizontal_8_dual_c
 
+void vpx_lpf_horizontal_edge_16_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+#define vpx_lpf_horizontal_edge_16 vpx_lpf_horizontal_edge_16_c
+
+void vpx_lpf_horizontal_edge_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+#define vpx_lpf_horizontal_edge_8 vpx_lpf_horizontal_edge_8_c
+
 void vpx_lpf_vertical_16_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_vertical_16 vpx_lpf_vertical_16_c
 
 void vpx_lpf_vertical_16_dual_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_vertical_16_dual vpx_lpf_vertical_16_dual_c
 
-void vpx_lpf_vertical_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_vertical_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_vertical_4 vpx_lpf_vertical_4_c
 
 void vpx_lpf_vertical_4_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 #define vpx_lpf_vertical_4_dual vpx_lpf_vertical_4_dual_c
 
-void vpx_lpf_vertical_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_vertical_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_vertical_8 vpx_lpf_vertical_8_c
 
 void vpx_lpf_vertical_8_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
diff --git a/third_party/libvpx/source/config/vpx_version.h b/third_party/libvpx/source/config/vpx_version.h
index 7fac6a4..5d2d329 100644
--- a/third_party/libvpx/source/config/vpx_version.h
+++ b/third_party/libvpx/source/config/vpx_version.h
@@ -1,7 +1,7 @@
 #define VERSION_MAJOR  1
 #define VERSION_MINOR  5
 #define VERSION_PATCH  0
-#define VERSION_EXTRA  "483-g89cc682"
+#define VERSION_EXTRA  "578-g9aa083d"
 #define VERSION_PACKED ((VERSION_MAJOR<<16)|(VERSION_MINOR<<8)|(VERSION_PATCH))
-#define VERSION_STRING_NOSP "v1.5.0-483-g89cc682"
-#define VERSION_STRING      " v1.5.0-483-g89cc682"
+#define VERSION_STRING_NOSP "v1.5.0-578-g9aa083d"
+#define VERSION_STRING      " v1.5.0-578-g9aa083d"
diff --git a/third_party/libvpx/source/config/win/ia32/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/win/ia32/vpx_dsp_rtcd.h
index a2aaf695..9c7f50b1 100644
--- a/third_party/libvpx/source/config/win/ia32/vpx_dsp_rtcd.h
+++ b/third_party/libvpx/source/config/win/ia32/vpx_dsp_rtcd.h
@@ -408,27 +408,32 @@
 void vpx_iwht4x4_1_add_c(const tran_low_t *input, uint8_t *dest, int dest_stride);
 #define vpx_iwht4x4_1_add vpx_iwht4x4_1_add_c
 
-void vpx_lpf_horizontal_16_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-void vpx_lpf_horizontal_16_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-void vpx_lpf_horizontal_16_avx2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-RTCD_EXTERN void (*vpx_lpf_horizontal_16)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-
-void vpx_lpf_horizontal_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-void vpx_lpf_horizontal_4_mmx(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-RTCD_EXTERN void (*vpx_lpf_horizontal_4)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_horizontal_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_horizontal_4_mmx(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+RTCD_EXTERN void (*vpx_lpf_horizontal_4)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 
 void vpx_lpf_horizontal_4_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 void vpx_lpf_horizontal_4_dual_sse2(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 RTCD_EXTERN void (*vpx_lpf_horizontal_4_dual)(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 
-void vpx_lpf_horizontal_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-void vpx_lpf_horizontal_8_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-RTCD_EXTERN void (*vpx_lpf_horizontal_8)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_horizontal_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_horizontal_8_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+RTCD_EXTERN void (*vpx_lpf_horizontal_8)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 
 void vpx_lpf_horizontal_8_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 void vpx_lpf_horizontal_8_dual_sse2(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 RTCD_EXTERN void (*vpx_lpf_horizontal_8_dual)(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 
+void vpx_lpf_horizontal_edge_16_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_horizontal_edge_16_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_horizontal_edge_16_avx2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+RTCD_EXTERN void (*vpx_lpf_horizontal_edge_16)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+
+void vpx_lpf_horizontal_edge_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_horizontal_edge_8_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_horizontal_edge_8_avx2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+RTCD_EXTERN void (*vpx_lpf_horizontal_edge_8)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+
 void vpx_lpf_vertical_16_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 void vpx_lpf_vertical_16_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 RTCD_EXTERN void (*vpx_lpf_vertical_16)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
@@ -437,17 +442,17 @@
 void vpx_lpf_vertical_16_dual_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 RTCD_EXTERN void (*vpx_lpf_vertical_16_dual)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 
-void vpx_lpf_vertical_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-void vpx_lpf_vertical_4_mmx(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-RTCD_EXTERN void (*vpx_lpf_vertical_4)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_vertical_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_vertical_4_mmx(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+RTCD_EXTERN void (*vpx_lpf_vertical_4)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 
 void vpx_lpf_vertical_4_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 void vpx_lpf_vertical_4_dual_sse2(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 RTCD_EXTERN void (*vpx_lpf_vertical_4_dual)(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 
-void vpx_lpf_vertical_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-void vpx_lpf_vertical_8_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-RTCD_EXTERN void (*vpx_lpf_vertical_8)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_vertical_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_vertical_8_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+RTCD_EXTERN void (*vpx_lpf_vertical_8)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 
 void vpx_lpf_vertical_8_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 void vpx_lpf_vertical_8_dual_sse2(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
@@ -1171,9 +1176,6 @@
     if (flags & HAS_SSE2) vpx_int_pro_row = vpx_int_pro_row_sse2;
     vpx_iwht4x4_16_add = vpx_iwht4x4_16_add_c;
     if (flags & HAS_SSE2) vpx_iwht4x4_16_add = vpx_iwht4x4_16_add_sse2;
-    vpx_lpf_horizontal_16 = vpx_lpf_horizontal_16_c;
-    if (flags & HAS_SSE2) vpx_lpf_horizontal_16 = vpx_lpf_horizontal_16_sse2;
-    if (flags & HAS_AVX2) vpx_lpf_horizontal_16 = vpx_lpf_horizontal_16_avx2;
     vpx_lpf_horizontal_4 = vpx_lpf_horizontal_4_c;
     if (flags & HAS_MMX) vpx_lpf_horizontal_4 = vpx_lpf_horizontal_4_mmx;
     vpx_lpf_horizontal_4_dual = vpx_lpf_horizontal_4_dual_c;
@@ -1182,6 +1184,12 @@
     if (flags & HAS_SSE2) vpx_lpf_horizontal_8 = vpx_lpf_horizontal_8_sse2;
     vpx_lpf_horizontal_8_dual = vpx_lpf_horizontal_8_dual_c;
     if (flags & HAS_SSE2) vpx_lpf_horizontal_8_dual = vpx_lpf_horizontal_8_dual_sse2;
+    vpx_lpf_horizontal_edge_16 = vpx_lpf_horizontal_edge_16_c;
+    if (flags & HAS_SSE2) vpx_lpf_horizontal_edge_16 = vpx_lpf_horizontal_edge_16_sse2;
+    if (flags & HAS_AVX2) vpx_lpf_horizontal_edge_16 = vpx_lpf_horizontal_edge_16_avx2;
+    vpx_lpf_horizontal_edge_8 = vpx_lpf_horizontal_edge_8_c;
+    if (flags & HAS_SSE2) vpx_lpf_horizontal_edge_8 = vpx_lpf_horizontal_edge_8_sse2;
+    if (flags & HAS_AVX2) vpx_lpf_horizontal_edge_8 = vpx_lpf_horizontal_edge_8_avx2;
     vpx_lpf_vertical_16 = vpx_lpf_vertical_16_c;
     if (flags & HAS_SSE2) vpx_lpf_vertical_16 = vpx_lpf_vertical_16_sse2;
     vpx_lpf_vertical_16_dual = vpx_lpf_vertical_16_dual_c;
diff --git a/third_party/libvpx/source/config/win/x64/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/win/x64/vpx_dsp_rtcd.h
index f249241..7eab80a 100644
--- a/third_party/libvpx/source/config/win/x64/vpx_dsp_rtcd.h
+++ b/third_party/libvpx/source/config/win/x64/vpx_dsp_rtcd.h
@@ -415,27 +415,32 @@
 void vpx_iwht4x4_1_add_c(const tran_low_t *input, uint8_t *dest, int dest_stride);
 #define vpx_iwht4x4_1_add vpx_iwht4x4_1_add_c
 
-void vpx_lpf_horizontal_16_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-void vpx_lpf_horizontal_16_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-void vpx_lpf_horizontal_16_avx2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-RTCD_EXTERN void (*vpx_lpf_horizontal_16)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-
-void vpx_lpf_horizontal_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-void vpx_lpf_horizontal_4_mmx(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_horizontal_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_horizontal_4_mmx(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_horizontal_4 vpx_lpf_horizontal_4_mmx
 
 void vpx_lpf_horizontal_4_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 void vpx_lpf_horizontal_4_dual_sse2(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 #define vpx_lpf_horizontal_4_dual vpx_lpf_horizontal_4_dual_sse2
 
-void vpx_lpf_horizontal_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-void vpx_lpf_horizontal_8_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_horizontal_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_horizontal_8_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_horizontal_8 vpx_lpf_horizontal_8_sse2
 
 void vpx_lpf_horizontal_8_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 void vpx_lpf_horizontal_8_dual_sse2(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 #define vpx_lpf_horizontal_8_dual vpx_lpf_horizontal_8_dual_sse2
 
+void vpx_lpf_horizontal_edge_16_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_horizontal_edge_16_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_horizontal_edge_16_avx2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+RTCD_EXTERN void (*vpx_lpf_horizontal_edge_16)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+
+void vpx_lpf_horizontal_edge_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_horizontal_edge_8_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_horizontal_edge_8_avx2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+RTCD_EXTERN void (*vpx_lpf_horizontal_edge_8)(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+
 void vpx_lpf_vertical_16_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 void vpx_lpf_vertical_16_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_vertical_16 vpx_lpf_vertical_16_sse2
@@ -444,16 +449,16 @@
 void vpx_lpf_vertical_16_dual_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_vertical_16_dual vpx_lpf_vertical_16_dual_sse2
 
-void vpx_lpf_vertical_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-void vpx_lpf_vertical_4_mmx(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_vertical_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_vertical_4_mmx(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_vertical_4 vpx_lpf_vertical_4_mmx
 
 void vpx_lpf_vertical_4_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 void vpx_lpf_vertical_4_dual_sse2(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 #define vpx_lpf_vertical_4_dual vpx_lpf_vertical_4_dual_sse2
 
-void vpx_lpf_vertical_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
-void vpx_lpf_vertical_8_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count);
+void vpx_lpf_vertical_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_vertical_8_sse2(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
 #define vpx_lpf_vertical_8 vpx_lpf_vertical_8_sse2
 
 void vpx_lpf_vertical_8_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
@@ -1085,8 +1090,10 @@
     if (flags & HAS_SSSE3) vpx_idct8x8_12_add = vpx_idct8x8_12_add_ssse3;
     vpx_idct8x8_64_add = vpx_idct8x8_64_add_sse2;
     if (flags & HAS_SSSE3) vpx_idct8x8_64_add = vpx_idct8x8_64_add_ssse3;
-    vpx_lpf_horizontal_16 = vpx_lpf_horizontal_16_sse2;
-    if (flags & HAS_AVX2) vpx_lpf_horizontal_16 = vpx_lpf_horizontal_16_avx2;
+    vpx_lpf_horizontal_edge_16 = vpx_lpf_horizontal_edge_16_sse2;
+    if (flags & HAS_AVX2) vpx_lpf_horizontal_edge_16 = vpx_lpf_horizontal_edge_16_avx2;
+    vpx_lpf_horizontal_edge_8 = vpx_lpf_horizontal_edge_8_sse2;
+    if (flags & HAS_AVX2) vpx_lpf_horizontal_edge_8 = vpx_lpf_horizontal_edge_8_avx2;
     vpx_mse16x16 = vpx_mse16x16_sse2;
     if (flags & HAS_AVX2) vpx_mse16x16 = vpx_mse16x16_avx2;
     vpx_quantize_b = vpx_quantize_b_sse2;
diff --git a/tools/android/loading/chrome_setup.py b/tools/android/loading/chrome_setup.py
index 9bf2908..245246d 100644
--- a/tools/android/loading/chrome_setup.py
+++ b/tools/android/loading/chrome_setup.py
@@ -2,7 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-"""Handles Chrome's configuration."""
+"""Handles Chrome's configuration. DEPRECATED!"""
 
 import contextlib
 import json
diff --git a/tools/android/loading/controller.py b/tools/android/loading/controller.py
new file mode 100644
index 0000000..28b3e97
--- /dev/null
+++ b/tools/android/loading/controller.py
@@ -0,0 +1,209 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Controller objects that control the context in which chrome runs.
+
+This is responsible for the setup necessary for launching chrome, and for
+creating a DevToolsConnection. There are remote device and local
+desktop-specific versions.
+"""
+
+import contextlib
+import os
+import shutil
+import subprocess
+import sys
+import tempfile
+import time
+
+_SRC_DIR = os.path.abspath(os.path.join(
+    os.path.dirname(__file__), '..', '..', '..'))
+
+import chrome_cache
+import device_setup
+import devtools_monitor
+import emulation
+import options
+
+sys.path.append(os.path.join(_SRC_DIR, 'third_party', 'catapult', 'devil'))
+from devil.android.sdk import intent
+
+OPTIONS = options.OPTIONS
+
+# An estimate of time to wait for the device to become idle after expensive
+# operations, such as opening the launcher activity.
+_TIME_TO_DEVICE_IDLE_SECONDS = 2
+
+
+class ChromeControllerBase(object):
+  """Base class for all controllers.
+
+  Defines common operations but should not be created directly.
+  """
+  def __init__(self):
+    self._chrome_args = [
+        '--disable-fre',
+        '--enable-test-events',
+        '--remote-debugging-port=%d' % OPTIONS.devtools_port,
+    ]
+    self._metadata = {}
+    self._emulated_device = None
+    self._emulated_network = None
+
+  def AddChromeArgument(self, arg):
+    """Add command-line argument to the chrome execution."""
+    self._chrome_args.append(arg)
+
+  @contextlib.contextmanager
+  def Open(self):
+    """Context that returns a connection/chrome instance."""
+    raise NotImplementedError
+
+  def ChromeMetadata(self):
+    """Return metadata such as emulation information.
+
+    Returns:
+      Metadata as JSON dictionary.
+    """
+    return self._metadata
+
+  def GetDevice(self):
+    """Returns an android device, or None if chrome is local."""
+    return None
+
+  def SetDeviceEmulation(self, device_name):
+    """Set device emulation.
+
+    Args:
+      device_name: (str) Key from --devices_file.
+    """
+    devices = emulation.LoadEmulatedDevices(file(OPTIONS.devices_file))
+    self._emulated_device = devices[device_name]
+
+  def SetNetworkEmulation(self, network_name):
+    """Set network emulation.
+
+    Args:
+      network_name: (str) Key from emulation.NETWORK_CONDITIONS.
+    """
+    self._emulated_network = emulation.NETWORK_CONDITIONS[network_name]
+
+  def _StartConnection(self, connection):
+    """This should be called after opening an appropriate connection."""
+    if self._emulated_device:
+      self._metadata.update(emulation.SetUpDeviceEmulationAndReturnMetadata(
+          connection, self._emulated_device))
+    if self._emulated_network:
+      emulation.SetUpNetworkEmulation(connection, **self._emulated_network)
+      self._metadata.update(self._emulated_network)
+
+
+class RemoteChromeController(ChromeControllerBase):
+  """A controller for an android device, aka remote chrome instance."""
+  # Seconds to sleep after starting chrome activity.
+  POST_ACTIVITY_SLEEP_SECONDS = 2
+
+  def __init__(self, device):
+    """Initialize the controller.
+
+    Args:
+      device: an andriod device.
+    """
+    assert device is not None, 'Should you be using LocalController instead?'
+    self._device = device
+    super(RemoteChromeController, self).__init__()
+    self._slow_death = False
+
+  @contextlib.contextmanager
+  def Open(self):
+    """Overridden connection creation."""
+    package_info = OPTIONS.ChromePackage()
+    command_line_path = '/data/local/chrome-command-line'
+
+    self._device.EnableRoot()
+    self._device.KillAll(package_info.package, quiet=True)
+
+    with device_setup.FlagReplacer(
+        self._device, command_line_path, self._chrome_flags):
+      start_intent = intent.Intent(
+          package=package_info.package, activity=package_info.activity,
+          data='about:blank')
+      self._device.StartActivity(start_intent, blocking=True)
+      time.sleep(self.POST_ACTIVITY_SLEEP_SECONDS)
+      with device_setup.ForwardPort(
+          self._device, 'tcp:%d' % OPTIONS.devtools_port,
+          'localabstract:chrome_devtools_remote'):
+        connection = devtools_monitor.DevToolsConnection(
+            OPTIONS.devtools_hostname, OPTIONS.devtools_port)
+        self._StartConnection(connection)
+        yield connection
+    if self._slow_death:
+      self._device.adb.Shell('am start com.google.android.launcher')
+      time.sleep(_TIME_TO_DEVICE_IDLE_SECONDS)
+      self._device.KillAll(OPTIONS.chrome_package_name, quiet=True)
+      time.sleep(_TIME_TO_DEVICE_IDLE_SECONDS)
+    self._device.KillAll(package_info.package, quiet=True)
+
+  def PushBrowserCache(self, cache_path):
+    """Push a chrome cache.
+
+    Args:
+      cache_path: The directory's path containing the cache locally.
+    """
+    chrome_cache.PushBrowserCache(self._device, cache_path)
+
+  def PullBrowserCache(self):
+    """Pull a chrome cache.
+
+    Returns:
+      Temporary directory containing all the browser cache. Caller will need to
+      remove this directory manually.
+    """
+    return chrome_cache.PullBrowserCache(self._device)
+
+  def SetSlowDeath(self, slow_death=True):
+    """Set to pause before final kill of chrome.
+
+    Gives time for caches to write.
+
+    Args:
+      slow_death: (bool) True if you want that which comes to all who live, to
+        be slow.
+    """
+    self._slow_death = slow_death
+
+
+class LocalChromeController(ChromeControllerBase):
+  """Controller for a local (desktop) chrome instance.
+
+  TODO(gabadie): implement cache push/pull and declare up in base class.
+  """
+  def __init__(self):
+    super(LocalChromeController, self).__init__()
+    if OPTIONS.no_sandbox:
+      self.AddChromeArgument('--no-sandbox')
+
+  @contextlib.contextmanager
+  def Open(self):
+    """Override for connection context."""
+    binary_filename = OPTIONS.local_binary
+    profile_dir = OPTIONS.local_profile_dir
+    using_temp_profile_dir = profile_dir is None
+    flags = self._chrome_flags
+    if using_temp_profile_dir:
+      profile_dir = tempfile.mkdtemp()
+      flags = '--user-data-dir=%s' + flags
+    chrome_out = None if OPTIONS.local_noisy else file('/dev/null', 'w')
+    process = subprocess.Popen(
+        [binary_filename] + flags, shell=False, stderr=chrome_out)
+    try:
+      time.sleep(10)
+      connection =  devtools_monitor.DevToolsConnection(
+          OPTIONS.devtools_hostname, OPTIONS.devtools_port)
+      self._StartConnection(connection)
+      yield connection
+    finally:
+      process.kill()
+      if using_temp_profile_dir:
+        shutil.rmtree(profile_dir)
diff --git a/tools/android/loading/device_setup.py b/tools/android/loading/device_setup.py
index 62b99b46..bb2b4d7 100644
--- a/tools/android/loading/device_setup.py
+++ b/tools/android/loading/device_setup.py
@@ -97,6 +97,7 @@
     device.adb.ForwardRemove(local)
 
 
+# Deprecated
 def _SetUpDevice(device, package_info):
   """Enables root and closes Chrome on a device."""
   device.EnableRoot()
@@ -189,6 +190,7 @@
     shutil.rmtree(temp_certificate_dir)
 
 
+# Deprecated
 @contextlib.contextmanager
 def _DevToolsConnectionOnDevice(device, flags):
   """Returns a DevToolsConnection context manager for a given device.
@@ -215,6 +217,7 @@
           OPTIONS.devtools_hostname, OPTIONS.devtools_port)
 
 
+# Deprecated, use *Controller.
 def DeviceConnection(device, additional_flags=None):
   """Context for starting recording on a device.
 
diff --git a/tools/android/loading/emulation.py b/tools/android/loading/emulation.py
new file mode 100644
index 0000000..fa2fd89
--- /dev/null
+++ b/tools/android/loading/emulation.py
@@ -0,0 +1,124 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Device and network emulation utilities via devtools."""
+
+import json
+
+# Copied from
+# WebKit/Source/devtools/front_end/network/NetworkConditionsSelector.js
+# Units:
+#   download/upload: byte/s
+#   latency: ms
+NETWORK_CONDITIONS = {
+    'GPRS': {
+        'download': 50 * 1024 / 8, 'upload': 20 * 1024 / 8, 'latency': 500},
+    'Regular 2G': {
+        'download': 250 * 1024 / 8, 'upload': 50 * 1024 / 8, 'latency': 300},
+    'Good 2G': {
+        'download': 450 * 1024 / 8, 'upload': 150 * 1024 / 8, 'latency': 150},
+    'Regular 3G': {
+        'download': 750 * 1024 / 8, 'upload': 250 * 1024 / 8, 'latency': 100},
+    'Good 3G': {
+        'download': 1.5 * 1024 * 1024 / 8, 'upload': 750 * 1024 / 8,
+        'latency': 40},
+    'Regular 4G': {
+        'download': 4 * 1024 * 1024 / 8, 'upload': 3 * 1024 * 1024 / 8,
+        'latency': 20},
+    'DSL': {
+        'download': 2 * 1024 * 1024 / 8, 'upload': 1 * 1024 * 1024 / 8,
+        'latency': 5},
+    'WiFi': {
+        'download': 30 * 1024 * 1024 / 8, 'upload': 15 * 1024 * 1024 / 8,
+        'latency': 2}
+}
+
+
+def LoadEmulatedDevices(registry):
+  """Loads a list of emulated devices from the DevTools JSON registry.
+
+  See, for example, third_party/WebKit/Source/devtools/front_end
+  /emulated_devices/module.json.
+
+  Args:
+    registry: A file-like object for the device registry (should be JSON).
+
+  Returns:
+    {'device_name': device}
+  """
+  json_dict = json.load(registry)
+  devices = {}
+  for device in json_dict['extensions']:
+    device = device['device']
+    devices[device['title']] = device
+  return devices
+
+
+def SetUpDeviceEmulationAndReturnMetadata(connection, device):
+  """Configures an instance of Chrome for device emulation.
+
+  Args:
+    connection: (DevToolsConnection)
+    device: (dict) An entry from LoadEmulatedDevices().
+
+  Returns:
+    A dict containing the device emulation metadata.
+  """
+  res = connection.SyncRequest('Emulation.canEmulate')
+  assert res['result'], 'Cannot set device emulation.'
+  data = _GetDeviceEmulationMetadata(device)
+  connection.SyncRequestNoResponse(
+      'Emulation.setDeviceMetricsOverride',
+      {'width': data['width'],
+       'height': data['height'],
+       'deviceScaleFactor': data['deviceScaleFactor'],
+       'mobile': data['mobile'],
+       'fitWindow': True})
+  connection.SyncRequestNoResponse('Network.setUserAgentOverride',
+                                   {'userAgent': data['userAgent']})
+  return data
+
+
+def SetUpNetworkEmulation(connection, latency, download, upload):
+  """Configures an instance of Chrome for network emulation.
+
+  See NETWORK_CONDITIONS for example (or valid?) emulation options.
+
+  Args:
+    connection: (DevToolsConnection)
+    latency: (float) Latency in ms.
+    download: (float) Download speed (Bytes / s).
+    upload: (float) Upload speed (Bytes / s).
+  """
+  res = connection.SyncRequest('Network.canEmulateNetworkConditions')
+  assert res['result'], 'Cannot set network emulation.'
+  connection.SyncRequestNoResponse(
+      'Network.emulateNetworkConditions',
+      {'offline': False, 'latency': latency, 'downloadThroughput': download,
+       'uploadThroughput': upload})
+
+
+def BandwidthToString(bandwidth):
+  """Converts a bandwidth to string.
+
+  Args:
+    bandwidth: The bandwidth to convert in byte/s. Must be a multiple of 1024/8.
+
+  Returns:
+    A string compatible with wpr --{up,down} command line flags.
+  """
+  assert bandwidth % (1024/8) == 0
+  bandwidth_kbps = (int(bandwidth) * 8) / 1024
+  if bandwidth_kbps % 1024:
+    return '{}Kbit/s'.format(bandwidth_kbps)
+  return '{}Mbit/s'.format(bandwidth_kbps / 1024)
+
+
+def _GetDeviceEmulationMetadata(device):
+  """Returns the metadata associated with a given device."""
+  return {'width': device['screen']['vertical']['width'],
+          'height': device['screen']['vertical']['height'],
+          'deviceScaleFactor': device['screen']['device-pixel-ratio'],
+          'mobile': 'mobile' in device['capabilities'],
+          'userAgent': device['user-agent']}
diff --git a/tools/android/loading/emulation_unittest.py b/tools/android/loading/emulation_unittest.py
new file mode 100644
index 0000000..9777e582
--- /dev/null
+++ b/tools/android/loading/emulation_unittest.py
@@ -0,0 +1,81 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+from StringIO import StringIO
+import unittest
+
+import emulation
+import test_utils
+
+
+_SRC_DIR = os.path.abspath(os.path.join(
+    os.path.dirname(__file__), '..', '..', '..'))
+
+
+class EmulationTestCase(unittest.TestCase):
+  def testLoadDevices(self):
+    devices = emulation.LoadEmulatedDevices(file(os.path.join(
+        _SRC_DIR, 'third_party/WebKit/Source/devtools/front_end',
+        'emulated_devices/module.json')))
+    # Just check we have something. We'll assume that if we were able to read
+    # the file without dying we must be ok.
+    self.assertTrue(devices)
+
+  def testSetUpDevice(self):
+    registry = StringIO("""{
+      "extensions": [
+          {
+              "type": "emulated-device",
+              "device": {
+                  "show-by-default": false,
+                  "title": "mattPhone" ,
+                  "screen": {
+                      "horizontal": {
+                          "width": 480,
+                          "height": 320
+                      },
+                      "device-pixel-ratio": 2,
+                      "vertical": {
+                          "width": 320,
+                          "height": 480
+                      }
+                  },
+                  "capabilities": [
+                      "touch",
+                      "mobile"
+                  ],
+                  "user-agent": "James Bond"
+              }
+          } ]}""")
+    devices = emulation.LoadEmulatedDevices(registry)
+    connection = test_utils.MockConnection(self)
+    connection.ExpectSyncRequest({'result': True}, 'Emulation.canEmulate')
+    metadata = emulation.SetUpDeviceEmulationAndReturnMetadata(
+        connection, devices['mattPhone'])
+    self.assertEqual(320, metadata['width'])
+    self.assertEqual('James Bond', metadata['userAgent'])
+    self.assertTrue(connection.AllExpectationsUsed())
+    self.assertEqual('Emulation.setDeviceMetricsOverride',
+                     connection.no_response_requests_seen[0][0])
+
+  def testSetUpNetwork(self):
+    connection = test_utils.MockConnection(self)
+    connection.ExpectSyncRequest({'result': True},
+                                 'Network.canEmulateNetworkConditions')
+    emulation.SetUpNetworkEmulation(connection, 120, 2048, 1024)
+    self.assertTrue(connection.AllExpectationsUsed())
+    self.assertEqual('Network.emulateNetworkConditions',
+                     connection.no_response_requests_seen[0][0])
+    self.assertEqual(
+        1024,
+        connection.no_response_requests_seen[0][1]['uploadThroughput'])
+
+  def testBandwidthToString(self):
+    self.assertEqual('16Kbit/s', emulation.BandwidthToString(2048))
+    self.assertEqual('8Mbit/s', emulation.BandwidthToString(1024 * 1024))
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/tools/android/loading/test_utils.py b/tools/android/loading/test_utils.py
index 5d2b617..f1c80c2 100644
--- a/tools/android/loading/test_utils.py
+++ b/tools/android/loading/test_utils.py
@@ -163,3 +163,47 @@
   @classmethod
   def FromRequestList(cls, requests, page_events=None, trace_events=None):
     return cls(LoadingTraceFromEvents(requests, page_events, trace_events))
+
+
+class MockConnection(object):
+  """Mock out connection for testing.
+
+  Use Expect* for requests expecting a repsonse. SyncRequestNoResponse puts
+  requests into no_response_requests_seen.
+
+  TODO(mattcary): use a standard mock system (the back-ported python3
+  unittest.mock? devil.utils.mock_calls?)
+
+  """
+  def __init__(self, test_case):
+    # List of (method, params) tuples.
+    self.no_response_requests_seen = []
+
+    self._test_case = test_case
+    self._expected_responses = {}
+
+  def ExpectSyncRequest(self, response, method, params=None):
+    """Test method when the connection is expected to make a SyncRequest.
+
+    Args:
+      response: (dict) the response to generate.
+      method: (str) the expected method in the call.
+      params: (dict) the expected params in the call.
+    """
+    self._expected_responses.setdefault(method, []).append((params, response))
+
+  def AllExpectationsUsed(self):
+    """Returns true when all expectations where used."""
+    return not self._expected_responses
+
+  def SyncRequestNoResponse(self, method, params):
+    """Mocked method."""
+    self.no_response_requests_seen.append((method, params))
+
+  def SyncRequest(self, method, params=None):
+    """Mocked method."""
+    expected_params, response = self._expected_responses[method].pop(0)
+    if not self._expected_responses[method]:
+      del self._expected_responses[method]
+    self._test_case.assertEqual(expected_params, params)
+    return response
diff --git a/tools/battor_agent/battor_agent.gyp b/tools/battor_agent/battor_agent.gyp
index abbb5cf7..974fbdef 100644
--- a/tools/battor_agent/battor_agent.gyp
+++ b/tools/battor_agent/battor_agent.gyp
@@ -14,7 +14,6 @@
         'battor_agent_lib',
         '../../device/serial/serial.gyp:device_serial',
         '../../device/serial/serial.gyp:device_serial_mojo',
-        '../../mojo/mojo_public.gyp:mojo_environment_standalone',
         '../../mojo/mojo_edk.gyp:mojo_system_impl',
       ],
       'sources': [
@@ -58,7 +57,6 @@
         '../../device/serial/serial.gyp:device_serial',
         '../../device/serial/serial.gyp:device_serial_test_util',
         '../../mojo/mojo_edk.gyp:mojo_system_impl',
-        '../../mojo/mojo_public.gyp:mojo_environment_standalone',
       	'../../testing/gmock.gyp:gmock',
         '../../testing/gtest.gyp:gtest',
       ],
diff --git a/tools/clang/plugins/ChromeClassTester.cpp b/tools/clang/plugins/ChromeClassTester.cpp
index ad7b82b..08e0d40d 100644
--- a/tools/clang/plugins/ChromeClassTester.cpp
+++ b/tools/clang/plugins/ChromeClassTester.cpp
@@ -120,7 +120,11 @@
 #if defined(LLVM_ON_UNIX)
   // Resolve the symlinktastic relative path and make it absolute.
   char resolvedPath[MAXPATHLEN];
-  if (realpath(filename.c_str(), resolvedPath)) {
+  if (options_.no_realpath) {
+    // Same reason as windows below, but we don't need to do
+    // the '\\' manipulation on linux.
+    filename.insert(filename.begin(), '/');
+  } else if (realpath(filename.c_str(), resolvedPath)) {
     filename = resolvedPath;
   }
 #endif
diff --git a/tools/clang/plugins/FindBadConstructsAction.cpp b/tools/clang/plugins/FindBadConstructsAction.cpp
index e8f103a6..ad9fc55 100644
--- a/tools/clang/plugins/FindBadConstructsAction.cpp
+++ b/tools/clang/plugins/FindBadConstructsAction.cpp
@@ -61,6 +61,8 @@
       options_.follow_macro_expansion = true;
     } else if (args[i] == "check-implicit-copy-ctors") {
       options_.check_implicit_copy_ctors = true;
+    } else if (args[i] == "no-realpath") {
+      options_.no_realpath = true;
     } else {
       parsed = false;
       llvm::errs() << "Unknown clang plugin argument: " << args[i] << "\n";
diff --git a/tools/clang/plugins/Options.h b/tools/clang/plugins/Options.h
index 58c66f4..e56084e 100644
--- a/tools/clang/plugins/Options.h
+++ b/tools/clang/plugins/Options.h
@@ -17,6 +17,10 @@
   // This is needed during the migration from ASTConsumer approach to the
   // RecursiveASTVisitor approach. See https://crbug.com/436357 for details.
   bool check_implicit_copy_ctors = false;
+
+  // This is needed for some distributed build-sytems to respect banned
+  // paths. See https://crbug.com/583454 for details.
+  bool no_realpath = false;
 };
 
 }  // namespace chrome_checker
diff --git a/tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp b/tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp
index 1f1928e..999a8672 100644
--- a/tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp
+++ b/tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp
@@ -432,19 +432,26 @@
 
   void run(const MatchFinder::MatchResult& result) override {
     const DeclNode* decl = result.Nodes.getNodeAs<DeclNode>("decl");
-    // If the decl originates inside a macro, just skip it completely.
-    clang::SourceLocation decl_loc =
-        TargetNodeTraits<clang::NamedDecl>::GetLoc(*decl);
-    if (decl_loc.isMacroID())
-      return;
     // If false, there's no name to be renamed.
     if (!decl->getIdentifier())
       return;
-    // If false, the name was not suitable for renaming.
+    clang::SourceLocation decl_loc =
+        TargetNodeTraits<clang::NamedDecl>::GetLoc(*decl);
+    if (decl_loc.isMacroID()) {
+      // Get the location of the spelling of the declaration. If token pasting
+      // was used this will be in "scratch space" and we don't know how to get
+      // from there back to/ the actual macro with the foo##bar text. So just
+      // don't replace in that case.
+      clang::SourceLocation spell =
+          result.SourceManager->getSpellingLoc(decl_loc);
+      if (strcmp(result.SourceManager->getBufferName(spell),
+                 "<scratch space>") == 0)
+        return;
+    }
     clang::ASTContext* context = result.Context;
     std::string new_name;
     if (!GetNameForDecl(*decl, *context, new_name))
-      return;
+      return;  // If false, the name was not suitable for renaming.
     llvm::StringRef old_name = decl->getName();
     if (old_name == new_name)
       return;
diff --git a/tools/clang/rewrite_to_chrome_style/tests/macros-expected.cc b/tools/clang/rewrite_to_chrome_style/tests/macros-expected.cc
index 2c8ff5c..f03e3a3 100644
--- a/tools/clang/rewrite_to_chrome_style/tests/macros-expected.cc
+++ b/tools/clang/rewrite_to_chrome_style/tests/macros-expected.cc
@@ -5,17 +5,20 @@
 // Identifiers in macros should never be rewritten, as the risk of things
 // breaking is extremely high.
 
-namespace blink {
-
 #define DEFINE_TYPE_CASTS(thisType, argumentType, argumentName, predicate) \
   inline thisType* to##thisType(argumentType* argumentName) {              \
     if (!predicate)                                                        \
       asm("int 3");                                                        \
     return static_cast<thisType*>(argumentName);                           \
+  }                                                                        \
+  inline long long ToInt(argumentType* argumentName) {                     \
+    return reinterpret_cast<long long>(argumentName);                      \
   }
 
 #define LIKELY(x) x
 
+namespace blink {
+
 struct Base {};
 struct Derived : public Base {};
 
@@ -26,6 +29,7 @@
   // 'toDerived' should not be renamed, since the definition lives inside
   // a macro invocation.
   Derived* derived_ptr = toDerived(base_ptr);
+  long long as_int = ToInt(base_ptr);
   // 'derivedPtr' should be renamed: it's a reference to a declaration defined
   // outside a macro invocation.
   if (LIKELY(derived_ptr)) {
diff --git a/tools/clang/rewrite_to_chrome_style/tests/macros-original.cc b/tools/clang/rewrite_to_chrome_style/tests/macros-original.cc
index 6ff5613b..3b6fdb5 100644
--- a/tools/clang/rewrite_to_chrome_style/tests/macros-original.cc
+++ b/tools/clang/rewrite_to_chrome_style/tests/macros-original.cc
@@ -5,17 +5,20 @@
 // Identifiers in macros should never be rewritten, as the risk of things
 // breaking is extremely high.
 
-namespace blink {
-
 #define DEFINE_TYPE_CASTS(thisType, argumentType, argumentName, predicate) \
   inline thisType* to##thisType(argumentType* argumentName) {              \
     if (!predicate)                                                        \
       asm("int 3");                                                        \
     return static_cast<thisType*>(argumentName);                           \
+  }                                                                        \
+  inline long long toInt(argumentType* argumentName) {                     \
+    return reinterpret_cast<long long>(argumentName);                      \
   }
 
 #define LIKELY(x) x
 
+namespace blink {
+
 struct Base {};
 struct Derived : public Base {};
 
@@ -26,6 +29,7 @@
   // 'toDerived' should not be renamed, since the definition lives inside
   // a macro invocation.
   Derived* derivedPtr = toDerived(basePtr);
+  long long asInt = toInt(basePtr);
   // 'derivedPtr' should be renamed: it's a reference to a declaration defined
   // outside a macro invocation.
   if (LIKELY(derivedPtr)) {
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 09ebfbb..1c569fae7 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -18023,6 +18023,28 @@
   <summary>Network channel used for invalidations.</summary>
 </histogram>
 
+<histogram name="IOS.ShareExtension.ReceivedEntriesCount" units="files">
+  <owner>olivierrobin@chromium.org</owner>
+  <summary>
+    The number of items received simultaneously in Chrome from the IOS share
+    extension.
+  </summary>
+</histogram>
+
+<histogram name="IOS.ShareExtension.ReceivedEntry"
+    enum="IOSShareExtensionReceivedEntryType">
+  <owner>olivierrobin@chromium.org</owner>
+  <summary>Type of the item received from the iOS share extension.</summary>
+</histogram>
+
+<histogram name="IOS.ShareExtension.ReceivedEntryDelay" units="ms">
+  <owner>olivierrobin@chromium.org</owner>
+  <summary>
+    The delay in milliseconds between the item creation in the extension and its
+    processing in Chrome.
+  </summary>
+</histogram>
+
 <histogram name="IPC.AttachmentBrokerPrivileged.BrokerAttachmentError"
     enum="IPCAttachmentBrokerPrivilegedBrokerAttachmentError">
   <owner>erikchen@chromium.org</owner>
@@ -71113,6 +71135,12 @@
   <int value="2" label="SubframeBlocked"/>
 </enum>
 
+<enum name="IOSShareExtensionReceivedEntryType" type="int">
+  <int value="0" label="Invalid item"/>
+  <int value="1" label="Cancelled item"/>
+  <int value="2" label="Reading list item"/>
+</enum>
+
 <enum name="IPCAttachmentBrokerPrivilegedBrokerAttachmentError" type="int">
   <int value="0" label="DESTINATION_FOUND">
     The brokerable attachment had a valid destination. This is the success case.
diff --git a/tools/valgrind/chrome_tests.py b/tools/valgrind/chrome_tests.py
index 24ace695..c3f3e585 100755
--- a/tools/valgrind/chrome_tests.py
+++ b/tools/valgrind/chrome_tests.py
@@ -410,10 +410,6 @@
     return self.SimpleTest("mojo_public_bindings",
                            "mojo_public_bindings_unittests")
 
-  def TestMojoPublicEnv(self):
-    return self.SimpleTest("mojo_public_env",
-                           "mojo_public_environment_unittests")
-
   def TestMojoPublicSystem(self):
     return self.SimpleTest("mojo_public_system",
                            "mojo_public_system_unittests")
@@ -707,8 +703,6 @@
     "mojo_public_utility_unittests": TestMojoPublicUtility,
     "mojo_public_bindings": TestMojoPublicBindings,
     "mojo_public_bindings_unittests": TestMojoPublicBindings,
-    "mojo_public_env": TestMojoPublicEnv,
-    "mojo_public_environment_unittests": TestMojoPublicEnv,
     "mojo_public_sysperf": TestMojoPublicSysPerf,
     "net": TestNet,              "net_unittests": TestNet,
     "net_perf": TestNetPerf,     "net_perftests": TestNetPerf,
diff --git a/ui/gfx/BUILD.gn b/ui/gfx/BUILD.gn
index fb1d5303e..c342cc7 100644
--- a/ui/gfx/BUILD.gn
+++ b/ui/gfx/BUILD.gn
@@ -701,6 +701,7 @@
       "range/range_mac_unittest.mm",
       "range/range_unittest.cc",
       "range/range_win_unittest.cc",
+      "screen_win_unittest.cc",
       "sequential_id_generator_unittest.cc",
       "shadow_value_unittest.cc",
       "skbitmap_operations_unittest.cc",
diff --git a/ui/ozone/platform/drm/gpu/drm_overlay_validator.cc b/ui/ozone/platform/drm/gpu/drm_overlay_validator.cc
index 1a66c81..9fb93b9 100644
--- a/ui/ozone/platform/drm/gpu/drm_overlay_validator.cc
+++ b/ui/ozone/platform/drm/gpu/drm_overlay_validator.cc
@@ -69,7 +69,6 @@
                                  const gfx::Rect& window_bounds,
                                  HardwareDisplayController* controller) {
   bool force_primary_format = false;
-  uint32_t optimal_format = original_format;
   uint32_t z_order = plane_z_order;
   // If Overlay completely covers primary and isn't transparent, try to find
   // optimal format w.r.t primary plane. This guarantees that optimal format
@@ -85,17 +84,17 @@
 #endif
   }
 
-  if (force_primary_format) {
-    optimal_format = DRM_FORMAT_XRGB8888;
-  } else {
-    if (controller->IsFormatSupported(DRM_FORMAT_UYVY, z_order)) {
-      optimal_format = DRM_FORMAT_UYVY;
-    } else if (controller->IsFormatSupported(DRM_FORMAT_XRGB8888, z_order)) {
-      optimal_format = DRM_FORMAT_XRGB8888;
-    }
+  if (force_primary_format)
+    return DRM_FORMAT_XRGB8888;
+
+  // YUV is preferable format if supported.
+  if (controller->IsFormatSupported(DRM_FORMAT_UYVY, z_order)) {
+    return DRM_FORMAT_UYVY;
+  } else if (controller->IsFormatSupported(DRM_FORMAT_XRGB8888, z_order)) {
+    return DRM_FORMAT_XRGB8888;
   }
 
-  return optimal_format;
+  return original_format;
 }
 
 }  // namespace
@@ -142,9 +141,10 @@
     gfx::Size scaled_buffer_size = GetScaledSize(
         overlay.buffer_size, overlay.display_rect, overlay.crop_rect);
 
-    scoped_refptr<ScanoutBuffer> buffer = GetBufferForPageFlipTest(
-        drm, scaled_buffer_size, GetFourCCFormatForFramebuffer(overlay.format),
-        buffer_generator_, &reusable_buffers);
+    uint32_t original_format = GetFourCCFormatForFramebuffer(overlay.format);
+    scoped_refptr<ScanoutBuffer> buffer =
+        GetBufferForPageFlipTest(drm, scaled_buffer_size, original_format,
+                                 buffer_generator_, &reusable_buffers);
     DCHECK(buffer);
 
     OverlayPlane plane(buffer, overlay.plane_z_order, overlay.transform,
@@ -153,6 +153,37 @@
 
     if (controller->TestPageFlip(test_list)) {
       overlay.is_overlay_candidate = true;
+
+      // If size scaling is needed, find an optimal format.
+      if (overlay.plane_z_order && scaled_buffer_size != overlay.buffer_size) {
+        uint32_t optimal_format = FindOptimalBufferFormat(
+            original_format, overlay.plane_z_order, overlay.display_rect,
+            window_->bounds(), controller);
+
+        if (original_format != optimal_format) {
+          OverlayPlane original_plain = test_list.back();
+          test_list.pop_back();
+          scoped_refptr<ScanoutBuffer> optimal_buffer =
+              GetBufferForPageFlipTest(drm, scaled_buffer_size, optimal_format,
+                                       buffer_generator_, &reusable_buffers);
+          DCHECK(optimal_buffer);
+
+          OverlayPlane optimal_plane(optimal_buffer, overlay.plane_z_order,
+                                     overlay.transform, overlay.display_rect,
+                                     overlay.crop_rect);
+          test_list.push_back(optimal_plane);
+
+          // If test failed here, it means even though optimal_format is
+          // supported, platform cannot support it with current combination of
+          // layers. This is usually the case when optimal_format needs certain
+          // capabilites (i.e. conversion, scaling etc) and needed hardware
+          // resources might be already in use. Fall back to original format.
+          if (!controller->TestPageFlip(test_list)) {
+            test_list.pop_back();
+            test_list.push_back(original_plain);
+          }
+        }
+      }
     } else {
       // If test failed here, platform cannot support this configuration
       // with current combination of layers. This is usually the case when this
@@ -166,7 +197,7 @@
     }
   }
 
-  UpdateOverlayHintsCache(drm, test_list, &reusable_buffers);
+  UpdateOverlayHintsCache(test_list);
 
   return validated_params;
 }
@@ -208,7 +239,8 @@
         target_size = original_size;
     }
 
-    if (original_size != target_size || original_format != target_format) {
+    // The size scaling piggybacks the format conversion.
+    if (original_size != target_size) {
       scoped_refptr<ScanoutBuffer> processed_buffer =
           plane.processing_callback.Run(target_size, target_format);
 
@@ -225,58 +257,26 @@
 }
 
 void DrmOverlayValidator::UpdateOverlayHintsCache(
-    const scoped_refptr<DrmDevice>& drm,
-    const OverlayPlaneList& plane_list,
-    std::vector<scoped_refptr<ScanoutBuffer>>* reusable_buffers) {
+    const OverlayPlaneList& plane_list) {
   const auto& iter = overlay_hints_cache_.Get(plane_list);
   if (iter != overlay_hints_cache_.end())
     return;
 
-  OverlayPlaneList preferred_format_test_list = plane_list;
-  HardwareDisplayController* controller = window_->GetController();
+  OverlayPlaneList hints_plane_list = plane_list;
   OverlayHintsList overlay_hints;
-  for (auto& plane : preferred_format_test_list) {
-    uint32_t original_format = plane.buffer->GetFramebufferPixelFormat();
-
-    if (plane.z_order == 0) {
-      overlay_hints.push_back(
-          OverlayHints(original_format, true /* scaling */));
-      continue;
-    }
-
-    uint32_t optimal_format = FindOptimalBufferFormat(
-        original_format, plane.z_order, plane.display_bounds, window_->bounds(),
-        controller);
-
-    if (optimal_format != original_format) {
-      scoped_refptr<ScanoutBuffer> original_buffer = plane.buffer;
-      plane.buffer =
-          GetBufferForPageFlipTest(drm, plane.buffer->GetSize(), optimal_format,
-                                   buffer_generator_, reusable_buffers);
-
-      if (!controller->TestPageFlip(preferred_format_test_list)) {
-        // If test failed here, it means even though optimal_format is
-        // supported, platform cannot support it with current combination of
-        // layers. This is usually the case when optimal_format needs certain
-        // capabilites (i.e. conversion, scaling etc) and needed hardware
-        // resources might be already in use. Fall back to original format.
-        optimal_format = original_format;
-        plane.buffer = original_buffer;
-      }
-    }
-
+  for (auto& plane : hints_plane_list) {
+    uint32_t format = plane.buffer->GetFramebufferPixelFormat();
     // TODO(kalyank): We always request scaling to be done by 3D engine, VPP
     // etc. We should use them only if downscaling is needed and let display
     // controller handle up-scaling on platforms which support it.
-    overlay_hints.push_back(OverlayHints(optimal_format, true /* scaling */));
+    overlay_hints.push_back(OverlayHints(format, true /* scaling */));
+
+    // Make sure we dont hold reference to buffer when caching this plane list.
+    plane.buffer = nullptr;
   }
 
-  // Make sure we dont hold reference to buffer when caching this plane list.
-  for (auto& plane : preferred_format_test_list)
-    plane.buffer = nullptr;
-
-  DCHECK(preferred_format_test_list.size() == overlay_hints.size());
-  overlay_hints_cache_.Put(preferred_format_test_list, overlay_hints);
+  DCHECK(hints_plane_list.size() == overlay_hints.size());
+  overlay_hints_cache_.Put(hints_plane_list, overlay_hints);
 }
 
 }  // namespace ui
diff --git a/ui/ozone/platform/drm/gpu/drm_overlay_validator.h b/ui/ozone/platform/drm/gpu/drm_overlay_validator.h
index fbe23d3..4ff1f78a 100644
--- a/ui/ozone/platform/drm/gpu/drm_overlay_validator.h
+++ b/ui/ozone/platform/drm/gpu/drm_overlay_validator.h
@@ -59,12 +59,8 @@
 
   using OverlayHintsList = std::vector<OverlayHints>;
 
-  // Check if we can optimize format for reducing Display controller read
-  // bandwidth for |plane_list| and cache the value.
-  void UpdateOverlayHintsCache(
-      const scoped_refptr<DrmDevice>& drm,
-      const OverlayPlaneList& plane_list,
-      std::vector<scoped_refptr<ScanoutBuffer>>* reusable_buffers);
+  // Update hints cache.
+  void UpdateOverlayHintsCache(const OverlayPlaneList& plane_list);
 
   DrmWindow* window_;  // Not owned.
   ScanoutBufferGenerator* buffer_generator_;  // Not owned.
diff --git a/ui/ozone/platform/drm/gpu/drm_overlay_validator_unittest.cc b/ui/ozone/platform/drm/gpu/drm_overlay_validator_unittest.cc
index 0530301..6622159 100644
--- a/ui/ozone/platform/drm/gpu/drm_overlay_validator_unittest.cc
+++ b/ui/ozone/platform/drm/gpu/drm_overlay_validator_unittest.cc
@@ -202,6 +202,40 @@
 
   ui::OverlayPlaneList plane_list =
       overlay_validator_->PrepareBuffersForPageFlip(plane_list_);
+  EXPECT_EQ(DRM_FORMAT_XRGB8888,
+            plane_list.back().buffer->GetFramebufferPixelFormat());
+  // Check if ClearCache actually clears the cache.
+  overlay_validator_->ClearCache();
+  plane_list = overlay_validator_->PrepareBuffersForPageFlip(plane_list_);
+  // There should be no entry in cache for this configuration and should return
+  // default value of DRM_FORMAT_XRGB8888.
+  EXPECT_EQ(DRM_FORMAT_XRGB8888,
+            plane_list.back().buffer->GetFramebufferPixelFormat());
+}
+
+TEST_F(DrmOverlayValidatorTest, ClearCacheOnResetWithScaling) {
+  // This test checks if we invalidate cache when Reset is called.
+  gfx::RectF crop_rect = gfx::RectF(0, 0, 0.5, 0.5);
+  overlay_params_.back().buffer_size = overlay_rect_.size();
+  overlay_params_.back().display_rect = overlay_rect_;
+  overlay_params_.back().crop_rect = crop_rect;
+  plane_list_.back().display_bounds = overlay_rect_;
+  plane_list_.back().crop_rect = crop_rect;
+  std::vector<uint32_t> xrgb_yuv_packed_formats = {DRM_FORMAT_XRGB8888,
+                                                   DRM_FORMAT_UYVY};
+
+  ui::FakePlaneInfo primary_plane_info(
+      100, 1 << 0, std::vector<uint32_t>(1, DRM_FORMAT_XRGB8888));
+  ui::FakePlaneInfo overlay_info(101, 1 << 0, xrgb_yuv_packed_formats);
+  std::vector<ui::FakePlaneInfo> planes_info{primary_plane_info, overlay_info};
+  plane_manager_->SetPlaneProperties(planes_info);
+  overlay_validator_->ClearCache();
+
+  overlay_validator_->TestPageFlip(overlay_params_, ui::OverlayPlaneList());
+
+  ui::OverlayPlaneList plane_list =
+      overlay_validator_->PrepareBuffersForPageFlip(plane_list_);
+  // Scaling allows format conversion.
   EXPECT_EQ(DRM_FORMAT_UYVY,
             plane_list.back().buffer->GetFramebufferPixelFormat());
   // Check if ClearCache actually clears the cache.
@@ -267,10 +301,9 @@
 #endif
 }
 
-TEST_F(DrmOverlayValidatorTest, OverlayPreferredFormat_YUV) {
+TEST_F(DrmOverlayValidatorTest, OverlayPreferredFormat) {
   plane_manager_->ResetPlaneCount();
   // This test checks for optimal format in case of non full screen video case.
-  // Prefer YUV as optimal format when Overlay supports it.
   overlay_params_.back().buffer_size = overlay_rect_.size();
   overlay_params_.back().display_rect = overlay_rect_;
   plane_list_.back().display_bounds = overlay_rect_;
@@ -290,6 +323,41 @@
   for (const auto& param : validated_params)
     EXPECT_TRUE(param.is_overlay_candidate);
 
+  EXPECT_EQ(3, plane_manager_->plane_count());
+
+  ui::OverlayPlaneList plane_list =
+      overlay_validator_->PrepareBuffersForPageFlip(plane_list_);
+  EXPECT_EQ(DRM_FORMAT_XRGB8888,
+            plane_list.back().buffer->GetFramebufferPixelFormat());
+}
+
+TEST_F(DrmOverlayValidatorTest, OverlayPreferredFormat_YUV) {
+  plane_manager_->ResetPlaneCount();
+  // This test checks for optimal format in case of non full screen video case.
+  // Prefer YUV as optimal format when Overlay supports it and scaling is
+  // needed.
+  gfx::RectF crop_rect = gfx::RectF(0, 0, 0.5, 0.5);
+  overlay_params_.back().buffer_size = overlay_rect_.size();
+  overlay_params_.back().display_rect = overlay_rect_;
+  overlay_params_.back().crop_rect = crop_rect;
+  plane_list_.back().display_bounds = overlay_rect_;
+  plane_list_.back().crop_rect = crop_rect;
+
+  std::vector<uint32_t> xrgb_yuv_packed_formats = {DRM_FORMAT_XRGB8888,
+                                                   DRM_FORMAT_UYVY};
+  ui::FakePlaneInfo primary_plane_info(
+      100, 1 << 0, std::vector<uint32_t>(1, DRM_FORMAT_XRGB8888));
+  ui::FakePlaneInfo overlay_info(101, 1 << 0, xrgb_yuv_packed_formats);
+  std::vector<ui::FakePlaneInfo> planes_info{primary_plane_info, overlay_info};
+  plane_manager_->SetPlaneProperties(planes_info);
+  overlay_validator_->ClearCache();
+
+  std::vector<ui::OverlayCheck_Params> validated_params =
+      overlay_validator_->TestPageFlip(overlay_params_, ui::OverlayPlaneList());
+
+  for (const auto& param : validated_params)
+    EXPECT_TRUE(param.is_overlay_candidate);
+
   EXPECT_EQ(5, plane_manager_->plane_count());
 
   ui::OverlayPlaneList plane_list =
@@ -367,9 +435,12 @@
       new ui::MockScanoutBuffer(primary_rect_.size())));
   EXPECT_TRUE(controller->Modeset(plane1, kDefaultMode));
 
+  gfx::RectF crop_rect = gfx::RectF(0, 0, 0.5, 0.5);
   overlay_params_.back().buffer_size = overlay_rect_.size();
   overlay_params_.back().display_rect = overlay_rect_;
+  overlay_params_.back().crop_rect = crop_rect;
   plane_list_.back().display_bounds = overlay_rect_;
+  plane_list_.back().crop_rect = crop_rect;
 
   ui::FakePlaneInfo primary_crtc_primary_plane(100, 1 << 0, only_rgb_format);
   ui::FakePlaneInfo primary_crtc_overlay(101, 1 << 0, xrgb_yuv_packed_formats);
@@ -391,8 +462,8 @@
 
   EXPECT_TRUE(validated_params.back().is_overlay_candidate);
 
-  // Both controllers have Overlay which support DRM_FORMAT_UYVY, hence this
-  // should be picked as the optimal format.
+  // Both controllers have Overlay which support DRM_FORMAT_UYVY, and scaling is
+  // needed, hence this should be picked as the optimal format.
   ui::OverlayPlaneList plane_list =
       overlay_validator_->PrepareBuffersForPageFlip(plane_list_);
   EXPECT_EQ(DRM_FORMAT_UYVY,
@@ -459,16 +530,11 @@
       overlay_validator_->TestPageFlip(overlay_params_, ui::OverlayPlaneList());
 
   EXPECT_TRUE(validated_params.back().is_overlay_candidate);
-  // Both controllers have Overlay which support DRM_FORMAT_UYVY, hence this
-  // should be picked as the optimal format.
   ui::OverlayPlaneList plane_list =
       overlay_validator_->PrepareBuffersForPageFlip(plane_list_);
-  EXPECT_EQ(DRM_FORMAT_UYVY,
+  EXPECT_EQ(DRM_FORMAT_XRGB8888,
             plane_list.back().buffer->GetFramebufferPixelFormat());
 
-  // DRM_FORMAT_XRGB8888 should be the preferred format when either of the
-  // controllers dont support UYVY format.
-
   // Check case where we dont have support for packed formats in Mirrored CRTC.
   planes_info.back().allowed_formats = only_rgb_format;
   plane_manager_->SetPlaneProperties(planes_info);
@@ -502,9 +568,12 @@
 TEST_F(DrmOverlayValidatorTest, OptimizeOnlyIfProcessingCallbackPresent) {
   // This test checks that we dont manipulate overlay buffers in case Processing
   // callback is not present.
+  gfx::RectF crop_rect = gfx::RectF(0, 0, 0.5, 0.5);
   overlay_params_.back().buffer_size = overlay_rect_.size();
   overlay_params_.back().display_rect = overlay_rect_;
+  overlay_params_.back().crop_rect = crop_rect;
   plane_list_.back().display_bounds = overlay_rect_;
+  plane_list_.back().crop_rect = crop_rect;
   std::vector<uint32_t> xrgb_yuv_packed_formats = {DRM_FORMAT_XRGB8888,
                                                    DRM_FORMAT_UYVY};
 
@@ -519,6 +588,7 @@
 
   ui::OverlayPlaneList plane_list =
       overlay_validator_->PrepareBuffersForPageFlip(plane_list_);
+  // Scaling allows format conversion.
   EXPECT_EQ(DRM_FORMAT_UYVY,
             plane_list.back().buffer->GetFramebufferPixelFormat());
   plane_list_.back().processing_callback.Reset();
@@ -531,9 +601,12 @@
 TEST_F(DrmOverlayValidatorTest, DontResetOriginalBufferIfProcessedIsInvalid) {
   // This test checks that we dont manipulate overlay buffers in case Processing
   // callback is not present.
+  gfx::RectF crop_rect = gfx::RectF(0, 0, 0.5, 0.5);
   overlay_params_.back().buffer_size = overlay_rect_.size();
   overlay_params_.back().display_rect = overlay_rect_;
+  overlay_params_.back().crop_rect = crop_rect;
   plane_list_.back().display_bounds = overlay_rect_;
+  plane_list_.back().crop_rect = crop_rect;
   std::vector<uint32_t> xrgb_yuv_packed_formats = {DRM_FORMAT_XRGB8888,
                                                    DRM_FORMAT_UYVY};
 
@@ -548,6 +621,7 @@
 
   ui::OverlayPlaneList plane_list =
       overlay_validator_->PrepareBuffersForPageFlip(plane_list_);
+  // Scaling allows format conversion.
   EXPECT_EQ(DRM_FORMAT_UYVY,
             plane_list.back().buffer->GetFramebufferPixelFormat());
   plane_list_.back().processing_callback = base::Bind(
diff --git a/ui/views/win/fullscreen_handler.cc b/ui/views/win/fullscreen_handler.cc
index 2f7d077..a40cfc54 100644
--- a/ui/views/win/fullscreen_handler.cc
+++ b/ui/views/win/fullscreen_handler.cc
@@ -14,11 +14,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 // FullscreenHandler, public:
 
-FullscreenHandler::FullscreenHandler()
-    : hwnd_(NULL),
-      fullscreen_(false),
-      metro_snap_(false) {
-}
+FullscreenHandler::FullscreenHandler() : hwnd_(NULL), fullscreen_(false) {}
 
 FullscreenHandler::~FullscreenHandler() {
 }
@@ -27,15 +23,7 @@
   if (fullscreen_ == fullscreen)
     return;
 
-  SetFullscreenImpl(fullscreen, false);
-}
-
-void FullscreenHandler::SetMetroSnap(bool metro_snap) {
-  if (metro_snap_ == metro_snap)
-    return;
-
-  SetFullscreenImpl(metro_snap, true);
-  metro_snap_ = metro_snap;
+  SetFullscreenImpl(fullscreen);
 }
 
 gfx::Rect FullscreenHandler::GetRestoreBounds() const {
@@ -45,7 +33,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 // FullscreenHandler, private:
 
-void FullscreenHandler::SetFullscreenImpl(bool fullscreen, bool for_metro) {
+void FullscreenHandler::SetFullscreenImpl(bool fullscreen) {
   ScopedFullscreenVisibility visibility(hwnd_);
 
   // Save current window state if not already fullscreen.
@@ -73,16 +61,14 @@
 
     // On expand, if we're given a window_rect, grow to it, otherwise do
     // not resize.
-    if (!for_metro) {
-      MONITORINFO monitor_info;
-      monitor_info.cbSize = sizeof(monitor_info);
-      GetMonitorInfo(MonitorFromWindow(hwnd_, MONITOR_DEFAULTTONEAREST),
-                     &monitor_info);
-      gfx::Rect window_rect(monitor_info.rcMonitor);
-      SetWindowPos(hwnd_, NULL, window_rect.x(), window_rect.y(),
-                   window_rect.width(), window_rect.height(),
-                   SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
-    }
+    MONITORINFO monitor_info;
+    monitor_info.cbSize = sizeof(monitor_info);
+    GetMonitorInfo(MonitorFromWindow(hwnd_, MONITOR_DEFAULTTONEAREST),
+                   &monitor_info);
+    gfx::Rect window_rect(monitor_info.rcMonitor);
+    SetWindowPos(hwnd_, NULL, window_rect.x(), window_rect.y(),
+                 window_rect.width(), window_rect.height(),
+                 SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
   } else {
     // Reset original window style and size.  The multiple window size/moves
     // here are ugly, but if SetWindowPos() doesn't redraw, the taskbar won't be
@@ -90,13 +76,11 @@
     SetWindowLong(hwnd_, GWL_STYLE, saved_window_info_.style);
     SetWindowLong(hwnd_, GWL_EXSTYLE, saved_window_info_.ex_style);
 
-    if (!for_metro) {
-      // On restore, resize to the previous saved rect size.
-      gfx::Rect new_rect(saved_window_info_.window_rect);
-      SetWindowPos(hwnd_, NULL, new_rect.x(), new_rect.y(),
-                   new_rect.width(), new_rect.height(),
-                   SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
-    }
+    // On restore, resize to the previous saved rect size.
+    gfx::Rect new_rect(saved_window_info_.window_rect);
+    SetWindowPos(hwnd_, NULL, new_rect.x(), new_rect.y(), new_rect.width(),
+                 new_rect.height(),
+                 SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
     if (saved_window_info_.maximized)
       ::SendMessage(hwnd_, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
   }
diff --git a/ui/views/win/fullscreen_handler.h b/ui/views/win/fullscreen_handler.h
index 176cbed5..b23b142 100644
--- a/ui/views/win/fullscreen_handler.h
+++ b/ui/views/win/fullscreen_handler.h
@@ -25,12 +25,10 @@
   void set_hwnd(HWND hwnd) { hwnd_ = hwnd; }
 
   void SetFullscreen(bool fullscreen);
-  void SetMetroSnap(bool metro_snap);
 
   gfx::Rect GetRestoreBounds() const;
 
   bool fullscreen() const { return fullscreen_; }
-  bool metro_snap() const { return metro_snap_; }
 
  private:
   // Information saved before going into fullscreen mode, used to restore the
@@ -42,11 +40,10 @@
     RECT window_rect;
   };
 
-  void SetFullscreenImpl(bool fullscreen, bool for_metro);
+  void SetFullscreenImpl(bool fullscreen);
 
   HWND hwnd_;
   bool fullscreen_;
-  bool metro_snap_;
 
   // Saved window information from before entering fullscreen mode.
   // TODO(beng): move to private once GetRestoredBounds() moves onto Widget.
@@ -57,4 +54,4 @@
 
 }  // namespace views
 
-#endif  // UI_VIEWS_WIN_FULLSCREEN_HANDLER_H_
\ No newline at end of file
+#endif  // UI_VIEWS_WIN_FULLSCREEN_HANDLER_H_
diff --git a/ui/views/win/hwnd_message_handler.cc b/ui/views/win/hwnd_message_handler.cc
index 71eeafc..88387d4 100644
--- a/ui/views/win/hwnd_message_handler.cc
+++ b/ui/views/win/hwnd_message_handler.cc
@@ -2221,7 +2221,6 @@
       }
       if (monitor && (monitor == last_monitor_) &&
           ((fullscreen_handler_->fullscreen() &&
-            !fullscreen_handler_->metro_snap() &&
             !background_fullscreen_hack_) ||
             work_area_changed)) {
         // A rect for the monitor we're on changed.  Normally Windows notifies