diff --git a/BUILD.gn b/BUILD.gn
index b804a562..9e0e2fd8 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -267,6 +267,10 @@
         "//ui/ozone/gl:ozone_gl_unittests",
       ]
     }
+
+    if (ozone_platform_x11) {
+      deps += [ "//ui/ozone:ozone_x11_unittests" ]
+    }
   }
 
   if (use_x11 || ozone_platform_x11) {
diff --git a/DEPS b/DEPS
index 4cb13098..4d4a9ed0 100644
--- a/DEPS
+++ b/DEPS
@@ -313,7 +313,7 @@
 
   # For Linux and Chromium OS.
   'src/third_party/cros_system_api': {
-      'url': Var('chromium_git') + '/chromiumos/platform/system_api.git' + '@' + 'caeea330067c6b166a877f1198cf9a7534c2a3d4',
+      'url': Var('chromium_git') + '/chromiumos/platform/system_api.git' + '@' + '3d171a2fcf084cfbafe35eb910c3df2883a1a0cc',
       'condition': 'checkout_linux',
   },
 
@@ -404,7 +404,7 @@
     Var('chromium_git') + '/chromium/deps/hunspell_dictionaries.git' + '@' + 'a9bac57ce6c9d390a52ebaad3259f5fdb871210e',
 
   'src/third_party/icu':
-    Var('chromium_git') + '/chromium/deps/icu.git' + '@' + '26f7d8ad2f7c6c902825a985146a1d9d68e783cb',
+    Var('chromium_git') + '/chromium/deps/icu.git' + '@' + 'e3b480d3be4446ea17011c0cdc9c4cd380a5c58f',
 
   'src/third_party/jsoncpp/source':
     Var('chromium_git') + '/external/github.com/open-source-parsers/jsoncpp.git' + '@' + 'f572e8e42e22cfcf5ab0aea26574f408943edfa4', # from svn 248
diff --git a/android_webview/java/src/org/chromium/android_webview/AwAutofillProvider.java b/android_webview/java/src/org/chromium/android_webview/AwAutofillProvider.java
index 06bf771..e95e04c 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwAutofillProvider.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwAutofillProvider.java
@@ -293,6 +293,27 @@
         notifyVirtualValueChanged(index);
     }
 
+    @Override
+    public void onTextFieldDidScroll(int index, float x, float y, float width, float height) {
+        // crbug.com/730764 - from P and above, Android framework listens to the onScrollChanged()
+        // and repositions the autofill UI automatically.
+        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O_MR1) return;
+        if (mRequest == null) return;
+
+        short sIndex = (short) index;
+        FocusField focusField = mRequest.getFocusField();
+        if (focusField == null || sIndex != focusField.fieldIndex) return;
+
+        int virtualId = mRequest.getVirtualId(sIndex);
+        Rect absBound = transformToWindowBounds(new RectF(x, y, x + width, y + height));
+        // Notify the new position to the Android framework. Note that we do not call
+        // notifyVirtualViewExited() here intentionally to avoid flickering.
+        mAutofillManager.notifyVirtualViewEntered(mContainerView, virtualId, absBound);
+
+        // Update focus field position.
+        mRequest.setFocusField(new FocusField(focusField.fieldIndex, absBound));
+    }
+
     private void notifyVirtualValueChanged(int index) {
         AutofillValue autofillValue = mRequest.getFieldNewValue(index);
         if (autofillValue == null) return;
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwAutofillTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwAutofillTest.java
index 0c7cf09..e35cdbd 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AwAutofillTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwAutofillTest.java
@@ -518,16 +518,32 @@
     @Test
     @SmallTest
     @Feature({"AndroidWebView"})
-    public void testTouchingFormBasicTest() throws Throwable {
-        // Currently, touching form triggers autofill only when the app resizes on showing soft
-        // input keyboard. (https://crbug.com/730764)
-        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+    public void testTouchingFormWithAdjustResize() throws Throwable {
+        ThreadUtils.runOnUiThread(new Runnable() {
             @Override
             public void run() {
                 mRule.getActivity().getWindow().setSoftInputMode(
                         WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
             }
         });
+        internalTestTriggerTest();
+    }
+
+    @Test
+    @SmallTest
+    @Feature({"AndroidWebView"})
+    public void testTouchingFormWithAdjustPan() throws Throwable {
+        ThreadUtils.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mRule.getActivity().getWindow().setSoftInputMode(
+                        WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
+            }
+        });
+        internalTestTriggerTest();
+    }
+
+    private void internalTestTriggerTest() throws Throwable {
         TestWebServer webServer = TestWebServer.start();
         final String data = "<html><head></head><body><form action='a.html' name='formname'>"
                 + "<input type='text' id='text1' name='username'"
diff --git a/build/android/buildhooks/OWNERS b/build/android/buildhooks/OWNERS
index a512a5a..c964495 100644
--- a/build/android/buildhooks/OWNERS
+++ b/build/android/buildhooks/OWNERS
@@ -1,5 +1,4 @@
 agrieve@chromium.org
 estevenson@chromium.org
-zpeng@chromium.org
 
 # COMPONENT: Build
diff --git a/build/android/bytecode/OWNERS b/build/android/bytecode/OWNERS
index a512a5a..c964495 100644
--- a/build/android/bytecode/OWNERS
+++ b/build/android/bytecode/OWNERS
@@ -1,5 +1,4 @@
 agrieve@chromium.org
 estevenson@chromium.org
-zpeng@chromium.org
 
 # COMPONENT: Build
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index f068835b..6beaf612 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -407,6 +407,9 @@
     ImageInvalidationUpdateDurationHistogramTimer image_invalidation_timer;
     PaintImageIdFlatSet images_to_invalidate =
         tile_manager_.TakeImagesToInvalidateOnSyncTree();
+    if (ukm_manager_)
+      ukm_manager_->AddCheckerboardedImages(images_to_invalidate.size());
+
     if (image_animation_controller_.has_value()) {
       const auto& animated_images =
           image_animation_controller_.value().AnimateForSyncTree(
diff --git a/cc/trees/layer_tree_host_unittest_checkerimaging.cc b/cc/trees/layer_tree_host_unittest_checkerimaging.cc
index 3a96d3b3..f71c658 100644
--- a/cc/trees/layer_tree_host_unittest_checkerimaging.cc
+++ b/cc/trees/layer_tree_host_unittest_checkerimaging.cc
@@ -8,18 +8,40 @@
 #include "cc/test/layer_tree_test.h"
 #include "cc/test/skia_common.h"
 #include "cc/trees/layer_tree_impl.h"
+#include "components/ukm/test_ukm_recorder.h"
 #include "components/viz/test/begin_frame_args_test.h"
 #include "components/viz/test/fake_external_begin_frame_source.h"
 #include "components/viz/test/test_layer_tree_frame_sink.h"
 
 namespace cc {
 namespace {
+const char kRenderingEvent[] = "Compositor.Rendering";
+const char kCheckerboardImagesMetric[] = "CheckerboardedImagesCount";
 
 class LayerTreeHostCheckerImagingTest : public LayerTreeTest {
  public:
-  void BeginTest() override { PostSetNeedsCommitToMainThread(); }
+  LayerTreeHostCheckerImagingTest() : url_(GURL("https://example.com")) {}
+
+  void BeginTest() override {
+    layer_tree_host()->SetURLForUkm(url_);
+    PostSetNeedsCommitToMainThread();
+  }
   void AfterTest() override {}
 
+  void VerifyUkmAndEndTest(LayerTreeHostImpl* impl) {
+    // Change the URL to ensure any accumulated metrics are flushed.
+    impl->ukm_manager()->SetSourceURL(GURL("chrome://test2"));
+
+    auto* recorder = static_cast<ukm::TestUkmRecorder*>(
+        impl->ukm_manager()->recorder_for_testing());
+    const auto& entries = recorder->GetEntriesByName(kRenderingEvent);
+    ASSERT_EQ(1u, entries.size());
+    auto* entry = entries[0];
+    recorder->ExpectEntrySourceHasUrl(entry, url_);
+    recorder->ExpectEntryMetric(entry, kCheckerboardImagesMetric, 1);
+    EndTest();
+  }
+
   void InitializeSettings(LayerTreeSettings* settings) override {
     settings->enable_checker_imaging = true;
     settings->min_image_bytes_to_checker = 512 * 1024;
@@ -50,6 +72,7 @@
  private:
   // Accessed only on the main thread.
   FakeContentLayerClient content_layer_client_;
+  GURL url_;
 };
 
 class LayerTreeHostCheckerImagingTestMergeWithMainFrame
@@ -118,7 +141,7 @@
         expected_update_rect.Union(gfx::Rect(600, 0, 50, 500));
         EXPECT_EQ(sync_layer_impl->update_rect(), expected_update_rect);
 
-        EndTest();
+        VerifyUkmAndEndTest(host_impl);
       } break;
       default:
         NOTREACHED();
@@ -182,8 +205,9 @@
 
   void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) override {
     num_of_activations_++;
-    if (num_of_activations_ == 2)
-      EndTest();
+    if (num_of_activations_ == 2) {
+      VerifyUkmAndEndTest(host_impl);
+    }
   }
 
   void AfterTest() override {
diff --git a/cc/trees/ukm_manager.cc b/cc/trees/ukm_manager.cc
index 8a817d5..cf500c92 100644
--- a/cc/trees/ukm_manager.cc
+++ b/cc/trees/ukm_manager.cc
@@ -14,11 +14,15 @@
   DCHECK(recorder_);
 }
 
-UkmManager::~UkmManager() = default;
+UkmManager::~UkmManager() {
+  RecordCheckerboardUkm();
+  RecordRenderingUkm();
+}
 
 void UkmManager::SetSourceURL(const GURL& url) {
   // If we accumulating any metrics, record them before reseting the source.
   RecordCheckerboardUkm();
+  RecordRenderingUkm();
 
   source_id_ = recorder_->GetNewSourceID();
   recorder_->UpdateSourceURL(source_id_, url);
@@ -46,6 +50,14 @@
   num_of_frames_++;
 }
 
+void UkmManager::AddCheckerboardedImages(int num_of_checkerboarded_images) {
+  if (user_interaction_in_progress_) {
+    num_of_images_checkerboarded_during_interaction_ +=
+        num_of_checkerboarded_images;
+  }
+  total_num_of_checkerboarded_images_ += num_of_checkerboarded_images;
+}
+
 void UkmManager::RecordCheckerboardUkm() {
   // Only make a recording if there was any visible area from PictureLayers,
   // which can be checkerboarded.
@@ -57,6 +69,8 @@
         .SetNumMissingTiles(num_missing_tiles_ / num_of_frames_)
         .SetCheckerboardedContentAreaRatio(
             (checkerboarded_content_area_ * 100) / total_visible_area_)
+        .SetCheckerboardedImagesCount(
+            num_of_images_checkerboarded_during_interaction_)
         .Record(recorder_.get());
   }
 
@@ -64,6 +78,17 @@
   num_missing_tiles_ = 0;
   num_of_frames_ = 0;
   total_visible_area_ = 0;
+  num_of_images_checkerboarded_during_interaction_ = 0;
+}
+
+void UkmManager::RecordRenderingUkm() {
+  if (source_id_ == ukm::kInvalidSourceId)
+    return;
+
+  ukm::builders::Compositor_Rendering(source_id_)
+      .SetCheckerboardedImagesCount(total_num_of_checkerboarded_images_)
+      .Record(recorder_.get());
+  total_num_of_checkerboarded_images_ = 0;
 }
 
 }  // namespace cc
diff --git a/cc/trees/ukm_manager.h b/cc/trees/ukm_manager.h
index 7521ccc..fef49175 100644
--- a/cc/trees/ukm_manager.h
+++ b/cc/trees/ukm_manager.h
@@ -29,22 +29,30 @@
 
   void SetSourceURL(const GURL& url);
 
+  // These metrics are recorded while a user interaction is in progress.
   void SetUserInteractionInProgress(bool in_progress);
   void AddCheckerboardStatsForFrame(int64_t checkerboard_area,
                                     int64_t num_missing_tiles,
                                     int64_t total_visible_area);
 
+  // These metrics are recorded until the source URL changes.
+  void AddCheckerboardedImages(int num_of_checkerboarded_images);
+
   ukm::UkmRecorder* recorder_for_testing() { return recorder_.get(); }
 
  private:
   void RecordCheckerboardUkm();
+  void RecordRenderingUkm();
 
   bool user_interaction_in_progress_ = false;
+  int64_t num_of_images_checkerboarded_during_interaction_ = 0;
   int64_t checkerboarded_content_area_ = 0;
   int64_t num_missing_tiles_ = 0;
   int64_t total_visible_area_ = 0;
   int64_t num_of_frames_ = 0;
 
+  int total_num_of_checkerboarded_images_ = 0;
+
   ukm::SourceId source_id_ = ukm::kInvalidSourceId;
   std::unique_ptr<ukm::UkmRecorder> recorder_;
 };
diff --git a/cc/trees/ukm_manager_unittest.cc b/cc/trees/ukm_manager_unittest.cc
index f9ad62bc..f69ab61 100644
--- a/cc/trees/ukm_manager_unittest.cc
+++ b/cc/trees/ukm_manager_unittest.cc
@@ -14,9 +14,12 @@
 const char kTestUrl2[] = "https://example.com/bar";
 
 const char kUserInteraction[] = "Compositor.UserInteraction";
+const char kRendering[] = "Compositor.Rendering";
+
 const char kCheckerboardArea[] = "CheckerboardedContentArea";
 const char kCheckerboardAreaRatio[] = "CheckerboardedContentAreaRatio";
 const char kMissingTiles[] = "NumMissingTiles";
+const char kCheckerboardedImagesCount[] = "CheckerboardedImagesCount";
 
 class UkmManagerTest : public testing::Test {
  public:
@@ -36,6 +39,7 @@
   manager_->SetUserInteractionInProgress(true);
   manager_->AddCheckerboardStatsForFrame(5, 1, 10);
   manager_->AddCheckerboardStatsForFrame(15, 3, 30);
+  manager_->AddCheckerboardedImages(6);
   manager_->SetUserInteractionInProgress(false);
 
   // We should see a single entry for the interaction above.
@@ -49,6 +53,7 @@
     test_ukm_recorder_->ExpectEntryMetric(entry, kCheckerboardArea, 10);
     test_ukm_recorder_->ExpectEntryMetric(entry, kMissingTiles, 2);
     test_ukm_recorder_->ExpectEntryMetric(entry, kCheckerboardAreaRatio, 50);
+    test_ukm_recorder_->ExpectEntryMetric(entry, kCheckerboardedImagesCount, 6);
   }
   test_ukm_recorder_->Purge();
 
@@ -75,6 +80,16 @@
     test_ukm_recorder_->ExpectEntryMetric(entry, kCheckerboardArea, 20);
     test_ukm_recorder_->ExpectEntryMetric(entry, kMissingTiles, 3);
     test_ukm_recorder_->ExpectEntryMetric(entry, kCheckerboardAreaRatio, 20);
+    test_ukm_recorder_->ExpectEntryMetric(entry, kCheckerboardedImagesCount, 0);
+  }
+
+  // An entry for rendering is emitted when the URL changes.
+  const auto& entries_rendering =
+      test_ukm_recorder_->GetEntriesByName(kRendering);
+  EXPECT_EQ(1u, entries_rendering.size());
+  for (const auto* entry : entries_rendering) {
+    EXPECT_EQ(original_id, entry->source_id);
+    test_ukm_recorder_->ExpectEntryMetric(entry, kCheckerboardedImagesCount, 6);
   }
 }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
index 7dd2046..34089a8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
@@ -204,6 +204,7 @@
     public static final String DONT_PREFETCH_LIBRARIES = "DontPrefetchLibraries";
     public static final String DOWNLOAD_HOME_SHOW_STORAGE_INFO = "DownloadHomeShowStorageInfo";
     public static final String DOWNLOADS_FOREGROUND = "DownloadsForeground";
+    public static final String DOWNLOADS_LOCATION_CHANGE = "DownloadsLocationChange";
     // When enabled, fullscreen WebContents will be moved to a new Activity. Coming soon...
     public static final String FULLSCREEN_ACTIVITY = "FullscreenActivity";
     public static final String GRANT_NOTIFICATIONS_TO_DSE = "GrantNotificationsToDSE";
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java
index 648062e33..6c4844f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java
@@ -394,6 +394,7 @@
 
     @Override
     public boolean dispatchDragEvent(DragEvent e) {
+        if (mTabVisible == null) return false;
         ContentViewCore contentViewCore = mTabVisible.getContentViewCore();
         if (contentViewCore == null) return false;
 
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index b4952242..4b98ce4 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -7527,11 +7527,11 @@
       <message name="IDS_PROFILES_SYNC_SETTINGS_LINK" desc="The link text to the Chrome sync settings page in the avatar menu tutorial card.">
         Settings
       </message>
-      <message name="IDS_PROFILES_TURN_ON_SYNC_BUTTON" desc="Button in the profile user menu to turn on Sync.">
-        Turn on Sync
+      <message name="IDS_PROFILES_DICE_SIGNIN_BUTTON" desc="Button in the profile user menu to sign in and turn on Sync.">
+        Sign in
       </message>
-      <message name="IDS_PROFILES_TURN_ON_SYNC_PROMO" desc="Text describing the benefits of turning on Sync.">
-        Turn on Sync to get your bookmarks, history, passwords, and other settings on all your devices.
+      <message name="IDS_PROFILES_DICE_SIGNIN_PROMO" desc="Text describing the benefits of signing in and turning on Sync.">
+        Sign in for a personalized browsing experience, synced across your devices
       </message>
       <message name="IDS_PROFILES_ACCOUNT_REMOVAL_BUTTON" desc="Text of the ok button on the account removal view in the avatar menu bubble.">
         Remove account
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index c428c8a..8a3a457 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -3560,6 +3560,13 @@
      FEATURE_VALUE_TYPE(features::kDownloadsForeground)},
 #endif  // defined(OS_ANDROID)
 
+#if defined(OS_ANDROID)
+    {"enable-downloads-location-change",
+     flag_descriptions::kDownloadsLocationChangeName,
+     flag_descriptions::kDownloadsLocationChangeDescription, kOsAndroid,
+     FEATURE_VALUE_TYPE(features::kDownloadsLocationChange)},
+#endif  // defined(OS_ANDROID)
+
     {"enable-block-tab-unders", flag_descriptions::kBlockTabUndersName,
      flag_descriptions::kBlockTabUndersDescription, kOsAll,
      FEATURE_VALUE_TYPE(TabUnderNavigationThrottle::kBlockTabUnders)},
diff --git a/chrome/browser/android/chrome_feature_list.cc b/chrome/browser/android/chrome_feature_list.cc
index 9912616..0fa76ec1 100644
--- a/chrome/browser/android/chrome_feature_list.cc
+++ b/chrome/browser/android/chrome_feature_list.cc
@@ -44,6 +44,7 @@
     &features::kClearOldBrowsingData,
     &features::kCopylessPaste,
     &features::kDownloadsForeground,
+    &features::kDownloadsLocationChange,
     &features::kImportantSitesInCbd,
     &features::kMaterialDesignIncognitoNTP,
     &features::kServiceWorkerPaymentApps,
diff --git a/chrome/browser/android/compositor/scene_layer/contextual_search_scene_layer.cc b/chrome/browser/android/compositor/scene_layer/contextual_search_scene_layer.cc
index 2270f3ee..6db3112 100644
--- a/chrome/browser/android/compositor/scene_layer/contextual_search_scene_layer.cc
+++ b/chrome/browser/android/compositor/scene_layer/contextual_search_scene_layer.cc
@@ -13,11 +13,12 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_android.h"
 #include "content/public/browser/android/compositor.h"
+#include "content/public/browser/storage_partition.h"
 #include "content/public/browser/web_contents.h"
+#include "content/public/common/url_loader_factory.mojom.h"
 #include "jni/ContextualSearchSceneLayer_jni.h"
 #include "net/base/load_flags.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
-#include "net/url_request/url_request_context_getter.h"
 #include "ui/android/resources/resource_manager_impl.h"
 #include "ui/android/view_android.h"
 #include "ui/gfx/android/java_bitmap.h"
@@ -193,14 +194,16 @@
 
   GURL gurl(thumbnail_url_);
   Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile);
+  content::mojom::URLLoaderFactory* loader_factory =
+      content::BrowserContext::GetDefaultStoragePartition(profile)
+          ->GetURLLoaderFactoryForBrowserProcess();
   fetcher_ = base::MakeUnique<chrome::BitmapFetcher>(gurl, this,
                                                      NO_TRAFFIC_ANNOTATION_YET);
   fetcher_->Init(
-      profile->GetRequestContext(),
       std::string(),
-      net::URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
+      blink::kWebReferrerPolicyNoReferrerWhenDowngradeOriginWhenCrossOrigin,
       net::LOAD_NORMAL);
-  fetcher_->Start();
+  fetcher_->Start(loader_factory);
 }
 
 void ContextualSearchSceneLayer::OnFetchComplete(const GURL& url,
diff --git a/chrome/browser/bitmap_fetcher/bitmap_fetcher.cc b/chrome/browser/bitmap_fetcher/bitmap_fetcher.cc
index af9447a2..b3c6a4a 100644
--- a/chrome/browser/bitmap_fetcher/bitmap_fetcher.cc
+++ b/chrome/browser/bitmap_fetcher/bitmap_fetcher.cc
@@ -4,7 +4,9 @@
 
 #include "chrome/browser/bitmap_fetcher/bitmap_fetcher.h"
 
+#include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/storage_partition.h"
 #include "net/url_request/url_fetcher.h"
 #include "net/url_request/url_request_context_getter.h"
 #include "net/url_request/url_request_status.h"
@@ -20,40 +22,40 @@
 BitmapFetcher::~BitmapFetcher() {
 }
 
-void BitmapFetcher::Init(net::URLRequestContextGetter* request_context,
-                         const std::string& referrer,
-                         net::URLRequest::ReferrerPolicy referrer_policy,
+void BitmapFetcher::Init(const std::string& referrer,
+                         blink::WebReferrerPolicy referrer_policy,
                          int load_flags) {
-  if (url_fetcher_ != NULL)
+  if (simple_loader_ != NULL)
     return;
 
-  url_fetcher_ = net::URLFetcher::Create(url_, net::URLFetcher::GET, this,
-                                         traffic_annotation_);
-  url_fetcher_->SetRequestContext(request_context);
-  url_fetcher_->SetReferrer(referrer);
-  url_fetcher_->SetReferrerPolicy(referrer_policy);
-  url_fetcher_->SetLoadFlags(load_flags);
+  auto resource_request = std::make_unique<content::ResourceRequest>();
+  resource_request->url = url_;
+  resource_request->referrer = GURL(referrer);
+  resource_request->referrer_policy = referrer_policy;
+  resource_request->load_flags = load_flags;
+  simple_loader_ = content::SimpleURLLoader::Create(std::move(resource_request),
+                                                    traffic_annotation_);
 }
 
-void BitmapFetcher::Start() {
-  if (url_fetcher_)
-    url_fetcher_->Start();
+void BitmapFetcher::Start(content::mojom::URLLoaderFactory* loader_factory) {
+  if (simple_loader_) {
+    content::SimpleURLLoader::BodyAsStringCallback callback = base::BindOnce(
+        &BitmapFetcher::OnSimpleLoaderComplete, base::Unretained(this));
+    simple_loader_->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
+        loader_factory, std::move(callback));
+  }
 }
 
-// Methods inherited from URLFetcherDelegate.
-
-void BitmapFetcher::OnURLFetchComplete(const net::URLFetcher* source) {
-  if (source->GetStatus().status() != net::URLRequestStatus::SUCCESS) {
+void BitmapFetcher::OnSimpleLoaderComplete(
+    std::unique_ptr<std::string> response_body) {
+  if (!response_body) {
     ReportFailure();
     return;
   }
 
-  std::string image_data;
-  source->GetResponseAsString(&image_data);
-
   // Call start to begin decoding.  The ImageDecoder will call OnImageDecoded
   // with the data when it is done.
-  ImageDecoder::Start(this, image_data);
+  ImageDecoder::Start(this, *response_body);
 }
 
 // Methods inherited from ImageDecoder::ImageRequest.
diff --git a/chrome/browser/bitmap_fetcher/bitmap_fetcher.h b/chrome/browser/bitmap_fetcher/bitmap_fetcher.h
index a34ef5ab..3e28b91 100644
--- a/chrome/browser/bitmap_fetcher/bitmap_fetcher.h
+++ b/chrome/browser/bitmap_fetcher/bitmap_fetcher.h
@@ -7,27 +7,23 @@
 
 #include <memory>
 
+#include "base/callback_forward.h"
 #include "base/macros.h"
 #include "chrome/browser/bitmap_fetcher/bitmap_fetcher_delegate.h"
 #include "chrome/browser/image_decoder.h"
+#include "content/public/common/resource_request.h"
+#include "content/public/common/simple_url_loader.h"
+#include "content/public/common/url_loader_factory.mojom.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
-#include "net/url_request/url_fetcher_delegate.h"
-#include "net/url_request/url_request.h"
 #include "url/gurl.h"
 
 class SkBitmap;
 
-namespace net {
-class URLFetcher;
-class URLRequestContextGetter;
-}  // namespace net
-
 namespace chrome {
 
 // Asynchrounously fetches an image from the given URL and returns the
 // decoded Bitmap to the provided BitmapFetcherDelegate.
-class BitmapFetcher : public net::URLFetcherDelegate,
-                      public ImageDecoder::ImageRequest {
+class BitmapFetcher : public ImageDecoder::ImageRequest {
  public:
   BitmapFetcher(const GURL& url,
                 BitmapFetcherDelegate* delegate,
@@ -35,7 +31,6 @@
   ~BitmapFetcher() override;
 
   const GURL& url() const { return url_; }
-  net::URLFetcher* url_fetcher() { return url_fetcher_.get(); }
 
   // Initializes internal fetcher.  After this function returns url_fetcher()
   // can be accessed to configure it further (eg. add user data to request).
@@ -43,22 +38,15 @@
   // Values for |load_flags| are defined in net/base/load_flags.h.  In general,
   // |net::LOAD_NORMAL| is appropriate.  Init may be called more than once in
   // some cases.  If so, subsequent starts will be ignored.
-  void Init(net::URLRequestContextGetter* request_context,
-            const std::string& referrer,
-            net::URLRequest::ReferrerPolicy referrer_policy,
+  void Init(const std::string& referrer,
+            blink::WebReferrerPolicy referrer_policy,
             int load_flags);
 
   // Start fetching the URL with the fetcher. The delegate is notified
   // asynchronously when done.  Start may be called more than once in some
   // cases.  If so, subsequent starts will be ignored since the operation is
   // already in progress.
-  void Start();
-
-  // Methods inherited from URLFetcherDelegate
-
-  // This will be called when the URL has been fetched, successfully or not.
-  // Use accessor methods on |source| to get the results.
-  void OnURLFetchComplete(const net::URLFetcher* source) override;
+  void Start(content::mojom::URLLoaderFactory* loader_factory);
 
   // Methods inherited from ImageDecoder::ImageRequest
 
@@ -71,10 +59,13 @@
   void OnDecodeImageFailed() override;
 
  private:
+  void OnSimpleLoaderComplete(std::unique_ptr<std::string> response_body);
+
   // Alerts the delegate that a failure occurred.
   void ReportFailure();
 
-  std::unique_ptr<net::URLFetcher> url_fetcher_;
+  std::unique_ptr<content::SimpleURLLoader> simple_loader_;
+
   const GURL url_;
   BitmapFetcherDelegate* const delegate_;
   const net::NetworkTrafficAnnotationTag traffic_annotation_;
diff --git a/chrome/browser/bitmap_fetcher/bitmap_fetcher_browsertest.cc b/chrome/browser/bitmap_fetcher/bitmap_fetcher_browsertest.cc
index bb90df207..c9e4144 100644
--- a/chrome/browser/bitmap_fetcher/bitmap_fetcher_browsertest.cc
+++ b/chrome/browser/bitmap_fetcher/bitmap_fetcher_browsertest.cc
@@ -10,12 +10,14 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/test/base/in_process_browser_test.h"
+#include "content/public/browser/storage_partition.h"
 #include "content/public/test/test_utils.h"
 #include "net/base/load_flags.h"
 #include "net/http/http_status_code.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "net/test/embedded_test_server/http_request.h"
+#include "net/test/embedded_test_server/http_response.h"
 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
-#include "net/url_request/test_url_fetcher_factory.h"
-#include "net/url_request/url_fetcher.h"
 #include "net/url_request/url_request_status.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/skia/include/core/SkBitmap.h"
@@ -25,6 +27,13 @@
 
 const bool kAsyncCall = true;
 const bool kSyncCall = false;
+const char kStartTestURL[] = "/this-should-work";
+const char kOnImageDecodedTestURL[] = "/this-should-work-as-well";
+const char kOnURLFetchFailureTestURL[] = "/this-should-be-fetch-failure";
+
+using net::test_server::BasicHttpResponse;
+using net::test_server::HttpRequest;
+using net::test_server::HttpResponse;
 
 namespace chrome {
 
@@ -77,15 +86,53 @@
 
 class BitmapFetcherBrowserTest : public InProcessBrowserTest {
  public:
-  void SetUp() override {
-    url_fetcher_factory_.reset(
-        new net::FakeURLFetcherFactory(&url_fetcher_impl_factory_));
-    InProcessBrowserTest::SetUp();
+  // InProcessBrowserTest overrides:
+  void SetUpOnMainThread() override {
+    InProcessBrowserTest::SetUpOnMainThread();
+
+    // Set up the test server.
+    embedded_test_server()->RegisterRequestHandler(base::BindRepeating(
+        &BitmapFetcherBrowserTest::HandleRequest, base::Unretained(this)));
+    ASSERT_TRUE(embedded_test_server()->Start());
+  }
+
+  void TearDownOnMainThread() override {
+    // Tear down the test server.
+    EXPECT_TRUE(embedded_test_server()->ShutdownAndWaitUntilComplete());
+    InProcessBrowserTest::TearDownOnMainThread();
   }
 
  protected:
-  net::URLFetcherImplFactory url_fetcher_impl_factory_;
-  std::unique_ptr<net::FakeURLFetcherFactory> url_fetcher_factory_;
+  SkBitmap test_bitmap() const {
+    // Return some realistic looking bitmap data
+    SkBitmap image;
+
+    // Put a real bitmap into "image".  2x2 bitmap of green 32 bit pixels.
+    image.allocN32Pixels(2, 2);
+    image.eraseColor(SK_ColorGREEN);
+    return image;
+  }
+
+ private:
+  std::unique_ptr<HttpResponse> HandleRequest(const HttpRequest& request) {
+    std::unique_ptr<BasicHttpResponse> response(new BasicHttpResponse);
+    if (request.relative_url == kStartTestURL) {
+      // Encode the bits as a PNG.
+      std::vector<unsigned char> compressed;
+      gfx::PNGCodec::EncodeBGRASkBitmap(test_bitmap(), true, &compressed);
+      // Copy the bits into a string and return them through the embedded
+      // test server
+      std::string image_string(compressed.begin(), compressed.end());
+      response->set_code(net::HTTP_OK);
+      response->set_content(image_string);
+    } else if (request.relative_url == kOnImageDecodedTestURL) {
+      response->set_code(net::HTTP_INTERNAL_SERVER_ERROR);
+    } else if (request.relative_url == kOnURLFetchFailureTestURL) {
+      response->set_code(net::HTTP_OK);
+      response->set_content(std::string("Not a real bitmap"));
+    }
+    return std::move(response);
+  }
 };
 
 // WARNING:  These tests work with --single_process, but not
@@ -93,38 +140,22 @@
 // for us by the test process if --single-process is used.
 
 IN_PROC_BROWSER_TEST_F(BitmapFetcherBrowserTest, StartTest) {
-  GURL url("http://example.com/this-should-work");
-
-  // Put some realistic looking bitmap data into the url_fetcher.
-  SkBitmap image;
-
-  // Put a real bitmap into "image".  2x2 bitmap of green 32 bit pixels.
-  image.allocN32Pixels(2, 2);
-  image.eraseColor(SK_ColorGREEN);
-
-  // Encode the bits as a PNG.
-  std::vector<unsigned char> compressed;
-  ASSERT_TRUE(gfx::PNGCodec::EncodeBGRASkBitmap(image, true, &compressed));
-
-  // Copy the bits into the string, and put them into the FakeURLFetcher.
-  std::string image_string(compressed.begin(), compressed.end());
+  GURL url = embedded_test_server()->GetURL(kStartTestURL);
 
   // Set up a delegate to wait for the callback.
   BitmapFetcherTestDelegate delegate(kAsyncCall);
 
   BitmapFetcher fetcher(url, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS);
 
-  url_fetcher_factory_->SetFakeResponse(
-      url, image_string, net::HTTP_OK, net::URLRequestStatus::SUCCESS);
-
   // We expect that the image decoder will get called and return
   // an image in a callback to OnImageDecoded().
   fetcher.Init(
-      browser()->profile()->GetRequestContext(),
       std::string(),
-      net::URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
+      blink::kWebReferrerPolicyNoReferrerWhenDowngradeOriginWhenCrossOrigin,
       net::LOAD_NORMAL);
-  fetcher.Start();
+  fetcher.Start(
+      content::BrowserContext::GetDefaultStoragePartition(browser()->profile())
+          ->GetURLLoaderFactoryForBrowserProcess());
 
   // Blocks until test delegate is notified via a callback.
   delegate.Wait();
@@ -133,11 +164,11 @@
 
   // Make sure we get back the bitmap we expect.
   const SkBitmap& found_image = delegate.bitmap();
-  EXPECT_TRUE(gfx::BitmapsAreEqual(image, found_image));
+  EXPECT_TRUE(gfx::BitmapsAreEqual(test_bitmap(), found_image));
 }
 
 IN_PROC_BROWSER_TEST_F(BitmapFetcherBrowserTest, OnImageDecodedTest) {
-  GURL url("http://example.com/this-should-work-as-well");
+  GURL url = embedded_test_server()->GetURL(kOnImageDecodedTestURL);
   SkBitmap image;
 
   // Put a real bitmap into "image".  2x2 bitmap of green 16 bit pixels.
@@ -158,7 +189,7 @@
 }
 
 IN_PROC_BROWSER_TEST_F(BitmapFetcherBrowserTest, OnURLFetchFailureTest) {
-  GURL url("http://example.com/this-should-be-fetch-failure");
+  GURL url = embedded_test_server()->GetURL(kOnURLFetchFailureTestURL);
 
   // We intentionally put no data into the bitmap to simulate a failure.
 
@@ -167,17 +198,13 @@
 
   BitmapFetcher fetcher(url, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS);
 
-  url_fetcher_factory_->SetFakeResponse(url,
-                                        std::string(),
-                                        net::HTTP_INTERNAL_SERVER_ERROR,
-                                        net::URLRequestStatus::FAILED);
-
   fetcher.Init(
-      browser()->profile()->GetRequestContext(),
       std::string(),
-      net::URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
+      blink::kWebReferrerPolicyNoReferrerWhenDowngradeOriginWhenCrossOrigin,
       net::LOAD_NORMAL);
-  fetcher.Start();
+  fetcher.Start(
+      content::BrowserContext::GetDefaultStoragePartition(browser()->profile())
+          ->GetURLLoaderFactoryForBrowserProcess());
 
   // Blocks until test delegate is notified via a callback.
   delegate.Wait();
@@ -189,17 +216,14 @@
   GURL url("http://example.com/this-should-be-a-decode-failure");
   BitmapFetcherTestDelegate delegate(kAsyncCall);
   BitmapFetcher fetcher(url, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS);
-  url_fetcher_factory_->SetFakeResponse(url,
-                                        std::string("Not a real bitmap"),
-                                        net::HTTP_OK,
-                                        net::URLRequestStatus::SUCCESS);
 
   fetcher.Init(
-      browser()->profile()->GetRequestContext(),
       std::string(),
-      net::URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
+      blink::kWebReferrerPolicyNoReferrerWhenDowngradeOriginWhenCrossOrigin,
       net::LOAD_NORMAL);
-  fetcher.Start();
+  fetcher.Start(
+      content::BrowserContext::GetDefaultStoragePartition(browser()->profile())
+          ->GetURLLoaderFactoryForBrowserProcess());
 
   // Blocks until test delegate is notified via a callback.
   delegate.Wait();
diff --git a/chrome/browser/bitmap_fetcher/bitmap_fetcher_service.cc b/chrome/browser/bitmap_fetcher/bitmap_fetcher_service.cc
index 84aece2..1052408 100644
--- a/chrome/browser/bitmap_fetcher/bitmap_fetcher_service.cc
+++ b/chrome/browser/bitmap_fetcher/bitmap_fetcher_service.cc
@@ -132,12 +132,12 @@
       new chrome::BitmapFetcher(url, this, traffic_annotation));
 
   new_fetcher->Init(
-      content::BrowserContext::GetDefaultStoragePartition(context_)->
-          GetURLRequestContext(),
       std::string(),
-      net::URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
+      blink::kWebReferrerPolicyNoReferrerWhenDowngradeOriginWhenCrossOrigin,
       net::LOAD_NORMAL);
-  new_fetcher->Start();
+  new_fetcher->Start(
+      content::BrowserContext::GetDefaultStoragePartition(context_)
+          ->GetURLLoaderFactoryForBrowserProcess());
   return new_fetcher;
 }
 
diff --git a/chrome/browser/chromeos/app_mode/kiosk_app_data.cc b/chrome/browser/chromeos/app_mode/kiosk_app_data.cc
index a1019cc..7eca0f1 100644
--- a/chrome/browser/chromeos/app_mode/kiosk_app_data.cc
+++ b/chrome/browser/chromeos/app_mode/kiosk_app_data.cc
@@ -20,10 +20,12 @@
 #include "chrome/browser/extensions/extension_util.h"
 #include "chrome/browser/extensions/webstore_data_fetcher.h"
 #include "chrome/browser/extensions/webstore_install_helper.h"
+#include "chrome/browser/net/system_network_context_manager.h"
 #include "chrome/browser/profiles/profile.h"
 #include "components/prefs/pref_service.h"
 #include "components/prefs/scoped_user_pref_update.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/common/url_loader_factory.mojom.h"
 #include "extensions/browser/extension_system.h"
 #include "extensions/browser/image_loader.h"
 #include "extensions/browser/sandboxed_unpacker.h"
@@ -192,14 +194,10 @@
   void Start(const std::string& app_id,
              const std::string& manifest,
              const GURL& icon_url,
-             net::URLRequestContextGetter* context_getter) {
+             content::mojom::URLLoaderFactory* loader_factory) {
     scoped_refptr<extensions::WebstoreInstallHelper> webstore_helper =
-        new extensions::WebstoreInstallHelper(this,
-                                              app_id,
-                                              manifest,
-                                              icon_url,
-                                              context_getter);
-    webstore_helper->Start();
+        new extensions::WebstoreInstallHelper(this, app_id, manifest, icon_url);
+    webstore_helper->Start(loader_factory);
   }
 
  private:
@@ -369,6 +367,11 @@
   return g_browser_process->system_request_context();
 }
 
+content::mojom::URLLoaderFactory* KioskAppData::GetURLLoaderFactory() {
+  return g_browser_process->system_network_context_manager()
+      ->GetURLLoaderFactory();
+}
+
 bool KioskAppData::LoadFromCache() {
   PrefService* local_state = g_browser_process->local_state();
   const base::DictionaryValue* dict =
@@ -492,7 +495,7 @@
 
   // WebstoreDataParser deletes itself when done.
   (new WebstoreDataParser(weak_factory_.GetWeakPtr()))
-      ->Start(app_id(), manifest, icon_url, GetRequestContextGetter());
+      ->Start(app_id(), manifest, icon_url, GetURLLoaderFactory());
 }
 
 void KioskAppData::OnWebstoreResponseParseFailure(const std::string& error) {
diff --git a/chrome/browser/chromeos/app_mode/kiosk_app_data.h b/chrome/browser/chromeos/app_mode/kiosk_app_data.h
index 2baa6a7..359152f 100644
--- a/chrome/browser/chromeos/app_mode/kiosk_app_data.h
+++ b/chrome/browser/chromeos/app_mode/kiosk_app_data.h
@@ -27,6 +27,12 @@
 class Image;
 }
 
+namespace content {
+namespace mojom {
+class URLLoaderFactory;
+}
+}  // namespace content
+
 namespace net {
 class URLRequestContextGetter;
 }
@@ -99,6 +105,9 @@
   // Returns URLRequestContextGetter to use for fetching web store data.
   net::URLRequestContextGetter* GetRequestContextGetter();
 
+  // Returns URLLoaderFactory to use for fetching web store data.
+  content::mojom::URLLoaderFactory* GetURLLoaderFactory();
+
   // Loads the locally cached data. Return false if there is none.
   bool LoadFromCache();
 
diff --git a/chrome/browser/extensions/api/dashboard_private/dashboard_private_api.cc b/chrome/browser/extensions/api/dashboard_private/dashboard_private_api.cc
index 97266d7..6a13f81 100644
--- a/chrome/browser/extensions/api/dashboard_private/dashboard_private_api.cc
+++ b/chrome/browser/extensions/api/dashboard_private/dashboard_private_api.cc
@@ -74,20 +74,19 @@
     }
   }
 
-  net::URLRequestContextGetter* context_getter = nullptr;
+  content::mojom::URLLoaderFactory* loader_factory = nullptr;
   if (!icon_url.is_empty()) {
-    context_getter =
-        content::BrowserContext::GetDefaultStoragePartition(browser_context())->
-            GetURLRequestContext();
+    loader_factory =
+        content::BrowserContext::GetDefaultStoragePartition(browser_context())
+            ->GetURLLoaderFactoryForBrowserProcess();
   }
 
   scoped_refptr<WebstoreInstallHelper> helper = new WebstoreInstallHelper(
-      this, params_->details.id, params_->details.manifest, icon_url,
-      context_getter);
+      this, params_->details.id, params_->details.manifest, icon_url);
 
   // The helper will call us back via OnWebstoreParseSuccess or
   // OnWebstoreParseFailure.
-  helper->Start();
+  helper->Start(loader_factory);
 
   // Matched with a Release in OnWebstoreParseSuccess/OnWebstoreParseFailure.
   AddRef();
diff --git a/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc b/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc
index b6792c0..b04347d 100644
--- a/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc
+++ b/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc
@@ -218,18 +218,19 @@
   ActiveInstallData install_data(details().id);
   scoped_active_install_.reset(new ScopedActiveInstall(tracker, install_data));
 
-  net::URLRequestContextGetter* context_getter = nullptr;
+  content::mojom::URLLoaderFactory* loader_factory = nullptr;
   if (!icon_url.is_empty()) {
-    context_getter = content::BrowserContext::GetDefaultStoragePartition(
-        browser_context())->GetURLRequestContext();
+    loader_factory =
+        content::BrowserContext::GetDefaultStoragePartition(browser_context())
+            ->GetURLLoaderFactoryForBrowserProcess();
   }
 
   scoped_refptr<WebstoreInstallHelper> helper = new WebstoreInstallHelper(
-      this, details().id, details().manifest, icon_url, context_getter);
+      this, details().id, details().manifest, icon_url);
 
   // The helper will call us back via OnWebstoreParseSuccess or
   // OnWebstoreParseFailure.
-  helper->Start();
+  helper->Start(loader_factory);
 
   // Matched with a Release in OnWebstoreParseSuccess/OnWebstoreParseFailure.
   AddRef();
diff --git a/chrome/browser/extensions/webstore_install_helper.cc b/chrome/browser/extensions/webstore_install_helper.cc
index 8689510..b520ee4 100644
--- a/chrome/browser/extensions/webstore_install_helper.cc
+++ b/chrome/browser/extensions/webstore_install_helper.cc
@@ -24,25 +24,22 @@
 
 namespace extensions {
 
-WebstoreInstallHelper::WebstoreInstallHelper(
-    Delegate* delegate,
-    const std::string& id,
-    const std::string& manifest,
-    const GURL& icon_url,
-    net::URLRequestContextGetter* context_getter)
+WebstoreInstallHelper::WebstoreInstallHelper(Delegate* delegate,
+                                             const std::string& id,
+                                             const std::string& manifest,
+                                             const GURL& icon_url)
     : delegate_(delegate),
       id_(id),
       manifest_(manifest),
       icon_url_(icon_url),
-      context_getter_(context_getter),
       icon_decode_complete_(false),
       manifest_parse_complete_(false),
-      parse_error_(Delegate::UNKNOWN_ERROR) {
-}
+      parse_error_(Delegate::UNKNOWN_ERROR) {}
 
 WebstoreInstallHelper::~WebstoreInstallHelper() {}
 
-void WebstoreInstallHelper::Start() {
+void WebstoreInstallHelper::Start(
+    content::mojom::URLLoaderFactory* loader_factory) {
   CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
   data_decoder::SafeJsonParser::Parse(
@@ -87,10 +84,10 @@
     icon_fetcher_.reset(
         new chrome::BitmapFetcher(icon_url_, this, traffic_annotation));
     icon_fetcher_->Init(
-        context_getter_, std::string(),
-        net::URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
+        std::string(),
+        blink::kWebReferrerPolicyNoReferrerWhenDowngradeOriginWhenCrossOrigin,
         net::LOAD_DO_NOT_SAVE_COOKIES | net::LOAD_DO_NOT_SEND_COOKIES);
-    icon_fetcher_->Start();
+    icon_fetcher_->Start(loader_factory);
   }
 }
 
diff --git a/chrome/browser/extensions/webstore_install_helper.h b/chrome/browser/extensions/webstore_install_helper.h
index c53ea812d..5c8342d 100644
--- a/chrome/browser/extensions/webstore_install_helper.h
+++ b/chrome/browser/extensions/webstore_install_helper.h
@@ -22,9 +22,11 @@
 class BitmapFetcher;
 }
 
-namespace net {
-class URLRequestContextGetter;
+namespace content {
+namespace mojom {
+class URLLoaderFactory;
 }
+}  // namespace content
 
 namespace safe_json {
 class SafeJsonParser;
@@ -69,9 +71,8 @@
   WebstoreInstallHelper(Delegate* delegate,
                         const std::string& id,
                         const std::string& manifest,
-                        const GURL& icon_url,
-                        net::URLRequestContextGetter* context_getter);
-  void Start();
+                        const GURL& icon_url);
+  void Start(content::mojom::URLLoaderFactory* loader_factory);
 
  private:
   friend class base::RefCounted<WebstoreInstallHelper>;
@@ -99,7 +100,6 @@
   // If |icon_url_| is non-empty, it needs to be fetched and decoded into an
   // SkBitmap.
   GURL icon_url_;
-  net::URLRequestContextGetter* context_getter_; // Only usable on UI thread.
   std::unique_ptr<chrome::BitmapFetcher> icon_fetcher_;
 
   // Flags for whether we're done doing icon decoding and manifest parsing.
diff --git a/chrome/browser/extensions/webstore_standalone_installer.cc b/chrome/browser/extensions/webstore_standalone_installer.cc
index be9e4ad..cc15d80 100644
--- a/chrome/browser/extensions/webstore_standalone_installer.cc
+++ b/chrome/browser/extensions/webstore_standalone_installer.cc
@@ -16,6 +16,7 @@
 #include "chrome/browser/extensions/webstore_data_fetcher.h"
 #include "chrome/browser/profiles/profile.h"
 #include "components/crx_file/id_util.h"
+#include "content/public/browser/storage_partition.h"
 #include "content/public/browser/web_contents.h"
 #include "extensions/browser/extension_prefs.h"
 #include "extensions/browser/extension_registry.h"
@@ -309,14 +310,11 @@
   webstore_data_ = std::move(webstore_data);
 
   scoped_refptr<WebstoreInstallHelper> helper =
-      new WebstoreInstallHelper(this,
-                                id_,
-                                manifest,
-                                icon_url,
-                                profile_->GetRequestContext());
+      new WebstoreInstallHelper(this, id_, manifest, icon_url);
   // The helper will call us back via OnWebstoreParseSuccess() or
   // OnWebstoreParseFailure().
-  helper->Start();
+  helper->Start(content::BrowserContext::GetDefaultStoragePartition(profile_)
+                    ->GetURLLoaderFactoryForBrowserProcess());
 }
 
 void WebstoreStandaloneInstaller::OnWebstoreResponseParseFailure(
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 86dd5e5..a7fc91c 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -1307,7 +1307,7 @@
 
 const char kSitePerProcessName[] = "Strict site isolation";
 const char kSitePerProcessDescription[] =
-    "Highly experimental security mode that ensures each renderer process "
+    "Experimental security mode that ensures each renderer process "
     "contains pages from at most one site. In this mode, out-of-process "
     "iframes will be used whenever an iframe is cross-site.";
 
@@ -1767,6 +1767,10 @@
 const char kDownloadsForegroundDescription[] =
     "Enable downloads as a foreground service for all versions of Android.";
 
+const char kDownloadsLocationChangeName[] = "Enable downloads location change";
+const char kDownloadsLocationChangeDescription[] =
+    "Enable changing default downloads storage location on Android.";
+
 const char kEnableAndroidPayIntegrationV1Name[] = "Enable Android Pay v1";
 const char kEnableAndroidPayIntegrationV1Description[] =
     "Enable integration with Android Pay using the first version of the API";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 31b93f4..68ef234e 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -1091,6 +1091,9 @@
 extern const char kDownloadsForegroundName[];
 extern const char kDownloadsForegroundDescription[];
 
+extern const char kDownloadsLocationChangeName[];
+extern const char kDownloadsLocationChangeDescription[];
+
 extern const char kEnableAndroidPayIntegrationV1Name[];
 extern const char kEnableAndroidPayIntegrationV1Description[];
 
diff --git a/chrome/browser/password_manager/account_chooser_dialog_android.cc b/chrome/browser/password_manager/account_chooser_dialog_android.cc
index 837e5510..12d67b4 100644
--- a/chrome/browser/password_manager/account_chooser_dialog_android.cc
+++ b/chrome/browser/password_manager/account_chooser_dialog_android.cc
@@ -23,6 +23,7 @@
 #include "components/password_manager/core/browser/password_manager_metrics_util.h"
 #include "components/password_manager/core/browser/password_ui_utils.h"
 #include "components/password_manager/core/common/credential_manager_types.h"
+#include "content/public/browser/storage_partition.h"
 #include "jni/AccountChooserDialog_jni.h"
 #include "ui/android/window_android.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -91,13 +92,13 @@
 void FetchAvatar(const base::android::ScopedJavaGlobalRef<jobject>& java_dialog,
                  const autofill::PasswordForm* password_form,
                  int index,
-                 net::URLRequestContextGetter* request_context) {
+                 content::mojom::URLLoaderFactory* loader_factory) {
   if (!password_form->icon_url.is_valid())
     return;
   // Fetcher deletes itself once fetching is finished.
   auto* fetcher =
       new AvatarFetcherAndroid(password_form->icon_url, index, java_dialog);
-  fetcher->Start(request_context);
+  fetcher->Start(loader_factory);
 }
 
 };  // namespace
@@ -148,12 +149,13 @@
       title_link_range.start(), title_link_range.end(),
       base::android::ConvertUTF8ToJavaString(env, origin),
       base::android::ConvertUTF16ToJavaString(env, signin_button)));
-  net::URLRequestContextGetter* request_context =
-      Profile::FromBrowserContext(web_contents_->GetBrowserContext())
-          ->GetRequestContext();
+  content::mojom::URLLoaderFactory* loader_factory =
+      content::BrowserContext::GetDefaultStoragePartition(
+          Profile::FromBrowserContext(web_contents_->GetBrowserContext()))
+          ->GetURLLoaderFactoryForBrowserProcess();
   int avatar_index = 0;
   for (const auto& form : local_credentials_forms())
-    FetchAvatar(dialog_jobject_, form.get(), avatar_index++, request_context);
+    FetchAvatar(dialog_jobject_, form.get(), avatar_index++, loader_factory);
 }
 
 void AccountChooserDialogAndroid::OnCredentialClicked(
diff --git a/chrome/browser/profiles/profile_avatar_downloader.cc b/chrome/browser/profiles/profile_avatar_downloader.cc
index a2fc1d0..9b9b50d7 100644
--- a/chrome/browser/profiles/profile_avatar_downloader.cc
+++ b/chrome/browser/profiles/profile_avatar_downloader.cc
@@ -9,6 +9,7 @@
 #include "base/callback.h"
 #include "base/files/file_path.h"
 #include "chrome/browser/browser_process.h"
+#include "chrome/browser/net/system_network_context_manager.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_avatar_icon_util.h"
 #include "net/base/load_flags.h"
@@ -57,16 +58,19 @@
 }
 
 void ProfileAvatarDownloader::Start() {
-  // In unit tests, the browser process can return a NULL request context.
-  net::URLRequestContextGetter* request_context =
-      g_browser_process->system_request_context();
-  if (request_context) {
+  SystemNetworkContextManager* system_network_context_manager =
+      g_browser_process->system_network_context_manager();
+  // In unit tests, the browser process can return a NULL context manager
+  if (!system_network_context_manager)
+    return;
+  content::mojom::URLLoaderFactory* loader_factory =
+      system_network_context_manager->GetURLLoaderFactory();
+  if (loader_factory) {
     fetcher_->Init(
-        request_context,
         std::string(),
-        net::URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
+        blink::kWebReferrerPolicyNoReferrerWhenDowngradeOriginWhenCrossOrigin,
         net::LOAD_NORMAL);
-    fetcher_->Start();
+    fetcher_->Start(loader_factory);
   }
 }
 
diff --git a/chrome/browser/resources/md_extensions/error_page.html b/chrome/browser/resources/md_extensions/error_page.html
index d3fbc22..e26aab3 100644
--- a/chrome/browser/resources/md_extensions/error_page.html
+++ b/chrome/browser/resources/md_extensions/error_page.html
@@ -32,6 +32,7 @@
       iron-icon {
         --iron-icon-fill-color: var(--paper-grey-500);
         @apply(--cr-icon-height-width);
+        flex-shrink: 0;
       }
 
       iron-icon[icon=warning] {
@@ -92,6 +93,7 @@
       .error-message {
         -webkit-margin-start: 10px;
         flex-grow: 1;
+        word-break: break-all;
       }
 
       #devtools-controls {
diff --git a/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc b/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc
index 29283269..4f8180fc3 100644
--- a/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc
@@ -33,6 +33,7 @@
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/synchronization/lock.h"
 #include "base/test/thread_test_helper.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
@@ -103,6 +104,8 @@
 using ::testing::Mock;
 using ::testing::StrictMock;
 
+#define ENABLE_FLAKY_PVER3_TESTS 1
+
 namespace safe_browsing {
 
 namespace {
@@ -268,6 +271,7 @@
 
   // Deletes the current database and creates a new one.
   bool ResetDatabase() override {
+    base::AutoLock locker(lock_);
     badurls_.clear();
     urls_by_hash_.clear();
     return true;
@@ -279,6 +283,7 @@
   bool ContainsBrowseUrl(const GURL& url,
                          std::vector<SBPrefix>* prefix_hits,
                          std::vector<SBFullHashResult>* cache_hits) override {
+    base::AutoLock locker(lock_);
     cache_hits->clear();
     return ContainsUrl(MALWARE, PHISH, std::vector<GURL>(1, url), prefix_hits);
   }
@@ -287,6 +292,7 @@
       const std::vector<SBFullHash>& full_hashes,
       std::vector<SBPrefix>* prefix_hits,
       std::vector<SBFullHashResult>* cache_hits) override {
+    base::AutoLock locker(lock_);
     cache_hits->clear();
     return ContainsUrl(MALWARE, PHISH, UrlsForHashes(full_hashes), prefix_hits);
   }
@@ -295,6 +301,7 @@
       const GURL& url,
       std::vector<SBPrefix>* prefix_hits,
       std::vector<SBFullHashResult>* cache_hits) override {
+    base::AutoLock locker(lock_);
     cache_hits->clear();
     return ContainsUrl(UNWANTEDURL, UNWANTEDURL, std::vector<GURL>(1, url),
                        prefix_hits);
@@ -304,6 +311,7 @@
       const std::vector<SBFullHash>& full_hashes,
       std::vector<SBPrefix>* prefix_hits,
       std::vector<SBFullHashResult>* cache_hits) override {
+    base::AutoLock locker(lock_);
     cache_hits->clear();
     return ContainsUrl(UNWANTEDURL, UNWANTEDURL, UrlsForHashes(full_hashes),
                        prefix_hits);
@@ -312,6 +320,7 @@
   bool ContainsDownloadUrlPrefixes(
       const std::vector<SBPrefix>& prefixes,
       std::vector<SBPrefix>* prefix_hits) override {
+    base::AutoLock locker(lock_);
     bool found = ContainsUrlPrefixes(BINURL, BINURL, prefixes, prefix_hits);
     if (!found)
       return false;
@@ -333,6 +342,7 @@
   bool ContainsResourceUrlPrefixes(
       const std::vector<SBPrefix>& prefixes,
       std::vector<SBPrefix>* prefix_hits) override {
+    base::AutoLock locker(lock_);
     prefix_hits->clear();
     return ContainsUrlPrefixes(RESOURCEBLACKLIST, RESOURCEBLACKLIST, prefixes,
                                prefix_hits);
@@ -362,6 +372,7 @@
   void AddUrl(const GURL& url,
               const SBFullHashResult& full_hash,
               const std::vector<SBPrefix>& prefix_hits) {
+    base::AutoLock locker(lock_);
     Hits* hits_for_url = &badurls_[url.spec()];
     hits_for_url->list_ids.push_back(full_hash.list_id);
     hits_for_url->prefix_hits.insert(hits_for_url->prefix_hits.end(),
@@ -382,6 +393,7 @@
                    int list_id1,
                    const std::vector<GURL>& urls,
                    std::vector<SBPrefix>* prefix_hits) {
+    lock_.AssertAcquired();
     bool hit = false;
     for (const GURL& url : urls) {
       const auto badurls_it = badurls_.find(url.spec());
@@ -401,6 +413,7 @@
   }
 
   std::vector<GURL> UrlsForHashes(const std::vector<SBFullHash>& full_hashes) {
+    lock_.AssertAcquired();
     std::vector<GURL> urls;
     for (auto hash : full_hashes) {
       auto url_it = urls_by_hash_.find(SBFullHashToString(hash));
@@ -415,6 +428,7 @@
                            int list_id1,
                            const std::vector<SBPrefix>& prefixes,
                            std::vector<SBPrefix>* prefix_hits) {
+    lock_.AssertAcquired();
     bool hit = false;
     for (const SBPrefix& prefix : prefixes) {
       for (const std::pair<int, SBPrefix>& entry : bad_prefixes_) {
@@ -428,6 +442,8 @@
     return hit;
   }
 
+  // Protects the members below.
+  base::Lock lock_;
   std::map<std::string, Hits> badurls_;
   std::set<std::pair<int, SBPrefix>> bad_prefixes_;
   std::map<std::string, GURL> urls_by_hash_;
@@ -449,14 +465,46 @@
       bool enable_extension_blacklist,
       bool enable_ip_blacklist,
       bool enabled_unwanted_software_list) override {
+    base::AutoLock locker(lock_);
+
     db_ = new TestSafeBrowsingDatabase();
+
+    if (!quit_closure_.is_null()) {
+      quit_closure_.Run();
+      quit_closure_ = base::Closure();
+    }
+
     return base::WrapUnique(db_);
   }
-  TestSafeBrowsingDatabase* GetDb() { return db_; }
+
+  TestSafeBrowsingDatabase* GetDb() {
+    base::RunLoop loop;
+    bool should_wait = false;
+    {
+      base::AutoLock locker(lock_);
+
+      if (db_)
+        return db_;
+
+      quit_closure_ = loop.QuitClosure();
+      should_wait = true;
+    }
+
+    if (should_wait)
+      loop.Run();
+
+   {
+     base::AutoLock locker(lock_);
+     return db_;
+   }
+  }
 
  private:
+  base::Lock lock_;
+
   // Owned by the SafebrowsingService.
   TestSafeBrowsingDatabase* db_;
+  base::Closure quit_closure_;
 };
 
 // A TestProtocolManager that could return fixed responses from
@@ -481,6 +529,8 @@
                    SafeBrowsingProtocolManager::FullHashCallback callback,
                    bool is_download,
                    ExtendedReportingLevel reporting_level) override {
+    base::AutoLock locker(lock_);
+
     BrowserThread::PostDelayedTask(
         BrowserThread::IO, FROM_HERE,
         base::BindOnce(InvokeFullHashCallback, callback, full_hashes_), delay_);
@@ -488,6 +538,7 @@
 
   // Prepare the GetFullHash results for the next request.
   void AddGetFullHashResponse(const SBFullHashResult& full_hash_result) {
+    base::AutoLock locker(lock_);
     full_hashes_.push_back(full_hash_result);
   }
 
@@ -498,6 +549,8 @@
   static int delete_count() { return delete_count_; }
 
  private:
+  // Protects |full_hashes_|.
+  base::Lock lock_;
   std::vector<SBFullHashResult> full_hashes_;
   base::TimeDelta delay_;
   static int create_count_;
@@ -519,15 +572,46 @@
       SafeBrowsingProtocolManagerDelegate* delegate,
       net::URLRequestContextGetter* request_context_getter,
       const SafeBrowsingProtocolConfig& config) override {
+    base::AutoLock locker(lock_);
+
     pm_ = new TestProtocolManager(delegate, request_context_getter, config);
+
+    if (!quit_closure_.is_null()) {
+      quit_closure_.Run();
+      quit_closure_ = base::Closure();
+    }
+
     return base::WrapUnique(pm_);
   }
 
-  TestProtocolManager* GetProtocolManager() { return pm_; }
+  TestProtocolManager* GetProtocolManager() {
+    base::RunLoop loop;
+    bool should_wait = false;
+    {
+      base::AutoLock locker(lock_);
+
+      if (pm_)
+        return pm_;
+
+      quit_closure_ = loop.QuitClosure();
+      should_wait = true;
+    }
+
+    if (should_wait)
+      loop.Run();
+
+   {
+     base::AutoLock locker(lock_);
+     return pm_;
+   }
+  }
 
  private:
+  base::Lock lock_;
+
   // Owned by the SafeBrowsingService.
   TestProtocolManager* pm_;
+  base::Closure quit_closure_;
 };
 
 class MockObserver : public SafeBrowsingUIManager::Observer {
diff --git a/chrome/browser/ui/cocoa/passwords/account_avatar_fetcher_manager.h b/chrome/browser/ui/cocoa/passwords/account_avatar_fetcher_manager.h
index 1d259661..3be32c6 100644
--- a/chrome/browser/ui/cocoa/passwords/account_avatar_fetcher_manager.h
+++ b/chrome/browser/ui/cocoa/passwords/account_avatar_fetcher_manager.h
@@ -8,7 +8,7 @@
 #include <Cocoa/Cocoa.h>
 
 #include "base/memory/ref_counted.h"
-#include "net/url_request/url_request_context_getter.h"
+#include "content/public/common/url_loader_factory.mojom.h"
 
 class AccountAvatarFetcherBridge;
 @class CredentialItemButton;
@@ -17,12 +17,11 @@
 // Handles retrieving avatar images for credential items.
 @interface AccountAvatarFetcherManager : NSObject {
   std::vector<std::unique_ptr<AccountAvatarFetcherBridge>> bridges_;
-  scoped_refptr<net::URLRequestContextGetter> requestContext_;
+  content::mojom::URLLoaderFactory* loaderFactory_;
 }
 
-// Initializes a manager with the specified request context.
-- (id)initWithRequestContext:
-        (scoped_refptr<net::URLRequestContextGetter>)requestContext;
+// Initializes a manager with the specified URL loader factory.
+- (id)initWithLoaderFactory:(content::mojom::URLLoaderFactory*)loaderFactory;
 
 // Retrieves the image located at |avatarURL| and updates |view| if successful.
 - (void)fetchAvatar:(const GURL&)avatarURL forView:(CredentialItemButton*)view;
diff --git a/chrome/browser/ui/cocoa/passwords/account_avatar_fetcher_manager.mm b/chrome/browser/ui/cocoa/passwords/account_avatar_fetcher_manager.mm
index 2667a12..26a40209 100644
--- a/chrome/browser/ui/cocoa/passwords/account_avatar_fetcher_manager.mm
+++ b/chrome/browser/ui/cocoa/passwords/account_avatar_fetcher_manager.mm
@@ -54,16 +54,15 @@
 
 @implementation AccountAvatarFetcherManager
 
-- (id)initWithRequestContext:
-        (scoped_refptr<net::URLRequestContextGetter>)requestContext {
+- (id)initWithLoaderFactory:(content::mojom::URLLoaderFactory*)loaderFactory {
   if ((self = [super init])) {
-    requestContext_ = requestContext;
+    loaderFactory_ = loaderFactory;
   }
   return self;
 }
 
 - (void)startRequestWithFetcher:(AccountAvatarFetcher*)fetcher {
-  fetcher->Start(requestContext_.get());
+  fetcher->Start(loaderFactory_);
 }
 
 - (void)fetchAvatar:(const GURL&)avatarURL forView:(CredentialItemButton*)view {
diff --git a/chrome/browser/ui/cocoa/passwords/account_chooser_view_controller.mm b/chrome/browser/ui/cocoa/passwords/account_chooser_view_controller.mm
index bbe5d4f..0e9f263 100644
--- a/chrome/browser/ui/cocoa/passwords/account_chooser_view_controller.mm
+++ b/chrome/browser/ui/cocoa/passwords/account_chooser_view_controller.mm
@@ -55,7 +55,7 @@
 - (instancetype)initWithBridge:(PasswordPromptBridgeInterface*)bridge {
   base::scoped_nsobject<AccountAvatarFetcherManager> avatarManager(
       [[AccountAvatarFetcherManager alloc]
-           initWithRequestContext:bridge->GetRequestContext()]);
+          initWithLoaderFactory:bridge->GetURLLoaderFactory()]);
   return [self initWithBridge:bridge avatarManager:avatarManager];
 }
 
diff --git a/chrome/browser/ui/cocoa/passwords/account_chooser_view_controller_unittest.mm b/chrome/browser/ui/cocoa/passwords/account_chooser_view_controller_unittest.mm
index 3e3b54f4..fa3a70c 100644
--- a/chrome/browser/ui/cocoa/passwords/account_chooser_view_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/passwords/account_chooser_view_controller_unittest.mm
@@ -82,7 +82,7 @@
   // PasswordPromptBridgeInterface:
   void PerformClose() override;
   PasswordDialogController* GetDialogController() override;
-  net::URLRequestContextGetter* GetRequestContext() const override;
+  content::mojom::URLLoaderFactory* GetURLLoaderFactory() const override;
 
  private:
   PasswordDialogControllerMock dialog_controller_;
@@ -121,8 +121,8 @@
   return &dialog_controller_;
 }
 
-net::URLRequestContextGetter*
-AccountChooserViewControllerTest::GetRequestContext() const {
+content::mojom::URLLoaderFactory*
+AccountChooserViewControllerTest::GetURLLoaderFactory() const {
   NOTREACHED();
   return nullptr;
 }
diff --git a/chrome/browser/ui/cocoa/passwords/auto_signin_view_controller.mm b/chrome/browser/ui/cocoa/passwords/auto_signin_view_controller.mm
index 60f79f09..961020c6 100644
--- a/chrome/browser/ui/cocoa/passwords/auto_signin_view_controller.mm
+++ b/chrome/browser/ui/cocoa/passwords/auto_signin_view_controller.mm
@@ -18,6 +18,8 @@
 #include "chrome/browser/ui/passwords/manage_passwords_view_utils.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/strings/grit/components_strings.h"
+#include "content/public/browser/storage_partition.h"
+#include "content/public/common/url_loader_factory.mojom.h"
 #include "skia/ext/skia_utils_mac.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
@@ -41,10 +43,12 @@
 
 - (instancetype)initWithDelegate:
     (id<BasePasswordsContentViewDelegate>)delegate {
-  auto* request_context = delegate.model->GetProfile()->GetRequestContext();
+  auto* loader_factory = content::BrowserContext::GetDefaultStoragePartition(
+                             delegate.model->GetProfile())
+                             ->GetURLLoaderFactoryForBrowserProcess();
   base::scoped_nsobject<AccountAvatarFetcherManager> avatarManager(
       [[AccountAvatarFetcherManager alloc]
-          initWithRequestContext:request_context]);
+          initWithLoaderFactory:loader_factory]);
   return [self initWithAvatarManager:avatarManager delegate:delegate];
 }
 
diff --git a/chrome/browser/ui/cocoa/passwords/autosignin_prompt_view_controller_unittest.mm b/chrome/browser/ui/cocoa/passwords/autosignin_prompt_view_controller_unittest.mm
index c46ef8f..63bba56 100644
--- a/chrome/browser/ui/cocoa/passwords/autosignin_prompt_view_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/passwords/autosignin_prompt_view_controller_unittest.mm
@@ -41,7 +41,7 @@
   // PasswordPromptBridgeInterface:
   void PerformClose() override;
   PasswordDialogController* GetDialogController() override;
-  net::URLRequestContextGetter* GetRequestContext() const override;
+  content::mojom::URLLoaderFactory* GetURLLoaderFactory() const override;
 
  private:
   PasswordDialogControllerMock dialog_controller_;
@@ -70,8 +70,8 @@
   return &dialog_controller_;
 }
 
-net::URLRequestContextGetter*
-AutoSigninPromptViewControllerTest::GetRequestContext() const {
+content::mojom::URLLoaderFactory*
+AutoSigninPromptViewControllerTest::GetURLLoaderFactory() const {
   NOTREACHED();
   return nullptr;
 }
diff --git a/chrome/browser/ui/cocoa/passwords/password_prompt_bridge_interface.h b/chrome/browser/ui/cocoa/passwords/password_prompt_bridge_interface.h
index 579a9e8..bc2cc86 100644
--- a/chrome/browser/ui/cocoa/passwords/password_prompt_bridge_interface.h
+++ b/chrome/browser/ui/cocoa/passwords/password_prompt_bridge_interface.h
@@ -6,8 +6,10 @@
 #define CHROME_BROWSER_UI_COCOA_PASSWORDS_PASSWORD_PROMPT_BRIDGE_INTERFACE_H_
 
 class PasswordDialogController;
-namespace net {
-class URLRequestContextGetter;
+namespace content {
+namespace mojom {
+class URLLoaderFactory;
+}
 }
 
 // An interface for the bridge between AccountChooserViewController and platform
@@ -20,8 +22,8 @@
   // Returns the controller containing the data.
   virtual PasswordDialogController* GetDialogController() = 0;
 
-  // Returns the request context for fetching the avatars.
-  virtual net::URLRequestContextGetter* GetRequestContext() const = 0;
+  // Returns the URL loader factory for fetching the avatars.
+  virtual content::mojom::URLLoaderFactory* GetURLLoaderFactory() const = 0;
 
  protected:
   virtual ~PasswordPromptBridgeInterface() = default;
diff --git a/chrome/browser/ui/cocoa/passwords/password_prompt_view_bridge.h b/chrome/browser/ui/cocoa/passwords/password_prompt_view_bridge.h
index b373110..a936f77 100644
--- a/chrome/browser/ui/cocoa/passwords/password_prompt_view_bridge.h
+++ b/chrome/browser/ui/cocoa/passwords/password_prompt_view_bridge.h
@@ -36,7 +36,7 @@
   // PasswordPromptBridgeInterface:
   void PerformClose() override;
   PasswordDialogController* GetDialogController() override;
-  net::URLRequestContextGetter* GetRequestContext() const override;
+  content::mojom::URLLoaderFactory* GetURLLoaderFactory() const override;
 
  private:
   void ShowWindow();
diff --git a/chrome/browser/ui/cocoa/passwords/password_prompt_view_bridge.mm b/chrome/browser/ui/cocoa/passwords/password_prompt_view_bridge.mm
index be9929d6e..392f776 100644
--- a/chrome/browser/ui/cocoa/passwords/password_prompt_view_bridge.mm
+++ b/chrome/browser/ui/cocoa/passwords/password_prompt_view_bridge.mm
@@ -10,7 +10,9 @@
 #import "chrome/browser/ui/cocoa/passwords/account_chooser_view_controller.h"
 #import "chrome/browser/ui/cocoa/passwords/autosignin_prompt_view_controller.h"
 #include "chrome/browser/ui/passwords/password_dialog_controller.h"
+#include "content/public/browser/storage_partition.h"
 #include "content/public/browser/web_contents.h"
+#include "content/public/common/url_loader_factory.mojom.h"
 
 PasswordPromptViewBridge::PasswordPromptViewBridge(
     PasswordDialogController* controller,
@@ -56,10 +58,11 @@
   return controller_;
 }
 
-net::URLRequestContextGetter*
-PasswordPromptViewBridge::GetRequestContext() const {
-  return Profile::FromBrowserContext(web_contents_->GetBrowserContext())->
-      GetRequestContext();
+content::mojom::URLLoaderFactory*
+PasswordPromptViewBridge::GetURLLoaderFactory() const {
+  return content::BrowserContext::GetDefaultStoragePartition(
+             Profile::FromBrowserContext(web_contents_->GetBrowserContext()))
+      ->GetURLLoaderFactoryForBrowserProcess();
 }
 
 void PasswordPromptViewBridge::ShowWindow() {
@@ -82,4 +85,3 @@
     PasswordDialogController* controller, content::WebContents* web_contents) {
   return new PasswordPromptViewBridge(controller, web_contents);
 }
-
diff --git a/chrome/browser/ui/passwords/account_avatar_fetcher.cc b/chrome/browser/ui/passwords/account_avatar_fetcher.cc
index 958b666..a07a3ca 100644
--- a/chrome/browser/ui/passwords/account_avatar_fetcher.cc
+++ b/chrome/browser/ui/passwords/account_avatar_fetcher.cc
@@ -53,12 +53,12 @@
 AccountAvatarFetcher::~AccountAvatarFetcher() = default;
 
 void AccountAvatarFetcher::Start(
-    net::URLRequestContextGetter* request_context) {
-  fetcher_.Init(request_context, std::string(),
-                net::URLRequest::NEVER_CLEAR_REFERRER,
+    content::mojom::URLLoaderFactory* loader_factory) {
+  fetcher_.Init(std::string(), blink::kWebReferrerPolicyAlways,
                 net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES |
-                net::LOAD_DO_NOT_SEND_AUTH_DATA | net::LOAD_MAYBE_USER_GESTURE);
-  fetcher_.Start();
+                    net::LOAD_DO_NOT_SEND_AUTH_DATA |
+                    net::LOAD_MAYBE_USER_GESTURE);
+  fetcher_.Start(loader_factory);
 }
 
 void AccountAvatarFetcher::OnFetchComplete(const GURL& /*url*/,
diff --git a/chrome/browser/ui/passwords/account_avatar_fetcher.h b/chrome/browser/ui/passwords/account_avatar_fetcher.h
index 09b7f40..3dae0a94 100644
--- a/chrome/browser/ui/passwords/account_avatar_fetcher.h
+++ b/chrome/browser/ui/passwords/account_avatar_fetcher.h
@@ -10,14 +10,16 @@
 #include "chrome/browser/bitmap_fetcher/bitmap_fetcher.h"
 #include "url/gurl.h"
 
+namespace content {
+namespace mojom {
+class URLLoaderFactory;
+}
+}  // namespace content
+
 namespace gfx {
 class ImageSkia;
 }  // namespace gfx
 
-namespace net {
-class URLRequestContextGetter;
-}  // namespace net
-
 class AccountAvatarFetcherDelegate {
  public:
   virtual void UpdateAvatar(const gfx::ImageSkia& image) = 0;
@@ -33,7 +35,7 @@
 
   ~AccountAvatarFetcher() override;
 
-  void Start(net::URLRequestContextGetter* request_context);
+  void Start(content::mojom::URLLoaderFactory* loader_factory);
 
  private:
   // chrome::BitmapFetcherDelegate:
diff --git a/chrome/browser/ui/views/passwords/account_chooser_dialog_view.cc b/chrome/browser/ui/views/passwords/account_chooser_dialog_view.cc
index c6388319..53de1ca6 100644
--- a/chrome/browser/ui/views/passwords/account_chooser_dialog_view.cc
+++ b/chrome/browser/ui/views/passwords/account_chooser_dialog_view.cc
@@ -14,6 +14,7 @@
 #include "chrome/grit/generated_resources.h"
 #include "components/autofill/core/common/password_form.h"
 #include "components/constrained_window/constrained_window_views.h"
+#include "content/public/browser/storage_partition.h"
 #include "content/public/browser/web_contents.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
@@ -51,7 +52,7 @@
 views::ScrollView* CreateCredentialsView(
     const PasswordDialogController::FormsVector& forms,
     views::ButtonListener* button_listener,
-    net::URLRequestContextGetter* request_context) {
+    content::mojom::URLLoaderFactory* loader_factory) {
   views::View* list_view = new views::View;
   list_view->SetLayoutManager(
       new views::BoxLayout(views::BoxLayout::kVertical));
@@ -59,9 +60,9 @@
   for (const auto& form : forms) {
     std::pair<base::string16, base::string16> titles =
         GetCredentialLabelsForAccountChooser(*form);
-    CredentialsItemView* credential_view = new CredentialsItemView(
-        button_listener, titles.first, titles.second, kButtonHoverColor,
-        form.get(), request_context);
+    CredentialsItemView* credential_view =
+        new CredentialsItemView(button_listener, titles.first, titles.second,
+                                kButtonHoverColor, form.get(), loader_factory);
     credential_view->SetLowerLabelColor(kAutoSigninTextColor);
     ChromeLayoutProvider* layout_provider = ChromeLayoutProvider::Get();
     gfx::Insets insets =
@@ -178,9 +179,11 @@
 
 void AccountChooserDialogView::InitWindow() {
   SetLayoutManager(new views::FillLayout());
-  AddChildView(CreateCredentialsView(
-      controller_->GetLocalForms(), this,
-      GetProfileFromWebContents(web_contents_)->GetRequestContext()));
+  AddChildView(
+      CreateCredentialsView(controller_->GetLocalForms(), this,
+                            content::BrowserContext::GetDefaultStoragePartition(
+                                GetProfileFromWebContents(web_contents_))
+                                ->GetURLLoaderFactoryForBrowserProcess()));
 }
 
 AccountChooserPrompt* CreateAccountChooserPromptView(
diff --git a/chrome/browser/ui/views/passwords/credentials_item_view.cc b/chrome/browser/ui/views/passwords/credentials_item_view.cc
index 1f255ca0..a4d91a64 100644
--- a/chrome/browser/ui/views/passwords/credentials_item_view.cc
+++ b/chrome/browser/ui/views/passwords/credentials_item_view.cc
@@ -62,7 +62,7 @@
     const base::string16& lower_text,
     SkColor hover_color,
     const autofill::PasswordForm* form,
-    net::URLRequestContextGetter* request_context)
+    content::mojom::URLLoaderFactory* loader_factory)
     : Button(button_listener),
       form_(form),
       upper_label_(nullptr),
@@ -84,7 +84,7 @@
     // Fetch the actual avatar.
     AccountAvatarFetcher* fetcher = new AccountAvatarFetcher(
         form_->icon_url, weak_ptr_factory_.GetWeakPtr());
-    fetcher->Start(request_context);
+    fetcher->Start(loader_factory);
   }
   AddChildView(image_view_);
 
diff --git a/chrome/browser/ui/views/passwords/credentials_item_view.h b/chrome/browser/ui/views/passwords/credentials_item_view.h
index 8aeda91..877dcb00 100644
--- a/chrome/browser/ui/views/passwords/credentials_item_view.h
+++ b/chrome/browser/ui/views/passwords/credentials_item_view.h
@@ -14,14 +14,16 @@
 struct PasswordForm;
 }
 
+namespace content {
+namespace mojom {
+class URLLoaderFactory;
+}
+}  // namespace content
+
 namespace gfx {
 class ImageSkia;
 }
 
-namespace net {
-class URLRequestContextGetter;
-}
-
 namespace views {
 class ImageView;
 class Label;
@@ -37,7 +39,7 @@
                       const base::string16& lower_text,
                       SkColor hover_color,
                       const autofill::PasswordForm* form,
-                      net::URLRequestContextGetter* request_context);
+                      content::mojom::URLLoaderFactory* loader_factory);
   ~CredentialsItemView() override;
 
   const autofill::PasswordForm* form() const { return form_; }
diff --git a/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.cc b/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.cc
index ead7b543..e7125411 100644
--- a/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.cc
+++ b/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.cc
@@ -27,6 +27,7 @@
 #include "chrome/grit/theme_resources.h"
 #include "components/password_manager/core/common/password_manager_features.h"
 #include "components/strings/grit/components_strings.h"
+#include "content/public/browser/storage_partition.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/material_design/material_design_controller.h"
 #include "ui/base/models/combobox_model.h"
@@ -394,7 +395,9 @@
   }
   credential = new CredentialsItemView(
       this, upper_text, lower_text, kButtonHoverColor, &form,
-      parent_->model()->GetProfile()->GetRequestContext());
+      content::BrowserContext::GetDefaultStoragePartition(
+          parent_->model()->GetProfile())
+          ->GetURLLoaderFactoryForBrowserProcess());
   credential->SetEnabled(false);
   AddChildView(credential);
 
diff --git a/chrome/browser/ui/views/passwords/manage_passwords_bubble_view_interactive_uitest.cc b/chrome/browser/ui/views/passwords/manage_passwords_bubble_view_interactive_uitest.cc
index 30e1687..3caff75 100644
--- a/chrome/browser/ui/views/passwords/manage_passwords_bubble_view_interactive_uitest.cc
+++ b/chrome/browser/ui/views/passwords/manage_passwords_bubble_view_interactive_uitest.cc
@@ -26,11 +26,16 @@
 #include "content/public/browser/notification_types.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/common/content_features.h"
-#include "net/url_request/test_url_fetcher_factory.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "net/test/embedded_test_server/http_request.h"
+#include "net/test/embedded_test_server/http_response.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "ui/base/ui_base_features.h"
 #include "ui/base/ui_features.h"
 
+using net::test_server::BasicHttpResponse;
+using net::test_server::HttpRequest;
+using net::test_server::HttpResponse;
 using testing::Eq;
 using testing::Field;
 using testing::_;
@@ -39,23 +44,6 @@
 
 const char kDisplayDispositionMetric[] = "PasswordBubble.DisplayDisposition";
 
-// A helper class that will create FakeURLFetcher and record the requested URLs.
-class TestURLFetcherCallback {
- public:
-  std::unique_ptr<net::FakeURLFetcher> CreateURLFetcher(
-      const GURL& url,
-      net::URLFetcherDelegate* d,
-      const std::string& response_data,
-      net::HttpStatusCode response_code,
-      net::URLRequestStatus::Status status) {
-    OnRequestDone(url);
-    return std::unique_ptr<net::FakeURLFetcher>(
-        new net::FakeURLFetcher(url, d, response_data, response_code, status));
-  }
-
-  MOCK_METHOD1(OnRequestDone, void(const GURL&));
-};
-
 bool IsBubbleShowing() {
   return ManagePasswordsBubbleView::manage_password_bubble() &&
       ManagePasswordsBubbleView::manage_password_bubble()->
@@ -81,6 +69,17 @@
     ManagePasswordsTest::SetUp();
   }
 
+  MOCK_METHOD0(OnIconRequestDone, void());
+
+  // Called on the server background thread.
+  std::unique_ptr<HttpResponse> HandleRequest(const HttpRequest& request) {
+    std::unique_ptr<BasicHttpResponse> response(new BasicHttpResponse);
+    if (request.relative_url == "/icon.png") {
+      OnIconRequestDone();
+    }
+    return std::move(response);
+  }
+
  private:
   base::test::ScopedFeatureList scoped_feature_list_;
 
@@ -349,24 +348,21 @@
 }
 
 IN_PROC_BROWSER_TEST_F(ManagePasswordsBubbleViewTest, AutoSignin) {
+  // Set up the test server to handle the form icon request.
+  embedded_test_server()->RegisterRequestHandler(base::BindRepeating(
+      &ManagePasswordsBubbleViewTest::HandleRequest, base::Unretained(this)));
+  ASSERT_TRUE(embedded_test_server()->InitializeAndListen());
   test_form()->origin = GURL("https://example.com");
   test_form()->display_name = base::ASCIIToUTF16("Peter");
   test_form()->username_value = base::ASCIIToUTF16("pet12@gmail.com");
-  GURL icon_url("https://google.com/icon.png");
-  test_form()->icon_url = icon_url;
+  test_form()->icon_url = embedded_test_server()->GetURL("/icon.png");
   std::vector<std::unique_ptr<autofill::PasswordForm>> local_credentials;
   local_credentials.push_back(
       base::MakeUnique<autofill::PasswordForm>(*test_form()));
 
   // Prepare to capture the network request.
-  TestURLFetcherCallback url_callback;
-  net::FakeURLFetcherFactory factory(
-      NULL,
-      base::Bind(&TestURLFetcherCallback::CreateURLFetcher,
-                 base::Unretained(&url_callback)));
-  factory.SetFakeResponse(icon_url, std::string(), net::HTTP_OK,
-                          net::URLRequestStatus::FAILED);
-  EXPECT_CALL(url_callback, OnRequestDone(icon_url));
+  EXPECT_CALL(*this, OnIconRequestDone());
+  embedded_test_server()->StartAcceptingConnections();
 
   SetupAutoSignin(std::move(local_credentials));
   EXPECT_TRUE(IsBubbleShowing());
diff --git a/chrome/browser/ui/views/passwords/password_dialog_view_browsertest.cc b/chrome/browser/ui/views/passwords/password_dialog_view_browsertest.cc
index baa4f0e..414d8fa 100644
--- a/chrome/browser/ui/views/passwords/password_dialog_view_browsertest.cc
+++ b/chrome/browser/ui/views/passwords/password_dialog_view_browsertest.cc
@@ -19,32 +19,20 @@
 #include "components/password_manager/core/browser/password_bubble_experiment.h"
 #include "components/password_manager/core/common/password_manager_pref_names.h"
 #include "components/prefs/pref_service.h"
-#include "net/url_request/test_url_fetcher_factory.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "net/test/embedded_test_server/http_request.h"
+#include "net/test/embedded_test_server/http_response.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "ui/views/test/widget_test.h"
 #include "ui/views/widget/widget.h"
 
 using ::testing::Field;
+using net::test_server::BasicHttpResponse;
+using net::test_server::HttpRequest;
+using net::test_server::HttpResponse;
 
 namespace {
 
-// A helper class that will create FakeURLFetcher and record the requested URLs.
-class TestURLFetcherCallback {
- public:
-  std::unique_ptr<net::FakeURLFetcher> CreateURLFetcher(
-      const GURL& url,
-      net::URLFetcherDelegate* d,
-      const std::string& response_data,
-      net::HttpStatusCode response_code,
-      net::URLRequestStatus::Status status) {
-    OnRequestDone(url);
-    return std::unique_ptr<net::FakeURLFetcher>(
-        new net::FakeURLFetcher(url, d, response_data, response_code, status));
-  }
-
-  MOCK_METHOD1(OnRequestDone, void(const GURL&));
-};
-
 // ManagePasswordsUIController subclass to capture the dialog instance
 class TestManagePasswordsUIController : public ManagePasswordsUIController {
  public:
@@ -127,6 +115,16 @@
   }
 
   MOCK_METHOD1(OnChooseCredential, void(const autofill::PasswordForm*));
+  MOCK_METHOD0(OnIconRequestDone, void());
+
+  // Called on the server background thread.
+  std::unique_ptr<HttpResponse> HandleRequest(const HttpRequest& request) {
+    std::unique_ptr<BasicHttpResponse> response(new BasicHttpResponse);
+    if (request.relative_url == "/icon.png") {
+      OnIconRequestDone();
+    }
+    return std::move(response);
+  }
 
  private:
   TestManagePasswordsUIController* controller_;
@@ -172,6 +170,10 @@
 
 IN_PROC_BROWSER_TEST_F(PasswordDialogViewTest,
                        PopupAccountChooserWithMultipleCredentialsReturnEmpty) {
+  // Set up the test server to handle the form icon request.
+  embedded_test_server()->RegisterRequestHandler(base::BindRepeating(
+      &PasswordDialogViewTest::HandleRequest, base::Unretained(this)));
+  ASSERT_TRUE(embedded_test_server()->InitializeAndListen());
   GURL origin("https://example.com");
   std::vector<std::unique_ptr<autofill::PasswordForm>> local_credentials;
   autofill::PasswordForm form;
@@ -180,21 +182,15 @@
   form.username_value = base::ASCIIToUTF16("peter@pan.test");
   form.icon_url = GURL("broken url");
   local_credentials.push_back(base::MakeUnique<autofill::PasswordForm>(form));
-  GURL icon_url("https://google.com/icon.png");
-  form.icon_url = icon_url;
+  form.icon_url = embedded_test_server()->GetURL("/icon.png");
   form.display_name = base::ASCIIToUTF16("Peter Pan");
   form.federation_origin =
       url::Origin::Create(GURL("https://google.com/federation"));
   local_credentials.push_back(base::MakeUnique<autofill::PasswordForm>(form));
 
   // Prepare to capture the network request.
-  TestURLFetcherCallback url_callback;
-  net::FakeURLFetcherFactory factory(
-      nullptr, base::Bind(&TestURLFetcherCallback::CreateURLFetcher,
-                          base::Unretained(&url_callback)));
-  factory.SetFakeResponse(icon_url, std::string(), net::HTTP_OK,
-                          net::URLRequestStatus::FAILED);
-  EXPECT_CALL(url_callback, OnRequestDone(icon_url));
+  EXPECT_CALL(*this, OnIconRequestDone());
+  embedded_test_server()->StartAcceptingConnections();
 
   SetupChooseCredentials(std::move(local_credentials), origin);
   ASSERT_TRUE(controller()->current_account_chooser());
diff --git a/chrome/browser/ui/views/profiles/profile_chooser_view.cc b/chrome/browser/ui/views/profiles/profile_chooser_view.cc
index 2d9f183..933da78 100644
--- a/chrome/browser/ui/views/profiles/profile_chooser_view.cc
+++ b/chrome/browser/ui/views/profiles/profile_chooser_view.cc
@@ -887,7 +887,7 @@
     bool is_guest) {
   if (!avatar_item.signed_in &&
       signin::IsDiceEnabledForProfile(browser_->profile()->GetPrefs()))
-    return CreateDiceTurnOnSyncView();
+    return CreateDiceSigninView();
 
   ChromeLayoutProvider* provider = ChromeLayoutProvider::Get();
 
@@ -989,7 +989,7 @@
   return view;
 }
 
-views::View* ProfileChooserView::CreateDiceTurnOnSyncView() {
+views::View* ProfileChooserView::CreateDiceSigninView() {
   // Creates a view that holds an illustration and a promo, which includes a
   // button. The illustration should slightly overlap with the promo at the
   // bottom, therefore between_child_spacing of |view| is set to negative
@@ -1013,7 +1013,7 @@
       gfx::Insets(0, kMenuEdgeMargin, kMenuEdgeMargin, kMenuEdgeMargin),
       kMenuEdgeMargin));
   views::Label* promo = new views::Label(
-      l10n_util::GetStringUTF16(IDS_PROFILES_TURN_ON_SYNC_PROMO));
+      l10n_util::GetStringUTF16(IDS_PROFILES_DICE_SIGNIN_PROMO));
   promo->SetMultiLine(true);
   promo->SetHorizontalAlignment(gfx::ALIGN_LEFT);
   promo->SetMaximumWidth(menu_width_ - 2 * kMenuEdgeMargin);
@@ -1021,7 +1021,7 @@
 
   signin_current_profile_button_ =
       views::MdTextButton::CreateSecondaryUiBlueButton(
-          this, l10n_util::GetStringUTF16(IDS_PROFILES_TURN_ON_SYNC_BUTTON));
+          this, l10n_util::GetStringUTF16(IDS_PROFILES_DICE_SIGNIN_BUTTON));
   promo_button_view->AddChildView(signin_current_profile_button_);
   view->AddChildView(promo_button_view);
   return view;
diff --git a/chrome/browser/ui/views/profiles/profile_chooser_view.h b/chrome/browser/ui/views/profiles/profile_chooser_view.h
index e0f96d9..23a1029 100644
--- a/chrome/browser/ui/views/profiles/profile_chooser_view.h
+++ b/chrome/browser/ui/views/profiles/profile_chooser_view.h
@@ -149,9 +149,9 @@
                            bool reauth_required,
                            int width);
 
-  // Creates the DICE UI view to turn on sync. It includes an illustration, a
-  // promo and a button.
-  views::View* CreateDiceTurnOnSyncView();
+  // Creates the DICE UI view to sign in and turn on sync. It includes an
+  // illustration, a promo and a button.
+  views::View* CreateDiceSigninView();
 
   // Creates a view to confirm account removal for |account_id_to_remove_|.
   views::View* CreateAccountRemovalView();
diff --git a/chrome/browser/ui/webui/settings/chromeos/easy_unlock_settings_handler.cc b/chrome/browser/ui/webui/settings/chromeos/easy_unlock_settings_handler.cc
index e761bea..d19dc51 100644
--- a/chrome/browser/ui/webui/settings/chromeos/easy_unlock_settings_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/easy_unlock_settings_handler.cc
@@ -33,6 +33,10 @@
     content::WebUIDataSource* html_source,
     Profile* profile) {
   EasyUnlockService* easy_unlock_service = EasyUnlockService::Get(profile);
+  // The service is not created for LockScreenApp profiles or "off the record".
+  if (!easy_unlock_service)
+    return nullptr;
+
   bool allowed = easy_unlock_service->IsAllowed();
   html_source->AddBoolean("easyUnlockAllowed", allowed);
   html_source->AddBoolean("easyUnlockEnabled",
diff --git a/chrome/browser/ui/webui/settings/chromeos/easy_unlock_settings_handler_unittest.cc b/chrome/browser/ui/webui/settings/chromeos/easy_unlock_settings_handler_unittest.cc
index d56e735..c1e69fd 100644
--- a/chrome/browser/ui/webui/settings/chromeos/easy_unlock_settings_handler_unittest.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/easy_unlock_settings_handler_unittest.cc
@@ -100,6 +100,11 @@
       Profile::FromBrowserContext(context));
 }
 
+std::unique_ptr<KeyedService> CreateNullEasyUnlockServiceForTest(
+    content::BrowserContext* context) {
+  return nullptr;
+}
+
 }  // namespace
 
 class EasyUnlockSettingsHandlerTest : public testing::Test {
@@ -120,6 +125,13 @@
         EasyUnlockService::Get(profile_.get()));
   }
 
+  void MakeEasyUnlockServiceNull() {
+    TestingProfile::Builder builder;
+    builder.AddTestingFactory(EasyUnlockServiceFactory::GetInstance(),
+                              &CreateNullEasyUnlockServiceForTest);
+    profile_ = builder.Build();
+  }
+
   void VerifyEnabledStatusCallback(size_t expected_total_calls,
                                    bool expected_status) {
     std::string event;
@@ -191,6 +203,16 @@
   EXPECT_FALSE(handler.get());
 }
 
+TEST_F(EasyUnlockSettingsHandlerTest, NotCreatedWhenEasyUnlockServiceNull) {
+  MakeEasyUnlockServiceNull();
+  std::unique_ptr<EasyUnlockSettingsHandler> handler;
+  content::WebUIDataSource* data_source =
+      content::WebUIDataSource::Create("test-data-source");
+  content::WebUIDataSource::Add(profile(), data_source);
+  handler.reset(EasyUnlockSettingsHandler::Create(data_source, profile()));
+  EXPECT_FALSE(handler.get());
+}
+
 TEST_F(EasyUnlockSettingsHandlerTest, EnabledStatus) {
   std::unique_ptr<EasyUnlockSettingsHandler> handler;
   handler.reset(new TestEasyUnlockSettingsHandler(profile()));
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc
index be0af73..58fe4a7e 100644
--- a/chrome/common/chrome_features.cc
+++ b/chrome/common/chrome_features.cc
@@ -199,6 +199,12 @@
                                          base::FEATURE_ENABLED_BY_DEFAULT};
 #endif
 
+#if defined(OS_ANDROID)
+// Enable changing default downloads storage location on Android.
+const base::Feature kDownloadsLocationChange{"DownloadsLocationChange",
+                                             base::FEATURE_DISABLED_BY_DEFAULT};
+#endif
+
 // Enables Expect CT reporting, which sends reports for opted-in sites
 // that don't serve sufficient Certificate Transparency information.
 const base::Feature kExpectCTReporting{"ExpectCTReporting",
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h
index 891d564..c6705685 100644
--- a/chrome/common/chrome_features.h
+++ b/chrome/common/chrome_features.h
@@ -105,6 +105,10 @@
 extern const base::Feature kDownloadsForeground;
 #endif
 
+#if defined(OS_ANDROID)
+extern const base::Feature kDownloadsLocationChange;
+#endif
+
 extern const base::Feature kExpectCTReporting;
 
 extern const base::Feature kExperimentalAppBanners;
diff --git a/chrome/renderer/autofill/autofill_renderer_browsertest.cc b/chrome/renderer/autofill/autofill_renderer_browsertest.cc
index eb1553b..98926f17 100644
--- a/chrome/renderer/autofill/autofill_renderer_browsertest.cc
+++ b/chrome/renderer/autofill/autofill_renderer_browsertest.cc
@@ -88,6 +88,10 @@
     called_field_change_ = true;
   }
 
+  void TextFieldDidScroll(const FormData& form,
+                          const FormFieldData& field,
+                          const gfx::RectF& bounding_box) override {}
+
   void QueryFormFieldAutofill(int32_t id,
                               const FormData& form,
                               const FormFieldData& field,
diff --git a/chrome/renderer/autofill/form_autocomplete_browsertest.cc b/chrome/renderer/autofill/form_autocomplete_browsertest.cc
index b77136e..6ce4f32 100644
--- a/chrome/renderer/autofill/form_autocomplete_browsertest.cc
+++ b/chrome/renderer/autofill/form_autocomplete_browsertest.cc
@@ -66,6 +66,10 @@
                           const gfx::RectF& bounding_box,
                           base::TimeTicks timestamp) override {}
 
+  void TextFieldDidScroll(const FormData& form,
+                          const FormFieldData& field,
+                          const gfx::RectF& bounding_box) override {}
+
   void QueryFormFieldAutofill(int32_t id,
                               const FormData& form,
                               const FormFieldData& field,
diff --git a/chrome/test/chromedriver/client/chromedriver.py b/chrome/test/chromedriver/client/chromedriver.py
index a028701..c751e6a 100644
--- a/chrome/test/chromedriver/client/chromedriver.py
+++ b/chrome/test/chromedriver/client/chromedriver.py
@@ -152,7 +152,7 @@
     elif chrome_binary:
       options['binary'] = chrome_binary
 
-    if sys.platform.startswith('linux') and not util.Is64Bit():
+    if sys.platform.startswith('linux'):
       if chrome_switches is None:
         chrome_switches = []
       # Workaround for crbug.com/611886.
diff --git a/chrome/test/chromedriver/test/run_py_tests.py b/chrome/test/chromedriver/test/run_py_tests.py
index b737f36..abef2ed 100755
--- a/chrome/test/chromedriver/test/run_py_tests.py
+++ b/chrome/test/chromedriver/test/run_py_tests.py
@@ -87,6 +87,8 @@
     'MobileEmulationCapabilityTest.testDeviceName',
     'MobileEmulationCapabilityTest.testNetworkConnectionTypeIsAppliedToAllTabs',
     'MobileEmulationCapabilityTest.testNetworkConnectionTypeIsAppliedToAllTabsImmediately',
+    # https://bugs.chromium.org/p/chromedriver/issues/detail?id=2164
+    'ChromeDriverTest.testSendTextToAlert',
 ]
 
 _VERSION_SPECIFIC_FILTER['64'] = [
diff --git a/chromecast/BUILD.gn b/chromecast/BUILD.gn
index a6768ea..4a93fd3 100644
--- a/chromecast/BUILD.gn
+++ b/chromecast/BUILD.gn
@@ -375,6 +375,7 @@
     test_type = "junit"
     tests = [
       "//base:base_junit_tests",
+      "//chromecast/base:cast_base_junit_tests",
       "//chromecast/browser/android:cast_shell_junit_tests",
       "//content/public/android:content_junit_tests",
       "//net/android:net_junit_tests",
diff --git a/chromecast/base/BUILD.gn b/chromecast/base/BUILD.gn
index 29db389..0dfcb1e 100644
--- a/chromecast/base/BUILD.gn
+++ b/chromecast/base/BUILD.gn
@@ -269,6 +269,7 @@
     java_files = [
       "$java_src_dir/org/chromium/chromecast/base/CastSettingsManager.java",
       "$java_src_dir/org/chromium/chromecast/base/ChromecastConfigAndroid.java",
+      "$java_src_dir/org/chromium/chromecast/base/CircularBuffer.java",
       "$java_src_dir/org/chromium/chromecast/base/DumpstateWriter.java",
       "$java_src_dir/org/chromium/chromecast/base/SystemTimeChangeNotifierAndroid.java",
     ]
@@ -277,4 +278,15 @@
       "//base:base_java",
     ]
   }
+
+  junit_binary("cast_base_junit_tests") {
+    java_test_dir = "//chromecast/base/java/test"
+    java_files = [
+      "$java_test_dir/org/chromium/chromecast/base/CircularBufferTest.java",
+    ]
+    deps = [
+      ":base_java",
+      "//third_party/hamcrest:hamcrest_java",
+    ]
+  }
 }
diff --git a/chromecast/base/java/src/org/chromium/chromecast/base/CircularBuffer.java b/chromecast/base/java/src/org/chromium/chromecast/base/CircularBuffer.java
new file mode 100644
index 0000000..8e0c33d
--- /dev/null
+++ b/chromecast/base/java/src/org/chromium/chromecast/base/CircularBuffer.java
@@ -0,0 +1,78 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chromecast.base;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * An Iterable object that stores up to a fixed amount of objects, and overwrites the least-recently
+ * inserted object if it exceeds its capacity. Appending, removing, and iterating are all constant
+ * time.
+ *
+ * This class is intended as a fast Iterable Deque with a fixed capacity. LinkedList generates lint
+ * warnings because every item requires a heap allocation for the Node, ArrayList requires rewriting
+ * the list when the head is removed, and ArrayDeque is not fixed-size.
+ *
+ * Currently, the only supported use case is appending items to the buffer, and then iterating the
+ * buffer. Concurrent modification while iterating, or appending items after iterating, is
+ * undefined behavior as of now.
+ *
+ * @param <T> The type that elements of the buffer should be instances of.
+ */
+public class CircularBuffer<T> implements Iterable<T> {
+    private final List<T> mData;
+    private final int mSize;
+    private boolean mAtCapacity;
+    private int mHeadPosition;
+    private int mTailPosition;
+
+    public CircularBuffer(int size) {
+        mData = new ArrayList<T>(size);
+        mSize = size;
+        mAtCapacity = false;
+        mHeadPosition = 0;
+        mTailPosition = 0;
+    }
+
+    public void add(T item) {
+        if (mSize == 0) {
+            return;
+        }
+        if (mAtCapacity) {
+            mData.set(mHeadPosition, item);
+            mHeadPosition = increment(mHeadPosition);
+        } else {
+            mData.add(item);
+        }
+        mTailPosition = increment(mTailPosition);
+        if (mTailPosition == mHeadPosition) {
+            mAtCapacity = true;
+        }
+    }
+
+    @Override
+    public Iterator<T> iterator() {
+        return new Iterator<T>() {
+            @Override
+            public boolean hasNext() {
+                return mAtCapacity || mHeadPosition != mTailPosition;
+            }
+
+            @Override
+            public T next() {
+                T result = mData.get(mHeadPosition);
+                mHeadPosition = increment(mHeadPosition);
+                mAtCapacity = false;
+                return result;
+            }
+        };
+    }
+
+    private int increment(int position) {
+        return (position + 1) % mSize;
+    }
+}
diff --git a/chromecast/base/java/test/org/chromium/chromecast/base/CircularBufferTest.java b/chromecast/base/java/test/org/chromium/chromecast/base/CircularBufferTest.java
new file mode 100644
index 0000000..ec52b9b
--- /dev/null
+++ b/chromecast/base/java/test/org/chromium/chromecast/base/CircularBufferTest.java
@@ -0,0 +1,73 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chromecast.base;
+
+import static org.hamcrest.Matchers.contains;
+import static org.hamcrest.Matchers.emptyIterable;
+import static org.junit.Assert.assertThat;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.BlockJUnit4ClassRunner;
+
+/**
+ * Tests for CircularBuffer.
+ *
+ * Currently, the only supported use case is appending items to the buffer, and then iterating the
+ * buffer. Concurrent modification while iterating, or appending items after iterating, is
+ * undefined behavior as of now.
+ */
+@RunWith(BlockJUnit4ClassRunner.class)
+public class CircularBufferTest {
+    @Test
+    public void testBufferWithNoCapacity() {
+        CircularBuffer<String> buffer = new CircularBuffer<>(0);
+        buffer.add("a");
+        assertThat(buffer, emptyIterable());
+    }
+
+    @Test
+    public void testBufferWithPartialCapacity() {
+        CircularBuffer<String> buffer = new CircularBuffer<>(4);
+        buffer.add("a");
+        buffer.add("b");
+        buffer.add("c");
+        assertThat(buffer, contains("a", "b", "c"));
+    }
+
+    @Test
+    public void testBufferWithFullCapacity() {
+        CircularBuffer<String> buffer = new CircularBuffer<>(4);
+        buffer.add("zero");
+        buffer.add("one");
+        buffer.add("two");
+        buffer.add("three");
+        assertThat(buffer, contains("zero", "one", "two", "three"));
+    }
+
+    @Test
+    public void testBufferThatOverflowsCapacityWrapsAroundAndErasesOldestElements() {
+        CircularBuffer<String> buffer = new CircularBuffer<>(4);
+        buffer.add("1");
+        buffer.add("2");
+        buffer.add("3");
+        buffer.add("4"); // Hits capacity; subsequent additions overwrite oldest elements.
+        buffer.add("5"); // erases "1"
+        buffer.add("6"); // erases "2"
+        assertThat(buffer, contains("3", "4", "5", "6"));
+    }
+
+    @Test
+    public void testBufferThatOverflowsTwice() {
+        CircularBuffer<String> buffer = new CircularBuffer<>(2);
+        buffer.add("a");
+        buffer.add("b");
+        buffer.add("c");
+        buffer.add("d");
+        buffer.add("e");
+        // Since the capacity is 2, return the 2 most-recently added items.
+        assertThat(buffer, contains("d", "e"));
+    }
+}
diff --git a/chromecast/browser/android/BUILD.gn b/chromecast/browser/android/BUILD.gn
index 9374666d..54077e51 100644
--- a/chromecast/browser/android/BUILD.gn
+++ b/chromecast/browser/android/BUILD.gn
@@ -11,9 +11,8 @@
 cast_shell_android_manifest =
     "$root_gen_dir/cast_shell_manifest/AndroidManifest.xml"
 
-manifest_variables = [
-  "cast_build_enable_background_activities=$enable_background_activities",
-]
+manifest_variables =
+    [ "cast_build_enable_background_activities=$enable_background_activities" ]
 
 jinja_template("cast_shell_manifest") {
   input = "apk/AndroidManifest.xml.jinja2"
@@ -69,6 +68,7 @@
     "$java_src_dir/org/chromium/chromecast/shell/CastWebContentsActivity.java",
     "$java_src_dir/org/chromium/chromecast/shell/CastWebContentsService.java",
     "$java_src_dir/org/chromium/chromecast/shell/CastWebContentsComponent.java",
+    "$java_src_dir/org/chromium/chromecast/shell/LogcatElision.java",
     "$java_src_dir/org/chromium/chromecast/shell/LogcatExtractor.java",
   ]
 
@@ -102,6 +102,7 @@
 junit_binary("cast_shell_junit_tests") {
   java_files = [
     "junit/src/org/chromium/chromecast/shell/CastWebContentsComponentTest.java",
+    "junit/src/org/chromium/chromecast/shell/LogcatElisionUnitTest.java",
     "junit/src/org/chromium/chromecast/shell/LogcatExtractorUnitTest.java",
   ]
 
@@ -113,5 +114,6 @@
     "//base:base_java_test_support",
     "//content/public/android:content_java",
     "//third_party/android_tools:android_support_core_utils_java",
+    "//third_party/hamcrest:hamcrest_java",
   ]
 }
diff --git a/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/LogcatElision.java b/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/LogcatElision.java
new file mode 100644
index 0000000..596e10f
--- /dev/null
+++ b/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/LogcatElision.java
@@ -0,0 +1,179 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chromecast.shell;
+
+import android.util.Patterns;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+class LogcatElision {
+    private static final String EMAIL_ELISION = "<EMAIL-ELIDED>";
+    private static final String URL_ELISION = "<WEBADDRESS-ELIDED>";
+
+    private static final String GOOD_IRI_CHAR = "a-zA-Z0-9\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF";
+
+    private static final Pattern IP_ADDRESS = Pattern.compile(
+            "((25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\.(25[0-5]|2[0-4]"
+            + "[0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1]"
+            + "[0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}"
+            + "|[1-9][0-9]|[0-9]))");
+
+    private static final String IRI =
+            "[" + GOOD_IRI_CHAR + "]([" + GOOD_IRI_CHAR + "\\-]{0,61}[" + GOOD_IRI_CHAR + "]){0,1}";
+
+    private static final String GOOD_GTLD_CHAR = "a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF";
+    private static final String GTLD = "[" + GOOD_GTLD_CHAR + "]{2,63}";
+    private static final String HOST_NAME = "(" + IRI + "\\.)+" + GTLD;
+
+    private static final Pattern DOMAIN_NAME =
+            Pattern.compile("(" + HOST_NAME + "|" + IP_ADDRESS + ")");
+
+    private static final Pattern WEB_URL =
+            Pattern.compile("(?:\\b|^)((?:(http|https|Http|Https|rtsp|Rtsp):"
+                    + "\\/\\/(?:(?:[a-zA-Z0-9\\$\\-\\_\\.\\+\\!\\*\\'\\(\\)"
+                    + "\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,64}(?:\\:(?:[a-zA-Z0-9\\$\\-\\_"
+                    + "\\.\\+\\!\\*\\'\\(\\)\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,25})?\\@)?)?"
+                    + "(?:" + DOMAIN_NAME + ")"
+                    + "(?:\\:\\d{1,5})?)"
+                    + "(\\/(?:(?:[" + GOOD_IRI_CHAR + "\\;\\/\\?\\:\\@\\&\\=\\#\\~"
+                    + "\\-\\.\\+\\!\\*\\'\\(\\)\\,\\_])|(?:\\%[a-fA-F0-9]{2}))*)?"
+                    + "(?:\\b|$)");
+
+    private static final String IP_ELISION = "<IP-ELIDED>";
+    private static final String MAC_ELISION = "<MAC-ELIDED>";
+
+    private static final String CONSOLE_ELISION = "[ELIDED:CONSOLE(0)] ELIDED CONSOLE MESSAGE";
+
+    private static final Pattern MAC_ADDRESS =
+            Pattern.compile("([0-9a-fA-F]{2}[-:]+){5}[0-9a-fA-F]{2}");
+    private static final Pattern CONSOLE_MSG = Pattern.compile("\\[\\w*:CONSOLE.*\\].*");
+
+    private static final String[] CHROME_NAMESPACE = new String[] {"org.chromium.", "com.google."};
+
+    private static final String[] CAST_NAMESPACE = new String[] {"Cast.", "CastV2."};
+
+    private static final String[] SYSTEM_NAMESPACE = new String[] {"android.accessibilityservice",
+            "android.accounts", "android.animation", "android.annotation", "android.app",
+            "android.appwidget", "android.bluetooth", "android.content", "android.database",
+            "android.databinding", "android.drm", "android.gesture", "android.graphics",
+            "android.hardware", "android.inputmethodservice", "android.location", "android.media",
+            "android.mtp", "android.net", "android.nfc", "android.opengl", "android.os",
+            "android.preference", "android.print", "android.printservice", "android.provider",
+            "android.renderscript", "android.sax", "android.security", "android.service",
+            "android.speech", "android.support", "android.system", "android.telecom",
+            "android.telephony", "android.test", "android.text", "android.transition",
+            "android.util", "android.view", "android.webkit", "android.widget", "com.android.",
+            "dalvik.", "java.", "javax.", "org.apache.", "org.json.", "org.w3c.dom.", "org.xml.",
+            "org.xmlpull."};
+
+    private static final Pattern JAVA_FILE = Pattern.compile(".java:[0-9]+$");
+
+    /**
+     * Elides any emails in the specified {@link String} with {@link
+     * #EMAIL_ELISION}.
+     *
+     * @param original String potentially containing emails.
+     * @return String with elided emails.
+     */
+    private static String elideEmail(String original) {
+        return Patterns.EMAIL_ADDRESS.matcher(original).replaceAll(EMAIL_ELISION);
+    }
+    /**
+     * Elides any URLs in the specified {@link String} with
+     * {@link #URL_ELISION}.
+     *
+     * @param original String potentially containing URLs.
+     * @return String with elided URLs.
+     */
+    private static String elideUrl(String original) {
+        StringBuilder buffer = new StringBuilder(original);
+        Matcher matcher = WEB_URL.matcher(buffer);
+        int start = 0;
+        while (matcher.find(start)) {
+            start = matcher.start();
+            int end = matcher.end();
+            String url = buffer.substring(start, end);
+            if (!likelyToBeChromeNamespace(url) && !likelyToBeSystemNamespace(url)
+                    && !likelyToBeCastNamespace(url) && !likelyToBeJavaFile(url)) {
+                buffer.replace(start, end, URL_ELISION);
+                end = start + URL_ELISION.length();
+                matcher = WEB_URL.matcher(buffer);
+            }
+            start = end;
+        }
+        return buffer.toString();
+    }
+
+    private static boolean likelyToBeChromeNamespace(String url) {
+        for (String ns : CHROME_NAMESPACE) {
+            if (url.startsWith(ns)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private static boolean likelyToBeSystemNamespace(String url) {
+        for (String ns : SYSTEM_NAMESPACE) {
+            if (url.startsWith(ns)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private static boolean likelyToBeCastNamespace(String url) {
+        for (String ns : CAST_NAMESPACE) {
+            if (url.startsWith(ns)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public static boolean likelyToBeJavaFile(String url) {
+        return JAVA_FILE.matcher(url).find();
+    }
+    /**
+     * Elides any IP addresses in the specified {@link String} with {@link
+     * #IP_ELISION}.
+     *
+     * @param original String potentially containing IPs.
+     * @return String with elided IPs.
+     */
+    private static String elideIp(String original) {
+        return Patterns.IP_ADDRESS.matcher(original).replaceAll(IP_ELISION);
+    }
+    /**
+     * Elides any MAC addresses in the specified {@link String} with {@link
+     * #MAC_ELISION}.
+     *
+     * @param original String potentially containing MACs.
+     * @return String with elided MACs.
+     */
+    private static String elideMac(String original) {
+        return MAC_ADDRESS.matcher(original).replaceAll(MAC_ELISION);
+    }
+    /**
+     * Elides any console messages in the specified {@link String} with {@link
+     * #CONSOLE_ELISION}.
+     *
+     * @param original String potentially containing console messages.
+     * @return String with elided console messages.
+     */
+    private static String elideConsole(String original) {
+        return CONSOLE_MSG.matcher(original).replaceAll(CONSOLE_ELISION);
+    }
+
+    public static String elide(String ln) {
+        ln = elideEmail(ln);
+        ln = elideIp(ln);
+        ln = elideUrl(ln);
+        ln = elideMac(ln);
+        ln = elideConsole(ln);
+        return ln;
+    }
+}
diff --git a/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/LogcatExtractor.java b/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/LogcatExtractor.java
index 2429a9a..5bf138b 100644
--- a/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/LogcatExtractor.java
+++ b/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/LogcatExtractor.java
@@ -1,126 +1,57 @@
 // Copyright 2017 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
-package org.chromium.chromecast.shell;
 
-import android.util.Patterns;
+package org.chromium.chromecast.shell;
 
 import org.chromium.base.Log;
 import org.chromium.base.VisibleForTesting;
+import org.chromium.chromecast.base.CircularBuffer;
 
 import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStreamReader;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
+import java.nio.charset.Charset;
+import java.nio.charset.UnsupportedCharsetException;
 
 /**
  * Extracts logcat out of Android devices and elide PII sensitive info from it.
  *
  * <p>Elided information includes: Emails, IP address, MAC address, URL/domains as well as
  * Javascript console messages.
- *
- * <p>Caller provides a list of minidump files as well as an intent. This Callable will then extract
- * the most recent logcat and save a copy for each minidump.
- *
- * <p>Upon completion, each minidump + logcat pairs will be passed to the MinidumpPreparationService
- * along with the intent provided here.
  */
 class LogcatExtractor {
     private static final String TAG = "LogcatExtractor";
     private static final long HALF_SECOND = 500;
-    protected static final String EMAIL_ELISION = "XXX@EMAIL.ELIDED";
-    @VisibleForTesting
-    protected static final String URL_ELISION = "HTTP://WEBADDRESS.ELIDED";
-
-    private static final String GOOD_IRI_CHAR = "a-zA-Z0-9\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF";
-
-    private static final Pattern IP_ADDRESS = Pattern.compile(
-            "((25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\.(25[0-5]|2[0-4]"
-            + "[0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1]"
-            + "[0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}"
-            + "|[1-9][0-9]|[0-9]))");
-
-    private static final String IRI =
-            "[" + GOOD_IRI_CHAR + "]([" + GOOD_IRI_CHAR + "\\-]{0,61}[" + GOOD_IRI_CHAR + "]){0,1}";
-
-    private static final String GOOD_GTLD_CHAR = "a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF";
-    private static final String GTLD = "[" + GOOD_GTLD_CHAR + "]{2,63}";
-    private static final String HOST_NAME = "(" + IRI + "\\.)+" + GTLD;
-
-    private static final Pattern DOMAIN_NAME =
-            Pattern.compile("(" + HOST_NAME + "|" + IP_ADDRESS + ")");
-
-    private static final Pattern WEB_URL =
-            Pattern.compile("(?:\\b|^)((?:(http|https|Http|Https|rtsp|Rtsp):"
-                    + "\\/\\/(?:(?:[a-zA-Z0-9\\$\\-\\_\\.\\+\\!\\*\\'\\(\\)"
-                    + "\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,64}(?:\\:(?:[a-zA-Z0-9\\$\\-\\_"
-                    + "\\.\\+\\!\\*\\'\\(\\)\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,25})?\\@)?)?"
-                    + "(?:" + DOMAIN_NAME + ")"
-                    + "(?:\\:\\d{1,5})?)"
-                    + "(\\/(?:(?:[" + GOOD_IRI_CHAR + "\\;\\/\\?\\:\\@\\&\\=\\#\\~"
-                    + "\\-\\.\\+\\!\\*\\'\\(\\)\\,\\_])|(?:\\%[a-fA-F0-9]{2}))*)?"
-                    + "(?:\\b|$)");
-
-    @VisibleForTesting
-    protected static final String IP_ELISION = "1.2.3.4";
-    @VisibleForTesting
-    protected static final String MAC_ELISION = "01:23:45:67:89:AB";
-
-    @VisibleForTesting
-    protected static final String CONSOLE_ELISION = "[ELIDED:CONSOLE(0)] ELIDED CONSOLE MESSAGE";
-
-    private static final Pattern MAC_ADDRESS =
-            Pattern.compile("([0-9a-fA-F]{2}[-:]+){5}[0-9a-fA-F]{2}");
-    private static final Pattern CONSOLE_MSG = Pattern.compile("\\[\\w*:CONSOLE.*\\].*");
-
-    private static final String[] CHROME_NAMESPACE = new String[] {"org.chromium.", "com.google."};
-
-    private static final String[] CAST_NAMESPACE = new String[] {"Cast.", "CastV2."};
-
-    private static final String[] SYSTEM_NAMESPACE = new String[] {"android.accessibilityservice",
-            "android.accounts", "android.animation", "android.annotation", "android.app",
-            "android.appwidget", "android.bluetooth", "android.content", "android.database",
-            "android.databinding", "android.drm", "android.gesture", "android.graphics",
-            "android.hardware", "android.inputmethodservice", "android.location", "android.media",
-            "android.mtp", "android.net", "android.nfc", "android.opengl", "android.os",
-            "android.preference", "android.print", "android.printservice", "android.provider",
-            "android.renderscript", "android.sax", "android.security", "android.service",
-            "android.speech", "android.support", "android.system", "android.telecom",
-            "android.telephony", "android.test", "android.text", "android.transition",
-            "android.util", "android.view", "android.webkit", "android.widget", "com.android.",
-            "dalvik.", "java.", "javax.", "org.apache.", "org.json.", "org.w3c.dom.", "org.xml.",
-            "org.xmlpull."};
-
-    private static final Pattern JAVA_FILE = Pattern.compile(".java:[0-9]+$");
 
     public static String getElidedLogcat() throws IOException, InterruptedException {
-        List<String> rawLogcat = getLogcat();
-        List<String> elidedLogcat = Collections.unmodifiableList(processLogcat(rawLogcat));
-        return joinLines(elidedLogcat);
+        return getElidedLogcat(getLogcat());
     }
 
-    private static List<String> getLogcat() throws IOException, InterruptedException {
-        LinkedList<String> rawLogcat = new LinkedList<String>();
+    @VisibleForTesting
+    static String getElidedLogcat(Iterable<String> rawLogcat) {
+        StringBuilder builder = new StringBuilder();
+        for (String line : rawLogcat) {
+            builder.append(LogcatElision.elide(line));
+            builder.append("\n");
+        }
+        return builder.toString();
+    }
+
+    private static Iterable<String> getLogcat() throws IOException, InterruptedException {
+        CircularBuffer<String> rawLogcat = new CircularBuffer<>(BuildConfig.LOGCAT_SIZE);
         String logLn = null;
         Integer exitValue = null;
 
         Process p = Runtime.getRuntime().exec("logcat -d");
         BufferedReader bReader = null;
         try {
-            bReader = new BufferedReader(new InputStreamReader(p.getInputStream()));
+            bReader = new BufferedReader(
+                    new InputStreamReader(p.getInputStream(), Charset.forName("UTF-8")));
             while (exitValue == null) {
                 while ((logLn = bReader.readLine()) != null) {
-                    // Add each new string to the end of the queue.
+                    // Add each new string to the end of the buffer.
                     rawLogcat.add(logLn);
-                    if (rawLogcat.size() > BuildConfig.LOGCAT_SIZE) {
-                        // Remove the head of the queue when it gets too large.
-                        rawLogcat.remove();
-                    }
                 }
                 try {
                     exitValue = p.exitValue();
@@ -134,130 +65,14 @@
                 throw new IOException(msg);
             }
             return rawLogcat;
+        } catch (UnsupportedCharsetException e) {
+            // Should never happen; all Java implementations are required to support UTF-8.
+            Log.wtf(TAG, "UTF-8 not supported", e);
+            return rawLogcat;
         } finally {
             if (bReader != null) {
                 bReader.close();
             }
         }
     }
-
-    private static String joinLines(List<String> elidedLogcat) {
-        StringBuilder sBuilder = new StringBuilder();
-        for (String ln : elidedLogcat) {
-            sBuilder.append(ln);
-            sBuilder.append("\n");
-        }
-        return sBuilder.toString();
-    }
-
-    @VisibleForTesting
-    protected static List<String> processLogcat(List<String> rawLogcat) {
-        List<String> out = new ArrayList<String>(rawLogcat.size());
-        for (String ln : rawLogcat) {
-            ln = elideEmail(ln);
-            ln = elideUrl(ln);
-            ln = elideIp(ln);
-            ln = elideMac(ln);
-            ln = elideConsole(ln);
-            out.add(ln);
-        }
-        return out;
-    }
-    /**
-     * Elides any emails in the specified {@link String} with {@link #EMAIL_ELISION}.
-     *
-     * @param original String potentially containing emails.
-     * @return String with elided emails.
-     */
-    @VisibleForTesting
-    protected static String elideEmail(String original) {
-        return Patterns.EMAIL_ADDRESS.matcher(original).replaceAll(EMAIL_ELISION);
-    }
-    /**
-     * Elides any URLs in the specified {@link String} with
-     * {@link #URL_ELISION}.
-     *
-     * @param original String potentially containing URLs.
-     * @return String with elided URLs.
-     */
-    @VisibleForTesting
-    protected static String elideUrl(String original) {
-        StringBuilder buffer = new StringBuilder(original);
-        Matcher matcher = WEB_URL.matcher(buffer);
-        int start = 0;
-        while (matcher.find(start)) {
-            start = matcher.start();
-            int end = matcher.end();
-            String url = buffer.substring(start, end);
-            if (!likelyToBeChromeNamespace(url) && !likelyToBeSystemNamespace(url)
-                    && !likelyToBeCastNamespace(url) && !likelyToBeJavaFile(url)) {
-                buffer.replace(start, end, URL_ELISION);
-                end = start + URL_ELISION.length();
-                matcher = WEB_URL.matcher(buffer);
-            }
-            start = end;
-        }
-        return buffer.toString();
-    }
-
-    public static boolean likelyToBeChromeNamespace(String url) {
-        for (String ns : CHROME_NAMESPACE) {
-            if (url.startsWith(ns)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    public static boolean likelyToBeSystemNamespace(String url) {
-        for (String ns : SYSTEM_NAMESPACE) {
-            if (url.startsWith(ns)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    public static boolean likelyToBeCastNamespace(String url) {
-        for (String ns : CAST_NAMESPACE) {
-            if (url.startsWith(ns)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    public static boolean likelyToBeJavaFile(String url) {
-        return JAVA_FILE.matcher(url).find();
-    }
-    /**
-     * Elides any IP addresses in the specified {@link String} with {@link #IP_ELISION}.
-     *
-     * @param original String potentially containing IPs.
-     * @return String with elided IPs.
-     */
-    @VisibleForTesting
-    protected static String elideIp(String original) {
-        return Patterns.IP_ADDRESS.matcher(original).replaceAll(IP_ELISION);
-    }
-    /**
-     * Elides any MAC addresses in the specified {@link String} with {@link #MAC_ELISION}.
-     *
-     * @param original String potentially containing MACs.
-     * @return String with elided MACs.
-     */
-    @VisibleForTesting
-    protected static String elideMac(String original) {
-        return MAC_ADDRESS.matcher(original).replaceAll(MAC_ELISION);
-    }
-    /**
-     * Elides any console messages in the specified {@link String} with {@link #CONSOLE_ELISION}.
-     *
-     * @param original String potentially containing console messages.
-     * @return String with elided console messages.
-     */
-    @VisibleForTesting
-    protected static String elideConsole(String original) {
-        return CONSOLE_MSG.matcher(original).replaceAll(CONSOLE_ELISION);
-    }
 }
diff --git a/chromecast/browser/android/junit/src/org/chromium/chromecast/shell/LogcatElisionUnitTest.java b/chromecast/browser/android/junit/src/org/chromium/chromecast/shell/LogcatElisionUnitTest.java
new file mode 100644
index 0000000..4015b01
--- /dev/null
+++ b/chromecast/browser/android/junit/src/org/chromium/chromecast/shell/LogcatElisionUnitTest.java
@@ -0,0 +1,142 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chromecast.shell;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.BlockJUnit4ClassRunner;
+
+/**
+ * junit tests for {@link LogcatExtractor}.
+ */
+@RunWith(BlockJUnit4ClassRunner.class)
+public class LogcatElisionUnitTest {
+    private static final int MAX_LINES = 5;
+
+    @Test
+    public void testElideEmail() {
+        String original = "email me at someguy@mailservice.com";
+        String expected = "email me at <EMAIL-ELIDED>";
+        assertEquals(expected, LogcatElision.elide(original));
+    }
+
+    @Test
+    public void testElideUrl() {
+        String original = "file bugs at crbug.com";
+        String expected = "file bugs at <WEBADDRESS-ELIDED>";
+        assertEquals(expected, LogcatElision.elide(original));
+    }
+
+    @Test
+    public void testElideUrl2() {
+        String original = "exception at org.chromium.chrome.browser.crash.LogcatElisionUnitTest";
+        assertEquals(original, LogcatElision.elide(original));
+    }
+
+    @Test
+    public void testElideUrl3() {
+        String original = "file bugs at crbug.com or code.google.com";
+        String expected = "file bugs at <WEBADDRESS-ELIDED> or <WEBADDRESS-ELIDED>";
+        assertEquals(expected, LogcatElision.elide(original));
+    }
+
+    @Test
+    public void testElideUrl4() {
+        String original = "test shorturl.com !!!";
+        String expected = "test <WEBADDRESS-ELIDED> !!!";
+        assertEquals(expected, LogcatElision.elide(original));
+    }
+
+    @Test
+    public void testElideUrl5() {
+        String original = "test just.the.perfect.len.url !!!";
+        String expected = "test <WEBADDRESS-ELIDED> !!!";
+        assertEquals(expected, LogcatElision.elide(original));
+    }
+
+    @Test
+    public void testElideUrl6() {
+        String original = "test a.very.very.very.very.very.long.url !!!";
+        String expected = "test <WEBADDRESS-ELIDED> !!!";
+        assertEquals(expected, LogcatElision.elide(original));
+    }
+
+    @Test
+    public void testElideUrl7() {
+        String original = " at android.content.Intent \n at java.util.ArrayList";
+        assertEquals(original, LogcatElision.elide(original));
+    }
+
+    @Test
+    public void testDontElideFileSuffixes() {
+        String original = "chromium_android_linker.so";
+        assertEquals(original, LogcatElision.elide(original));
+    }
+
+    @Test
+    public void testElideIp() {
+        String original = "traceroute 127.0.0.1";
+        String expected = "traceroute <IP-ELIDED>";
+        assertEquals(expected, LogcatElision.elide(original));
+    }
+
+    @Test
+    public void testElideMac1() {
+        String original = "MAC: AB-AB-AB-AB-AB-AB";
+        String expected = "MAC: <MAC-ELIDED>";
+        assertEquals(expected, LogcatElision.elide(original));
+    }
+
+    @Test
+    public void testElideMac2() {
+        String original = "MAC: AB:AB:AB:AB:AB:AB";
+        String expected = "MAC: <MAC-ELIDED>";
+        assertEquals(expected, LogcatElision.elide(original));
+    }
+
+    @Test
+    public void testElideConsole() {
+        String original = "I/chromium(123): [INFO:CONSOLE(2)] hello!";
+        String expected = "I/chromium(123): [ELIDED:CONSOLE(0)] ELIDED CONSOLE MESSAGE";
+        assertEquals(expected, LogcatElision.elide(original));
+    }
+
+    @Test
+    public void testLogTagNotElided() {
+        String original = "I/cr_FooBar(123): Some message";
+        assertEquals(original, LogcatElision.elide(original));
+    }
+
+    @Test
+    public void testLogCastNotElided() {
+        String original = "09-08 11:52:12.569  4406  4406 I chromium: "
+                + "Cast.Discovery.Mdns.Request.AppId.In=25";
+        assertEquals(original, LogcatElision.elide(original));
+    }
+
+    @Test
+    public void testLogAndroidNotElided() {
+        String original = "09-08 11:54:38.053  4406  4406 D cr_AvSettingsAndroid:"
+                + "[AvSettingsAndroid.java:180] HDMI plug update: "
+                + "action=android.media.action.HDMI_AUDIO_PLUG, plug=1";
+        assertEquals(original, LogcatElision.elide(original));
+    }
+
+    @Test
+    public void testLogJavaNotElided() {
+        String original = "09-08 11:54:38.053  4406  4406 D cr_AvSettingsAndroid: "
+                + " [AvSettingsAndroid.java:187] Max channel count = 8";
+        assertEquals(original, LogcatElision.elide(original));
+    }
+
+    @Test
+    public void testLogCcNotElided() {
+        String original = "09-08 11:59:12.335  4406  4443 I chromium: "
+                + "[4406:4443:INFO:wifi_util.cc(113)]   No peers:";
+        assertEquals(original, LogcatElision.elide(original));
+    }
+}
diff --git a/chromecast/browser/android/junit/src/org/chromium/chromecast/shell/LogcatExtractorUnitTest.java b/chromecast/browser/android/junit/src/org/chromium/chromecast/shell/LogcatExtractorUnitTest.java
index a46fb03..d1de556 100644
--- a/chromecast/browser/android/junit/src/org/chromium/chromecast/shell/LogcatExtractorUnitTest.java
+++ b/chromecast/browser/android/junit/src/org/chromium/chromecast/shell/LogcatExtractorUnitTest.java
@@ -4,145 +4,57 @@
 
 package org.chromium.chromecast.shell;
 
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.not;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
+import org.junit.runners.BlockJUnit4ClassRunner;
 
-import org.chromium.testing.local.LocalRobolectricTestRunner;
-
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
+// TODO(sandv): Add test cases as need arises.
 /**
- * junit tests for {@link LogcatExtractor}.
+ * Tests for LogcatExtractor.
+ *
+ * Full testing of elision of PII is done in LogcatElisionUnitTest.
  */
-@RunWith(LocalRobolectricTestRunner.class)
-@Config(manifest = Config.NONE)
+@RunWith(BlockJUnit4ClassRunner.class)
 public class LogcatExtractorUnitTest {
-    private static final int MAX_LINES = 5;
-
     @Test
-    public void testElideEmail() {
-        String original = "email me at someguy@mailservice.com";
-        String expected = "email me at XXX@EMAIL.ELIDED";
-        assertEquals(expected, LogcatExtractor.elideEmail(original));
+    public void testEmptyLogcat() {
+        List<String> lines = new ArrayList<String>();
+        assertEquals("", LogcatExtractor.getElidedLogcat(lines));
     }
 
     @Test
-    public void testElideUrl() {
-        String original = "file bugs at crbug.com";
-        String expected = "file bugs at HTTP://WEBADDRESS.ELIDED";
-        assertEquals(expected, LogcatExtractor.elideUrl(original));
+    public void testLogcatOfEmptyString() {
+        List<String> lines = Arrays.asList("");
+        assertEquals("\n", LogcatExtractor.getElidedLogcat(lines));
     }
 
     @Test
-    public void testElideUrl2() {
-        String original = "exception at org.chromium.chrome.browser.crash.LogcatExtractorUnitTest";
-        assertEquals(original, LogcatExtractor.elideUrl(original));
+    public void testJoinsLines() {
+        List<String> lines = Arrays.asList("a", "b", "c");
+        assertEquals("a\nb\nc\n", LogcatExtractor.getElidedLogcat(lines));
     }
 
     @Test
-    public void testElideUrl3() {
-        String original = "file bugs at crbug.com or code.google.com";
-        String expected = "file bugs at HTTP://WEBADDRESS.ELIDED or HTTP://WEBADDRESS.ELIDED";
-        assertEquals(expected, LogcatExtractor.elideUrl(original));
+    public void testElidesPii() {
+        List<String> lines = Arrays.asList("email me at someguy@mailservice.com",
+                "file bugs at crbug.com", "at android.content.Intent", "at java.util.ArrayList",
+                "mac address: AB-AB-AB-AB-AB-AB");
+        String elided = LogcatExtractor.getElidedLogcat(lines);
+        // PII like email addresses, web addresses, and MAC addresses are elided.
+        assertThat(elided, not(containsString("someguy@mailservice.com")));
+        assertThat(elided, not(containsString("crbug.com")));
+        assertThat(elided, not(containsString("AB-AB-AB-AB-AB-AB")));
+        // Tags for class names relevant for debugging should not be elided.
+        assertThat(elided, containsString("android.content.Intent"));
+        assertThat(elided, containsString("java.util.ArrayList"));
     }
-
-    @Test
-    public void testElideUrl4() {
-        String original = "test shorturl.com !!!";
-        String expected = "test HTTP://WEBADDRESS.ELIDED !!!";
-        assertEquals(expected, LogcatExtractor.elideUrl(original));
-    }
-
-    @Test
-    public void testElideUrl5() {
-        String original = "test just.the.perfect.len.url !!!";
-        String expected = "test HTTP://WEBADDRESS.ELIDED !!!";
-        assertEquals(expected, LogcatExtractor.elideUrl(original));
-    }
-
-    @Test
-    public void testElideUrl6() {
-        String original = "test a.very.very.very.very.very.long.url !!!";
-        String expected = "test HTTP://WEBADDRESS.ELIDED !!!";
-        assertEquals(expected, LogcatExtractor.elideUrl(original));
-    }
-
-    @Test
-    public void testElideUrl7() {
-        String original = " at android.content.Intent \n at java.util.ArrayList";
-        assertEquals(original, LogcatExtractor.elideUrl(original));
-    }
-
-    @Test
-    public void testDontElideFileSuffixes() {
-        String original = "chromium_android_linker.so";
-        assertEquals(original, LogcatExtractor.elideUrl(original));
-    }
-
-    @Test
-    public void testElideIp() {
-        String original = "traceroute 127.0.0.1";
-        String expected = "traceroute 1.2.3.4";
-        assertEquals(expected, LogcatExtractor.elideIp(original));
-    }
-
-    @Test
-    public void testElideMac1() {
-        String original = "MAC: AB-AB-AB-AB-AB-AB";
-        String expected = "MAC: 01:23:45:67:89:AB";
-        assertEquals(expected, LogcatExtractor.elideMac(original));
-    }
-
-    @Test
-    public void testElideMac2() {
-        String original = "MAC: AB:AB:AB:AB:AB:AB";
-        String expected = "MAC: 01:23:45:67:89:AB";
-        assertEquals(expected, LogcatExtractor.elideMac(original));
-    }
-
-    @Test
-    public void testElideConsole() {
-        String original = "I/chromium(123): [INFO:CONSOLE(2)] hello!";
-        String expected = "I/chromium(123): [ELIDED:CONSOLE(0)] ELIDED CONSOLE MESSAGE";
-        assertEquals(expected, LogcatExtractor.elideConsole(original));
-    }
-
-    @Test
-    public void testLogTagNotElided() {
-        List<String> original = Arrays.asList(new String[] {"I/cr_FooBar(123): Some message"});
-        assertEquals(original, LogcatExtractor.processLogcat(original));
-    }
-
-    @Test
-    public void testLogCastNotElided() {
-        String original = "09-08 11:52:12.569  4406  4406 I chromium: "
-                + "Cast.Discovery.Mdns.Request.AppId.In=25";
-        assertEquals(original, LogcatExtractor.elideUrl(original));
-    }
-
-    @Test
-    public void testLogAndroidNotElided() {
-        String original = "09-08 11:54:38.053  4406  4406 D cr_AvSettingsAndroid:"
-                + "[AvSettingsAndroid.java:180] HDMI plug update: "
-                + "action=android.media.action.HDMI_AUDIO_PLUG, plug=1";
-        assertEquals(original, LogcatExtractor.elideUrl(original));
-    }
-
-    @Test
-    public void testLogJavaNotElided() {
-        String original = "09-08 11:54:38.053  4406  4406 D cr_AvSettingsAndroid: "
-                + " [AvSettingsAndroid.java:187] Max channel count = 8";
-        assertEquals(original, LogcatExtractor.elideUrl(original));
-    }
-
-    @Test
-    public void testLogCcNotElided() {
-        String original = "09-08 11:59:12.335  4406  4443 I chromium: "
-                + "[4406:4443:INFO:wifi_util.cc(113)]   No peers:";
-        assertEquals(original, LogcatExtractor.elideUrl(original));
-    }
-}
\ No newline at end of file
+}
diff --git a/chromecast/media/cma/backend/audio_video_pipeline_device_unittest.cc b/chromecast/media/cma/backend/audio_video_pipeline_device_unittest.cc
index d2a6d80..ef430518 100644
--- a/chromecast/media/cma/backend/audio_video_pipeline_device_unittest.cc
+++ b/chromecast/media/cma/backend/audio_video_pipeline_device_unittest.cc
@@ -889,13 +889,11 @@
 }
 
 void AudioVideoPipelineDeviceTest::EndImmediateEosTest() {
-  EXPECT_EQ(kStartPts, backend_->GetCurrentPts());
   RunPlaybackChecks();
 
   ASSERT_TRUE(backend_->Pause());
   base::RunLoop().RunUntilIdle();
 
-  EXPECT_EQ(kStartPts, backend_->GetCurrentPts());
   RunPlaybackChecks();
 
   backend_->Stop();
diff --git a/chromeos/dbus/cros_disks_client.cc b/chromeos/dbus/cros_disks_client.cc
index 44b40c7..e3e7b5f6 100644
--- a/chromeos/dbus/cros_disks_client.cc
+++ b/chromeos/dbus/cros_disks_client.cc
@@ -15,6 +15,7 @@
 #include "base/files/file_util.h"
 #include "base/location.h"
 #include "base/macros.h"
+#include "base/observer_list.h"
 #include "base/stl_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/sys_info.h"
@@ -94,7 +95,17 @@
 // The CrosDisksClient implementation.
 class CrosDisksClientImpl : public CrosDisksClient {
  public:
-  CrosDisksClientImpl() : proxy_(NULL), weak_ptr_factory_(this) {}
+  CrosDisksClientImpl() : proxy_(nullptr), weak_ptr_factory_(this) {}
+
+  // CrosDisksClient override.
+  void AddObserver(Observer* observer) override {
+    observer_list_.AddObserver(observer);
+  }
+
+  // CrosDisksClient override.
+  void RemoveObserver(Observer* observer) override {
+    observer_list_.RemoveObserver(observer);
+  }
 
   // CrosDisksClient override.
   void Mount(const std::string& source_path,
@@ -223,74 +234,50 @@
                        error_callback));
   }
 
-  // CrosDisksClient override.
-  void SetMountEventHandler(
-      const MountEventHandler& mount_event_handler) override {
-    static const SignalEventTuple kSignalEventTuples[] = {
-      { cros_disks::kDeviceAdded, CROS_DISKS_DEVICE_ADDED },
-      { cros_disks::kDeviceScanned, CROS_DISKS_DEVICE_SCANNED },
-      { cros_disks::kDeviceRemoved, CROS_DISKS_DEVICE_REMOVED },
-      { cros_disks::kDiskAdded, CROS_DISKS_DISK_ADDED },
-      { cros_disks::kDiskChanged, CROS_DISKS_DISK_CHANGED },
-      { cros_disks::kDiskRemoved, CROS_DISKS_DISK_REMOVED },
-    };
-    const size_t kNumSignalEventTuples = arraysize(kSignalEventTuples);
-
-    for (size_t i = 0; i < kNumSignalEventTuples; ++i) {
-      proxy_->ConnectToSignal(
-          cros_disks::kCrosDisksInterface,
-          kSignalEventTuples[i].signal_name,
-          base::Bind(&CrosDisksClientImpl::OnMountEvent,
-                     weak_ptr_factory_.GetWeakPtr(),
-                     kSignalEventTuples[i].event_type,
-                     mount_event_handler),
-          base::Bind(&CrosDisksClientImpl::OnSignalConnected,
-                     weak_ptr_factory_.GetWeakPtr()));
-    }
-  }
-
-  // CrosDisksClient override.
-  void SetMountCompletedHandler(
-      const MountCompletedHandler& mount_completed_handler) override {
-    proxy_->ConnectToSignal(
-        cros_disks::kCrosDisksInterface,
-        cros_disks::kMountCompleted,
-        base::Bind(&CrosDisksClientImpl::OnMountCompleted,
-                   weak_ptr_factory_.GetWeakPtr(),
-                   mount_completed_handler),
-        base::Bind(&CrosDisksClientImpl::OnSignalConnected,
-                   weak_ptr_factory_.GetWeakPtr()));
-  }
-
-  // CrosDisksClient override.
-  void SetFormatCompletedHandler(
-      const FormatCompletedHandler& format_completed_handler) override {
-    proxy_->ConnectToSignal(
-        cros_disks::kCrosDisksInterface,
-        cros_disks::kFormatCompleted,
-        base::Bind(&CrosDisksClientImpl::OnFormatCompleted,
-                   weak_ptr_factory_.GetWeakPtr(),
-                   format_completed_handler),
-        base::Bind(&CrosDisksClientImpl::OnSignalConnected,
-                   weak_ptr_factory_.GetWeakPtr()));
-  }
-
-  // CrosDisksClient override.
-  void SetRenameCompletedHandler(
-      const RenameCompletedHandler& rename_completed_handler) override {
-    proxy_->ConnectToSignal(
-        cros_disks::kCrosDisksInterface, cros_disks::kRenameCompleted,
-        base::Bind(&CrosDisksClientImpl::OnRenameCompleted,
-                   weak_ptr_factory_.GetWeakPtr(), rename_completed_handler),
-        base::Bind(&CrosDisksClientImpl::OnSignalConnected,
-                   weak_ptr_factory_.GetWeakPtr()));
-  }
-
  protected:
   void Init(dbus::Bus* bus) override {
     proxy_ = bus->GetObjectProxy(
         cros_disks::kCrosDisksServiceName,
         dbus::ObjectPath(cros_disks::kCrosDisksServicePath));
+
+    // Register handlers for D-Bus signals.
+    constexpr SignalEventTuple kSignalEventTuples[] = {
+        {cros_disks::kDeviceAdded, CROS_DISKS_DEVICE_ADDED},
+        {cros_disks::kDeviceScanned, CROS_DISKS_DEVICE_SCANNED},
+        {cros_disks::kDeviceRemoved, CROS_DISKS_DEVICE_REMOVED},
+        {cros_disks::kDiskAdded, CROS_DISKS_DISK_ADDED},
+        {cros_disks::kDiskChanged, CROS_DISKS_DISK_CHANGED},
+        {cros_disks::kDiskRemoved, CROS_DISKS_DISK_REMOVED},
+    };
+    for (const auto& entry : kSignalEventTuples) {
+      proxy_->ConnectToSignal(
+          cros_disks::kCrosDisksInterface, entry.signal_name,
+          base::BindRepeating(&CrosDisksClientImpl::OnMountEvent,
+                              weak_ptr_factory_.GetWeakPtr(), entry.event_type),
+          base::BindOnce(&CrosDisksClientImpl::OnSignalConnected,
+                         weak_ptr_factory_.GetWeakPtr()));
+    }
+
+    proxy_->ConnectToSignal(
+        cros_disks::kCrosDisksInterface, cros_disks::kMountCompleted,
+        base::BindRepeating(&CrosDisksClientImpl::OnMountCompleted,
+                            weak_ptr_factory_.GetWeakPtr()),
+        base::BindOnce(&CrosDisksClientImpl::OnSignalConnected,
+                       weak_ptr_factory_.GetWeakPtr()));
+
+    proxy_->ConnectToSignal(
+        cros_disks::kCrosDisksInterface, cros_disks::kFormatCompleted,
+        base::BindRepeating(&CrosDisksClientImpl::OnFormatCompleted,
+                            weak_ptr_factory_.GetWeakPtr()),
+        base::BindOnce(&CrosDisksClientImpl::OnSignalConnected,
+                       weak_ptr_factory_.GetWeakPtr()));
+
+    proxy_->ConnectToSignal(
+        cros_disks::kCrosDisksInterface, cros_disks::kRenameCompleted,
+        base::BindRepeating(&CrosDisksClientImpl::OnRenameCompleted,
+                            weak_ptr_factory_.GetWeakPtr()),
+        base::BindOnce(&CrosDisksClientImpl::OnSignalConnected,
+                       weak_ptr_factory_.GetWeakPtr()));
   }
 
  private:
@@ -429,32 +416,34 @@
     callback.Run(disk);
   }
 
-  // Handles mount event signals and calls |handler|.
-  void OnMountEvent(MountEventType event_type,
-                    MountEventHandler handler,
-                    dbus::Signal* signal) {
+  // Handles mount event signals and notifies observers.
+  void OnMountEvent(MountEventType event_type, dbus::Signal* signal) {
     dbus::MessageReader reader(signal);
     std::string device;
     if (!reader.PopString(&device)) {
       LOG(ERROR) << "Invalid signal: " << signal->ToString();
       return;
     }
-    handler.Run(event_type, device);
+
+    for (auto& observer : observer_list_)
+      observer.OnMountEvent(event_type, device);
   }
 
-  // Handles MountCompleted signal and calls |handler|.
-  void OnMountCompleted(MountCompletedHandler handler, dbus::Signal* signal) {
+  // Handles MountCompleted signal and notifies observers.
+  void OnMountCompleted(dbus::Signal* signal) {
     dbus::MessageReader reader(signal);
     MountEntry entry;
     if (!ReadMountEntryFromDbus(&reader, &entry)) {
       LOG(ERROR) << "Invalid signal: " << signal->ToString();
       return;
     }
-    handler.Run(entry);
+
+    for (auto& observer : observer_list_)
+      observer.OnMountCompleted(entry);
   }
 
-  // Handles FormatCompleted signal and calls |handler|.
-  void OnFormatCompleted(FormatCompletedHandler handler, dbus::Signal* signal) {
+  // Handles FormatCompleted signal and notifies observers.
+  void OnFormatCompleted(dbus::Signal* signal) {
     dbus::MessageReader reader(signal);
     uint32_t error_code = 0;
     std::string device_path;
@@ -462,11 +451,15 @@
       LOG(ERROR) << "Invalid signal: " << signal->ToString();
       return;
     }
-    handler.Run(static_cast<FormatError>(error_code), device_path);
+
+    for (auto& observer : observer_list_) {
+      observer.OnFormatCompleted(static_cast<FormatError>(error_code),
+                                 device_path);
+    }
   }
 
-  // Handles RenameCompleted signal and calls |handler|.
-  void OnRenameCompleted(RenameCompletedHandler handler, dbus::Signal* signal) {
+  // Handles RenameCompleted signal and notifies observers.
+  void OnRenameCompleted(dbus::Signal* signal) {
     dbus::MessageReader reader(signal);
     uint32_t error_code = 0;
     std::string device_path;
@@ -474,7 +467,11 @@
       LOG(ERROR) << "Invalid signal: " << signal->ToString();
       return;
     }
-    handler.Run(static_cast<RenameError>(error_code), device_path);
+
+    for (auto& observer : observer_list_) {
+      observer.OnRenameCompleted(static_cast<RenameError>(error_code),
+                                 device_path);
+    }
   }
 
   // Handles the result of signal connection setup.
@@ -487,6 +484,8 @@
 
   dbus::ObjectProxy* proxy_;
 
+  base::ObserverList<Observer> observer_list_;
+
   // Note: This should remain the last member so it'll be destroyed and
   // invalidate its weak pointers before any other members are destroyed.
   base::WeakPtrFactory<CrosDisksClientImpl> weak_ptr_factory_;
diff --git a/chromeos/dbus/cros_disks_client.h b/chromeos/dbus/cros_disks_client.h
index d571986..c6afed07 100644
--- a/chromeos/dbus/cros_disks_client.h
+++ b/chromeos/dbus/cros_disks_client.h
@@ -280,32 +280,35 @@
   typedef base::Callback<void(const DiskInfo& disk_info)>
       GetDevicePropertiesCallback;
 
-  // A callback to handle MountCompleted signal.
-  typedef base::Callback<void(const MountEntry& entry)> MountCompletedHandler;
+  class Observer {
+   public:
+    // Called when a mount event signal is received.
+    virtual void OnMountEvent(MountEventType event_type,
+                              const std::string& device_path) = 0;
 
-  // A callback to handle FormatCompleted signal.
-  // The first argument is the error code.
-  // The second argument is the device path.
-  typedef base::Callback<void(FormatError error_code,
-                              const std::string& device_path)>
-      FormatCompletedHandler;
+    // Called when a MountCompleted signal is received.
+    virtual void OnMountCompleted(const MountEntry& entry) = 0;
 
-  // A callback to handle RenameCompleted signal.
-  // The first argument is the error code.
-  // The second argument is the device path.
-  typedef base::Callback<void(RenameError error_code,
-                              const std::string& device_path)>
-      RenameCompletedHandler;
+    // Called when a FormatCompleted signal is received.
+    virtual void OnFormatCompleted(FormatError error_code,
+                                   const std::string& device_path) = 0;
 
-  // A callback to handle mount events.
-  // The first argument is the event type.
-  // The second argument is the device path.
-  typedef base::Callback<void(MountEventType event_type,
-                              const std::string& device_path)>
-      MountEventHandler;
+    // Called when a RenameCompleted signal is received.
+    virtual void OnRenameCompleted(RenameError error_code,
+                                   const std::string& device_path) = 0;
+
+   protected:
+    virtual ~Observer() = default;
+  };
 
   ~CrosDisksClient() override;
 
+  // Registers the given |observer| to listen D-Bus signals.
+  virtual void AddObserver(Observer* observer) = 0;
+
+  // Unregisters the |observer| from this instance.
+  virtual void RemoveObserver(Observer* observer) = 0;
+
   // Calls Mount method.  |callback| is called after the method call succeeds,
   // otherwise, |error_callback| is called.
   // When mounting an archive, caller may set two optional arguments:
@@ -367,26 +370,6 @@
                                    const GetDevicePropertiesCallback& callback,
                                    const base::Closure& error_callback) = 0;
 
-  // Registers |mount_event_handler| as a callback to be invoked when a mount
-  // event signal is received.
-  virtual void SetMountEventHandler(
-      const MountEventHandler& mount_event_handler) = 0;
-
-  // Registers |mount_completed_handler| as a callback to be invoked when a
-  // MountCompleted signal is received.
-  virtual void SetMountCompletedHandler(
-      const MountCompletedHandler& mount_completed_handler) = 0;
-
-  // Registers |format_completed_handler| as a callback to be invoked when a
-  // FormatCompleted signal is received.
-  virtual void SetFormatCompletedHandler(
-      const FormatCompletedHandler& format_completed_handler) = 0;
-
-  // Registers |rename_completed_handler| as a callback to be invoked when a
-  // RenameCompleted signal is received.
-  virtual void SetRenameCompletedHandler(
-      const RenameCompletedHandler& rename_completed_handler) = 0;
-
   // Factory function, creates a new instance and returns ownership.
   // For normal usage, access the singleton via DBusThreadManager::Get().
   static CrosDisksClient* Create(DBusClientImplementationType type);
diff --git a/chromeos/dbus/fake_cros_disks_client.cc b/chromeos/dbus/fake_cros_disks_client.cc
index 9de08922..31c205d7 100644
--- a/chromeos/dbus/fake_cros_disks_client.cc
+++ b/chromeos/dbus/fake_cros_disks_client.cc
@@ -4,6 +4,8 @@
 
 #include "chromeos/dbus/fake_cros_disks_client.h"
 
+#include <utility>
+
 #include "base/bind.h"
 #include "base/files/file_util.h"
 #include "base/location.h"
@@ -40,26 +42,6 @@
   return MOUNT_ERROR_NONE;
 }
 
-// Continuation of Mount().
-void DidMount(const CrosDisksClient::MountCompletedHandler&
-              mount_completed_handler,
-              const std::string& source_path,
-              MountType type,
-              const base::Closure& callback,
-              const base::FilePath& mounted_path,
-              MountError mount_error) {
-  // Tell the caller of Mount() that the mount request was accepted.
-  base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, callback);
-
-  // Tell the caller of Mount() that the mount completed.
-  if (!mount_completed_handler.is_null()) {
-    base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::Bind(mount_completed_handler,
-                              MountEntry(mount_error, source_path, type,
-                                         mounted_path.AsUTF8Unsafe())));
-  }
-}
-
 }  // namespace
 
 FakeCrosDisksClient::FakeCrosDisksClient()
@@ -68,13 +50,22 @@
       format_call_count_(0),
       format_success_(true),
       rename_call_count_(0),
-      rename_success_(true) {}
+      rename_success_(true),
+      weak_ptr_factory_(this) {}
 
 FakeCrosDisksClient::~FakeCrosDisksClient() = default;
 
 void FakeCrosDisksClient::Init(dbus::Bus* bus) {
 }
 
+void FakeCrosDisksClient::AddObserver(Observer* observer) {
+  observer_list_.AddObserver(observer);
+}
+
+void FakeCrosDisksClient::RemoveObserver(Observer* observer) {
+  observer_list_.RemoveObserver(observer);
+}
+
 void FakeCrosDisksClient::Mount(const std::string& source_path,
                                 const std::string& source_format,
                                 const std::string& mount_label,
@@ -85,7 +76,7 @@
   // This fake implementation assumes mounted path is device when source_format
   // is empty, or an archive otherwise.
   MountType type =
-      (source_format == "") ? MOUNT_TYPE_DEVICE : MOUNT_TYPE_ARCHIVE;
+      source_format.empty() ? MOUNT_TYPE_DEVICE : MOUNT_TYPE_ARCHIVE;
 
   base::FilePath mounted_path;
   switch (type) {
@@ -98,7 +89,7 @@
           base::FilePath::FromUTF8Unsafe(mount_label));
       break;
     case MOUNT_TYPE_INVALID:
-      // Unreachable
+      NOTREACHED();
       return;
   }
   mounted_paths_.insert(mounted_path);
@@ -106,9 +97,23 @@
   base::PostTaskWithTraitsAndReplyWithResult(
       FROM_HERE,
       {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
-      base::Bind(&PerformFakeMount, source_path, mounted_path),
-      base::Bind(&DidMount, mount_completed_handler_, source_path, type,
-                 callback, mounted_path));
+      base::BindOnce(&PerformFakeMount, source_path, mounted_path),
+      base::BindOnce(&FakeCrosDisksClient::DidMount,
+                     weak_ptr_factory_.GetWeakPtr(), source_path, type,
+                     callback, mounted_path));
+}
+
+void FakeCrosDisksClient::DidMount(const std::string& source_path,
+                                   MountType type,
+                                   base::OnceClosure callback,
+                                   const base::FilePath& mounted_path,
+                                   MountError mount_error) {
+  // Tell the caller of Mount() that the mount request was accepted.
+  std::move(callback).Run();
+
+  // Notify observers that the mount is completed.
+  NotifyMountCompleted(mount_error, source_path, type,
+                       mounted_path.AsUTF8Unsafe());
 }
 
 void FakeCrosDisksClient::Unmount(const std::string& device_path,
@@ -193,62 +198,28 @@
     const base::Closure& error_callback) {
 }
 
-void FakeCrosDisksClient::SetMountEventHandler(
-    const MountEventHandler& mount_event_handler) {
-  mount_event_handler_ = mount_event_handler;
+void FakeCrosDisksClient::NotifyMountCompleted(MountError error_code,
+                                               const std::string& source_path,
+                                               MountType mount_type,
+                                               const std::string& mount_path) {
+  for (auto& observer : observer_list_) {
+    observer.OnMountCompleted(
+        MountEntry(error_code, source_path, mount_type, mount_path));
+  }
 }
 
-void FakeCrosDisksClient::SetMountCompletedHandler(
-    const MountCompletedHandler& mount_completed_handler) {
-  mount_completed_handler_ = mount_completed_handler;
-}
-
-void FakeCrosDisksClient::SetFormatCompletedHandler(
-    const FormatCompletedHandler& format_completed_handler) {
-  format_completed_handler_ = format_completed_handler;
-}
-
-void FakeCrosDisksClient::SetRenameCompletedHandler(
-    const RenameCompletedHandler& rename_completed_handler) {
-  rename_completed_handler_ = rename_completed_handler;
-}
-
-bool FakeCrosDisksClient::SendMountEvent(MountEventType event,
-                                         const std::string& path) {
-  if (mount_event_handler_.is_null())
-    return false;
-  mount_event_handler_.Run(event, path);
-  return true;
-}
-
-bool FakeCrosDisksClient::SendMountCompletedEvent(
-    MountError error_code,
-    const std::string& source_path,
-    MountType mount_type,
-    const std::string& mount_path) {
-  if (mount_completed_handler_.is_null())
-    return false;
-  mount_completed_handler_.Run(
-      MountEntry(error_code, source_path, mount_type, mount_path));
-  return true;
-}
-
-bool FakeCrosDisksClient::SendFormatCompletedEvent(
+void FakeCrosDisksClient::NotifyFormatCompleted(
     FormatError error_code,
     const std::string& device_path) {
-  if (format_completed_handler_.is_null())
-    return false;
-  format_completed_handler_.Run(error_code, device_path);
-  return true;
+  for (auto& observer : observer_list_)
+    observer.OnFormatCompleted(error_code, device_path);
 }
 
-bool FakeCrosDisksClient::SendRenameCompletedEvent(
+void FakeCrosDisksClient::NotifyRenameCompleted(
     RenameError error_code,
     const std::string& device_path) {
-  if (rename_completed_handler_.is_null())
-    return false;
-  rename_completed_handler_.Run(error_code, device_path);
-  return true;
+  for (auto& observer : observer_list_)
+    observer.OnRenameCompleted(error_code, device_path);
 }
 
 }  // namespace chromeos
diff --git a/chromeos/dbus/fake_cros_disks_client.h b/chromeos/dbus/fake_cros_disks_client.h
index 495d97f..c9d2a88 100644
--- a/chromeos/dbus/fake_cros_disks_client.h
+++ b/chromeos/dbus/fake_cros_disks_client.h
@@ -10,6 +10,9 @@
 
 #include "base/callback.h"
 #include "base/files/file_path.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/observer_list.h"
 #include "chromeos/dbus/cros_disks_client.h"
 
 namespace chromeos {
@@ -23,6 +26,8 @@
 
   // CrosDisksClient overrides
   void Init(dbus::Bus* bus) override;
+  void AddObserver(Observer* observer) override;
+  void RemoveObserver(Observer* observer) override;
 
   // Performs fake mounting for archive files. Instead of actually extracting
   // contents of archive files, this function creates a directory that
@@ -58,27 +63,17 @@
   void GetDeviceProperties(const std::string& device_path,
                            const GetDevicePropertiesCallback& callback,
                            const base::Closure& error_callback) override;
-  void SetMountEventHandler(
-      const MountEventHandler& mount_event_handler) override;
-  void SetMountCompletedHandler(
-      const MountCompletedHandler& mount_completed_handler) override;
-  void SetFormatCompletedHandler(
-      const FormatCompletedHandler& format_completed_handler) override;
-  void SetRenameCompletedHandler(
-      const RenameCompletedHandler& rename_completed_handler) override;
 
   // Used in tests to simulate signals sent by cros disks layer.
-  // Invokes handlers set in |SetMountEventHandler|, |SetMountCompletedHandler|,
-  // and |SetFormatCompletedHandler|.
-  bool SendMountEvent(MountEventType event, const std::string& path);
-  bool SendMountCompletedEvent(MountError error_code,
-                               const std::string& source_path,
-                               MountType mount_type,
-                               const std::string& mount_path);
-  bool SendFormatCompletedEvent(FormatError error_code,
-                                const std::string& device_path);
-  bool SendRenameCompletedEvent(RenameError error_code,
-                                const std::string& device_path);
+  // Calls corresponding methods of the registered observers.
+  void NotifyMountCompleted(MountError error_code,
+                            const std::string& source_path,
+                            MountType mount_type,
+                            const std::string& mount_path);
+  void NotifyFormatCompleted(FormatError error_code,
+                             const std::string& device_path);
+  void NotifyRenameCompleted(RenameError error_code,
+                             const std::string& device_path);
 
   // Returns how many times Unmount() was called.
   int unmount_call_count() const {
@@ -143,11 +138,14 @@
   void MakeRenameFail() { rename_success_ = false; }
 
  private:
-  MountEventHandler mount_event_handler_;
-  MountCompletedHandler mount_completed_handler_;
-  FormatCompletedHandler format_completed_handler_;
-  RenameCompletedHandler rename_completed_handler_;
+  // Continuation of Mount().
+  void DidMount(const std::string& source_path,
+                MountType type,
+                base::OnceClosure callback,
+                const base::FilePath& mounted_path,
+                MountError mount_error);
 
+  base::ObserverList<Observer> observer_list_;
   int unmount_call_count_;
   std::string last_unmount_device_path_;
   UnmountOptions last_unmount_options_;
@@ -162,6 +160,10 @@
   std::string last_rename_volume_name_;
   bool rename_success_;
   std::set<base::FilePath> mounted_paths_;
+
+  base::WeakPtrFactory<FakeCrosDisksClient> weak_ptr_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(FakeCrosDisksClient);
 };
 
 }  // namespace chromeos
diff --git a/chromeos/disks/disk_mount_manager.cc b/chromeos/disks/disk_mount_manager.cc
index cc18683..ad80c3be 100644
--- a/chromeos/disks/disk_mount_manager.cc
+++ b/chromeos/disks/disk_mount_manager.cc
@@ -10,6 +10,8 @@
 #include <map>
 #include <set>
 #include <string>
+#include <utility>
+#include <vector>
 
 #include "base/bind.h"
 #include "base/macros.h"
@@ -17,6 +19,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
 #include "base/strings/string_util.h"
+#include "chromeos/dbus/cros_disks_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/disks/suspend_unmount_manager.h"
 
@@ -32,7 +35,8 @@
 DiskMountManager* g_disk_mount_manager = NULL;
 
 // The DiskMountManager implementation.
-class DiskMountManagerImpl : public DiskMountManager {
+class DiskMountManagerImpl : public DiskMountManager,
+                             public CrosDisksClient::Observer {
  public:
   DiskMountManagerImpl() :
     already_refreshed_(false),
@@ -43,29 +47,18 @@
         dbus_thread_manager->GetPowerManagerClient();
     suspend_unmount_manager_.reset(
         new SuspendUnmountManager(this, power_manager_client));
-    cros_disks_client_->SetMountEventHandler(
-        base::Bind(&DiskMountManagerImpl::OnMountEvent,
-                   weak_ptr_factory_.GetWeakPtr()));
-    cros_disks_client_->SetMountCompletedHandler(
-        base::Bind(&DiskMountManagerImpl::OnMountCompleted,
-                   weak_ptr_factory_.GetWeakPtr()));
-    cros_disks_client_->SetFormatCompletedHandler(
-        base::Bind(&DiskMountManagerImpl::OnFormatCompleted,
-                   weak_ptr_factory_.GetWeakPtr()));
-    cros_disks_client_->SetRenameCompletedHandler(
-        base::Bind(&DiskMountManagerImpl::OnRenameCompleted,
-                   weak_ptr_factory_.GetWeakPtr()));
+    cros_disks_client_->AddObserver(this);
   }
 
-  ~DiskMountManagerImpl() override = default;
+  ~DiskMountManagerImpl() override { cros_disks_client_->RemoveObserver(this); }
 
   // DiskMountManager override.
-  void AddObserver(Observer* observer) override {
+  void AddObserver(DiskMountManager::Observer* observer) override {
     observers_.AddObserver(observer);
   }
 
   // DiskMountManager override.
-  void RemoveObserver(Observer* observer) override {
+  void RemoveObserver(DiskMountManager::Observer* observer) override {
     observers_.RemoveObserver(observer);
   }
 
@@ -425,8 +418,8 @@
     }
   }
 
-  // Callback to handle MountCompleted signal and Mount method call failure.
-  void OnMountCompleted(const MountEntry& entry) {
+  // CrosDisksClient::Observer override.
+  void OnMountCompleted(const MountEntry& entry) override {
     MountCondition mount_condition = MOUNT_CONDITION_NONE;
     if (entry.mount_type() == MOUNT_TYPE_DEVICE) {
       if (entry.error_code() == MOUNT_ERROR_UNKNOWN_FILESYSTEM) {
@@ -547,9 +540,9 @@
     NotifyFormatStatusUpdate(FORMAT_STARTED, FORMAT_ERROR_NONE, device_path);
   }
 
-  // Callback to handle FormatCompleted signal and Format method call failure.
+  // CrosDisksClient::Observer override.
   void OnFormatCompleted(FormatError error_code,
-                         const std::string& device_path) {
+                         const std::string& device_path) override {
     auto iter = disks_.find(device_path);
 
     // disk might have been removed by now?
@@ -603,9 +596,9 @@
     NotifyRenameStatusUpdate(RENAME_STARTED, RENAME_ERROR_NONE, device_path);
   }
 
-  // Callback to handle RenameCompleted signal and Rename method call failure.
+  // CrosDisksClient::Observer override.
   void OnRenameCompleted(RenameError error_code,
-                         const std::string& device_path) {
+                         const std::string& device_path) override {
     auto iter = disks_.find(device_path);
 
     // disk might have been removed by now?
@@ -724,8 +717,9 @@
     refresh_callbacks_.clear();
   }
 
-  // Callback to handle mount event signals.
-  void OnMountEvent(MountEventType event, const std::string& device_path_arg) {
+  // CrosDisksClient::Observer override.
+  void OnMountEvent(MountEventType event,
+                    const std::string& device_path_arg) override {
     // Take a copy of the argument so we can modify it below.
     std::string device_path = device_path_arg;
     switch (event) {
@@ -819,7 +813,7 @@
   }
 
   // Mount event change observers.
-  base::ObserverList<Observer> observers_;
+  base::ObserverList<DiskMountManager::Observer> observers_;
 
   CrosDisksClient* cros_disks_client_;
 
@@ -913,7 +907,7 @@
   // Only the second condition is checked here, because Disks are created from
   // non-virtual mount devices only.
   return !on_boot_device_;
-};
+}
 
 bool DiskMountManager::Disk::IsStatefulPartition() const {
   return mount_path_ == kStatefulPartition;
diff --git a/chromeos/disks/disk_mount_manager_unittest.cc b/chromeos/disks/disk_mount_manager_unittest.cc
index 7d4fad3..da0da33 100644
--- a/chromeos/disks/disk_mount_manager_unittest.cc
+++ b/chromeos/disks/disk_mount_manager_unittest.cc
@@ -6,6 +6,9 @@
 #include <stdint.h>
 
 #include <memory>
+#include <string>
+#include <utility>
+#include <vector>
 
 #include "base/bind.h"
 #include "base/run_loop.h"
@@ -793,8 +796,8 @@
   // Send failing FORMAT_COMPLETED signal.
   // The failure is marked by ! in fromt of the path (but this should change
   // soon).
-  fake_cros_disks_client_->SendFormatCompletedEvent(
-      chromeos::FORMAT_ERROR_UNKNOWN, kDevice1SourcePath);
+  fake_cros_disks_client_->NotifyFormatCompleted(chromeos::FORMAT_ERROR_UNKNOWN,
+                                                 kDevice1SourcePath);
 
   // The observer should get notified that the device was unmounted and that
   // formatting has started.
@@ -840,8 +843,8 @@
   EXPECT_FALSE(HasMountPoint(kDevice1MountPath));
 
   // Simulate cros_disks reporting success.
-  fake_cros_disks_client_->SendFormatCompletedEvent(chromeos::FORMAT_ERROR_NONE,
-                                                    kDevice1SourcePath);
+  fake_cros_disks_client_->NotifyFormatCompleted(chromeos::FORMAT_ERROR_NONE,
+                                                 kDevice1SourcePath);
 
   // The observer should receive UNMOUNTING, FORMAT_STARTED and FORMAT_COMPLETED
   // events (all of them without an error set).
@@ -886,11 +889,11 @@
   EXPECT_FALSE(HasMountPoint(kDevice1MountPath));
 
   // Simulate cros_disks reporting success.
-  fake_cros_disks_client_->SendFormatCompletedEvent(chromeos::FORMAT_ERROR_NONE,
-                                                    kDevice1SourcePath);
+  fake_cros_disks_client_->NotifyFormatCompleted(chromeos::FORMAT_ERROR_NONE,
+                                                 kDevice1SourcePath);
 
   // Simulate the device remounting.
-  fake_cros_disks_client_->SendMountCompletedEvent(
+  fake_cros_disks_client_->NotifyMountCompleted(
       chromeos::MOUNT_ERROR_NONE, kDevice1SourcePath,
       chromeos::MOUNT_TYPE_DEVICE, kDevice1MountPath);
 
@@ -913,8 +916,8 @@
   EXPECT_EQ("vfat", fake_cros_disks_client_->last_format_filesystem());
 
   // Simulate cros_disks reporting success.
-  fake_cros_disks_client_->SendFormatCompletedEvent(chromeos::FORMAT_ERROR_NONE,
-                                                    kDevice1SourcePath);
+  fake_cros_disks_client_->NotifyFormatCompleted(chromeos::FORMAT_ERROR_NONE,
+                                                 kDevice1SourcePath);
 
   // The observer should receive UNMOUNTING, FORMAT_STARTED and FORMAT_COMPLETED
   // events (all of them without an error set) twice (once for each formatting
@@ -957,10 +960,10 @@
                      chromeos::MOUNT_TYPE_DEVICE,
                      chromeos::MOUNT_ACCESS_MODE_READ_ONLY);
   // Simulate cros_disks reporting mount completed.
-  fake_cros_disks_client_->SendMountCompletedEvent(
+  fake_cros_disks_client_->NotifyMountCompleted(
       chromeos::MOUNT_ERROR_NONE, kSourcePath1, chromeos::MOUNT_TYPE_DEVICE,
       kMountPath1);
-  fake_cros_disks_client_->SendMountCompletedEvent(
+  fake_cros_disks_client_->NotifyMountCompleted(
       chromeos::MOUNT_ERROR_NONE, kSourcePath2, chromeos::MOUNT_TYPE_DEVICE,
       kMountPath2);
 
@@ -999,7 +1002,7 @@
                      chromeos::MOUNT_TYPE_DEVICE,
                      chromeos::MOUNT_ACCESS_MODE_READ_WRITE);
   // Simulate cros_disks reporting mount completed.
-  fake_cros_disks_client_->SendMountCompletedEvent(
+  fake_cros_disks_client_->NotifyMountCompleted(
       chromeos::MOUNT_ERROR_NONE, kReadOnlyDeviceSourcePath,
       chromeos::MOUNT_TYPE_DEVICE, kReadOnlyDeviceMountPath);
 
@@ -1022,7 +1025,7 @@
   manager->RemountAllRemovableDrives(chromeos::MOUNT_ACCESS_MODE_READ_ONLY);
 
   // Simulate cros_disks reporting mount completed.
-  fake_cros_disks_client_->SendMountCompletedEvent(
+  fake_cros_disks_client_->NotifyMountCompleted(
       chromeos::MOUNT_ERROR_NONE, kDevice1SourcePath,
       chromeos::MOUNT_TYPE_DEVICE, kDevice1MountPath);
 
@@ -1040,7 +1043,7 @@
   manager->RemountAllRemovableDrives(chromeos::MOUNT_ACCESS_MODE_READ_WRITE);
 
   // Simulate cros_disks reporting mount completed.
-  fake_cros_disks_client_->SendMountCompletedEvent(
+  fake_cros_disks_client_->NotifyMountCompleted(
       chromeos::MOUNT_ERROR_NONE, kDevice1SourcePath,
       chromeos::MOUNT_TYPE_DEVICE, kDevice1MountPath);
   // Event handlers of observers should be called.
@@ -1246,8 +1249,8 @@
   // Send failing RENAME_COMPLETED signal.
   // The failure is marked by ! in fromt of the path (but this should change
   // soon).
-  fake_cros_disks_client_->SendRenameCompletedEvent(
-      chromeos::RENAME_ERROR_UNKNOWN, kDevice1SourcePath);
+  fake_cros_disks_client_->NotifyRenameCompleted(chromeos::RENAME_ERROR_UNKNOWN,
+                                                 kDevice1SourcePath);
 
   // The observer should get notified that the device was unmounted and that
   // renaming has started.
@@ -1293,8 +1296,8 @@
   EXPECT_FALSE(HasMountPoint(kDevice1MountPath));
 
   // Simulate cros_disks reporting success.
-  fake_cros_disks_client_->SendRenameCompletedEvent(chromeos::RENAME_ERROR_NONE,
-                                                    kDevice1SourcePath);
+  fake_cros_disks_client_->NotifyRenameCompleted(chromeos::RENAME_ERROR_NONE,
+                                                 kDevice1SourcePath);
 
   // The observer should receive UNMOUNTING, RENAME_STARTED and RENAME_COMPLETED
   // events (all of them without an error set).
@@ -1342,11 +1345,11 @@
   EXPECT_FALSE(HasMountPoint(kDevice1MountPath));
 
   // Simulate cros_disks reporting success.
-  fake_cros_disks_client_->SendRenameCompletedEvent(chromeos::RENAME_ERROR_NONE,
-                                                    kDevice1SourcePath);
+  fake_cros_disks_client_->NotifyRenameCompleted(chromeos::RENAME_ERROR_NONE,
+                                                 kDevice1SourcePath);
 
   // Simulate the device remounting.
-  fake_cros_disks_client_->SendMountCompletedEvent(
+  fake_cros_disks_client_->NotifyMountCompleted(
       chromeos::MOUNT_ERROR_NONE, kDevice1SourcePath,
       chromeos::MOUNT_TYPE_DEVICE, kDevice1MountPath);
 
@@ -1374,8 +1377,8 @@
             disks.find(kDevice1SourcePath)->second->base_mount_path());
 
   // Simulate cros_disks reporting success.
-  fake_cros_disks_client_->SendRenameCompletedEvent(chromeos::RENAME_ERROR_NONE,
-                                                    kDevice1SourcePath);
+  fake_cros_disks_client_->NotifyRenameCompleted(chromeos::RENAME_ERROR_NONE,
+                                                 kDevice1SourcePath);
 
   // The observer should receive UNMOUNTING, RENAME_STARTED and RENAME_COMPLETED
   // events (all of them without an error set) twice (once for each renaming
diff --git a/components/autofill/android/autofill_provider_android.cc b/components/autofill/android/autofill_provider_android.cc
index 88c8ae11..ca83aaa 100644
--- a/components/autofill/android/autofill_provider_android.cc
+++ b/components/autofill/android/autofill_provider_android.cc
@@ -122,6 +122,29 @@
       transformed_bounding.width(), transformed_bounding.height());
 }
 
+void AutofillProviderAndroid::OnTextFieldDidScroll(
+    AutofillHandlerProxy* handler,
+    const FormData& form,
+    const FormFieldData& field,
+    const gfx::RectF& bounding_box) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  size_t index;
+  if (!IsCurrentlyLinkedHandler(handler) || !IsCurrentlyLinkedForm(form) ||
+      !form_->GetSimilarFieldIndex(field, &index))
+    return;
+
+  form_->OnTextFieldDidChange(index, field.value);
+  JNIEnv* env = AttachCurrentThread();
+  ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
+  if (obj.is_null())
+    return;
+
+  gfx::RectF transformed_bounding = ToClientAreaBound(bounding_box);
+  Java_AutofillProvider_onTextFieldDidScroll(
+      env, obj, index, transformed_bounding.x(), transformed_bounding.y(),
+      transformed_bounding.width(), transformed_bounding.height());
+}
+
 bool AutofillProviderAndroid::OnWillSubmitForm(
     AutofillHandlerProxy* handler,
     const FormData& form,
diff --git a/components/autofill/android/autofill_provider_android.h b/components/autofill/android/autofill_provider_android.h
index 9ab0a897..463aa1b 100644
--- a/components/autofill/android/autofill_provider_android.h
+++ b/components/autofill/android/autofill_provider_android.h
@@ -36,6 +36,10 @@
                             const FormFieldData& field,
                             const gfx::RectF& bounding_box,
                             const base::TimeTicks timestamp) override;
+  void OnTextFieldDidScroll(AutofillHandlerProxy* handler,
+                            const FormData& form,
+                            const FormFieldData& field,
+                            const gfx::RectF& bounding_box) override;
   bool OnWillSubmitForm(AutofillHandlerProxy* handler,
                         const FormData& form,
                         const base::TimeTicks timestamp) override;
diff --git a/components/autofill/android/java/src/org/chromium/components/autofill/AutofillProvider.java b/components/autofill/android/java/src/org/chromium/components/autofill/AutofillProvider.java
index e79d4b0..b2d96b4 100644
--- a/components/autofill/android/java/src/org/chromium/components/autofill/AutofillProvider.java
+++ b/components/autofill/android/java/src/org/chromium/components/autofill/AutofillProvider.java
@@ -76,7 +76,7 @@
             FormData formData, int focus, float x, float y, float width, float height);
 
     /**
-     * Invoked when text field is changed.
+     * Invoked when text field's value is changed.
      *
      * @param index index of field in current form.
      * @param x the boundary of focus field.
@@ -90,6 +90,20 @@
             int index, float x, float y, float width, float height);
 
     /**
+     * Invoked when text field is scrolled.
+     *
+     * @param index index of field in current form.
+     * @param x the boundary of focus field.
+     * @param y the boundary of focus field.
+     * @param width the boundary of focus field.
+     * @param height the boundary of focus field.
+     *
+     */
+    @CalledByNative
+    protected abstract void onTextFieldDidScroll(
+            int index, float x, float y, float width, float height);
+
+    /**
      * Invoked when current form will be submitted.
      *
      */
diff --git a/components/autofill/content/browser/content_autofill_driver.cc b/components/autofill/content/browser/content_autofill_driver.cc
index 0cf792b..e7ce3745 100644
--- a/components/autofill/content/browser/content_autofill_driver.cc
+++ b/components/autofill/content/browser/content_autofill_driver.cc
@@ -45,6 +45,7 @@
     autofill_handler_ = base::MakeUnique<AutofillHandlerProxy>(this, provider);
     GetAutofillAgent()->SetUserGestureRequired(false);
     GetAutofillAgent()->SetSecureContextRequired(true);
+    GetAutofillAgent()->SetFocusRequiresScroll(false);
   } else {
     autofill_handler_ = base::MakeUnique<AutofillManager>(
         this, client, app_locale, enable_download_manager);
@@ -206,6 +207,12 @@
   autofill_handler_->OnTextFieldDidChange(form, field, bounding_box, timestamp);
 }
 
+void ContentAutofillDriver::TextFieldDidScroll(const FormData& form,
+                                               const FormFieldData& field,
+                                               const gfx::RectF& bounding_box) {
+  autofill_handler_->OnTextFieldDidScroll(form, field, bounding_box);
+}
+
 void ContentAutofillDriver::QueryFormFieldAutofill(
     int32_t id,
     const FormData& form,
diff --git a/components/autofill/content/browser/content_autofill_driver.h b/components/autofill/content/browser/content_autofill_driver.h
index 61684b5..624f87bb1 100644
--- a/components/autofill/content/browser/content_autofill_driver.h
+++ b/components/autofill/content/browser/content_autofill_driver.h
@@ -80,6 +80,9 @@
                           const FormFieldData& field,
                           const gfx::RectF& bounding_box,
                           base::TimeTicks timestamp) override;
+  void TextFieldDidScroll(const FormData& form,
+                          const FormFieldData& field,
+                          const gfx::RectF& bounding_box) override;
   void QueryFormFieldAutofill(int32_t id,
                               const FormData& form,
                               const FormFieldData& field,
diff --git a/components/autofill/content/browser/content_autofill_driver_unittest.cc b/components/autofill/content/browser/content_autofill_driver_unittest.cc
index 2bb5a3b..52af5253 100644
--- a/components/autofill/content/browser/content_autofill_driver_unittest.cc
+++ b/components/autofill/content/browser/content_autofill_driver_unittest.cc
@@ -206,6 +206,8 @@
 
   void SetSecureContextRequired(bool required) override {}
 
+  void SetFocusRequiresScroll(bool require) override {}
+
   mojo::BindingSet<mojom::AutofillAgent> bindings_;
 
   base::Closure quit_closure_;
diff --git a/components/autofill/content/common/autofill_agent.mojom b/components/autofill/content/common/autofill_agent.mojom
index df5e5a2..8e41cdc 100644
--- a/components/autofill/content/common/autofill_agent.mojom
+++ b/components/autofill/content/common/autofill_agent.mojom
@@ -64,6 +64,9 @@
   // Configures the render to require, or not, the secure context to query
   // autofill suggestion, the default is false.
   SetSecureContextRequired(bool required);
+
+  // Configures whether scroll is required in order to complete focus. The default is true.
+  SetFocusRequiresScroll(bool require);
 };
 
 // There is one instance of this interface per render frame in the render
diff --git a/components/autofill/content/common/autofill_driver.mojom b/components/autofill/content/common/autofill_driver.mojom
index f04cf1af13a..e3a18f08 100644
--- a/components/autofill/content/common/autofill_driver.mojom
+++ b/components/autofill/content/common/autofill_driver.mojom
@@ -30,6 +30,11 @@
                      gfx.mojom.RectF bounding_box,
                      mojo.common.mojom.TimeTicks timestamp);
 
+  // Notification that a form field has scrolled.
+  TextFieldDidScroll(FormData form,
+                     FormFieldData field,
+                     gfx.mojom.RectF bounding_box);
+
   // Queries the browser for Autofill suggestions for a form input field.
   // |id| is the request ID which is used to map responses correctly.
   QueryFormFieldAutofill(int32 id,
@@ -77,13 +82,13 @@
 
   // Notification that this password form was submitted by the user.
   PasswordFormSubmitted(PasswordForm password_form);
-  
+
   // Notification that a user starts typing in password fields and the omnibox
   // icon with anchored save/update prompt should be available.
   ShowManualFallbackForSaving(PasswordForm password_form);
-  
-  // Notification that there is no user input in password fields and the 
-  // save/update prompt anchored to the omnibox icon should be removed. 
+
+  // Notification that there is no user input in password fields and the
+  // save/update prompt anchored to the omnibox icon should be removed.
   HideManualFallbackForSaving();
 
   // Notification that in-page navigation happened and at this moment we have
diff --git a/components/autofill/content/renderer/autofill_agent.cc b/components/autofill/content/renderer/autofill_agent.cc
index 5168ecf..8712c83f 100644
--- a/components/autofill/content/renderer/autofill_agent.cc
+++ b/components/autofill/content/renderer/autofill_agent.cc
@@ -211,6 +211,18 @@
 }
 
 void AutofillAgent::DidChangeScrollOffset() {
+  if (!focus_requires_scroll_ && is_popup_possibly_visible_ &&
+      element_.Focused()) {
+    FormData form;
+    FormFieldData field;
+    if (form_util::FindFormAndFieldForFormControlElement(element_, &form,
+                                                         &field)) {
+      GetAutofillDriver()->TextFieldDidScroll(
+          form, field,
+          render_frame()->GetRenderView()->ElementBoundsInWindow(element_));
+    }
+  }
+
   if (IsKeyboardAccessoryEnabled())
     return;
 
@@ -220,7 +232,7 @@
 void AutofillAgent::FocusedNodeChanged(const WebNode& node) {
   was_focused_before_now_ = false;
 
-  if (IsKeyboardAccessoryEnabled() &&
+  if ((IsKeyboardAccessoryEnabled() || !focus_requires_scroll_) &&
       WebUserGestureIndicator::IsProcessingUserGesture(
           node.IsNull() ? nullptr : node.GetDocument().GetFrame())) {
     focused_node_was_last_clicked_ = true;
@@ -593,6 +605,10 @@
   is_secure_context_required_ = required;
 }
 
+void AutofillAgent::SetFocusRequiresScroll(bool require) {
+  focus_requires_scroll_ = require;
+}
+
 void AutofillAgent::QueryAutofillSuggestions(
     const WebFormControlElement& element) {
   if (!element.GetDocument().GetFrame())
@@ -711,7 +727,7 @@
   if (!focused_element.IsNull() && password_autofill_agent_)
     password_autofill_agent_->FocusedNodeHasChanged(focused_element);
 
-  if (!IsKeyboardAccessoryEnabled())
+  if (!IsKeyboardAccessoryEnabled() && focus_requires_scroll_)
     HandleFocusChangeComplete();
 }
 
@@ -720,7 +736,7 @@
   DCHECK(!node.IsNull());
   focused_node_was_last_clicked_ = node.Focused();
 
-  if (IsKeyboardAccessoryEnabled())
+  if (IsKeyboardAccessoryEnabled() || !focus_requires_scroll_)
     HandleFocusChangeComplete();
 }
 
diff --git a/components/autofill/content/renderer/autofill_agent.h b/components/autofill/content/renderer/autofill_agent.h
index 44810de..d5a6a9a 100644
--- a/components/autofill/content/renderer/autofill_agent.h
+++ b/components/autofill/content/renderer/autofill_agent.h
@@ -84,6 +84,7 @@
       const PasswordFormFillData& form_data) override;
   void SetUserGestureRequired(bool required) override;
   void SetSecureContextRequired(bool required) override;
+  void SetFocusRequiresScroll(bool require) override;
 
   void ShowNotSecureWarning(const blink::WebInputElement& element);
 
@@ -307,6 +308,9 @@
 
   FormTracker form_tracker_;
 
+  // Whether or not we delay focus handling until scrolling occurs.
+  bool focus_requires_scroll_ = true;
+
   mojo::Binding<mojom::AutofillAgent> binding_;
 
   mojom::AutofillDriverPtr autofill_driver_;
diff --git a/components/autofill/core/browser/autofill_handler.cc b/components/autofill/core/browser/autofill_handler.cc
index 7c1424b..a099eb8d 100644
--- a/components/autofill/core/browser/autofill_handler.cc
+++ b/components/autofill/core/browser/autofill_handler.cc
@@ -36,6 +36,18 @@
   OnTextFieldDidChangeImpl(form, field, transformed_box, timestamp);
 }
 
+void AutofillHandler::OnTextFieldDidScroll(const FormData& form,
+                                           const FormFieldData& field,
+                                           const gfx::RectF& bounding_box) {
+  if (!IsValidFormData(form) || !IsValidFormFieldData(field))
+    return;
+
+  gfx::RectF transformed_box =
+      driver_->TransformBoundingBoxToViewportCoordinates(bounding_box);
+
+  OnTextFieldDidScrollImpl(form, field, transformed_box);
+}
+
 void AutofillHandler::OnQueryFormFieldAutofill(int query_id,
                                                const FormData& form,
                                                const FormFieldData& field,
diff --git a/components/autofill/core/browser/autofill_handler.h b/components/autofill/core/browser/autofill_handler.h
index d8f7b67..e8bdf42 100644
--- a/components/autofill/core/browser/autofill_handler.h
+++ b/components/autofill/core/browser/autofill_handler.h
@@ -40,6 +40,11 @@
                             const gfx::RectF& bounding_box,
                             const base::TimeTicks timestamp);
 
+  // Invoked when the textfield is scrolled.
+  void OnTextFieldDidScroll(const FormData& form,
+                            const FormFieldData& field,
+                            const gfx::RectF& bounding_box);
+
   // Invoked when the |form| needs to be autofilled, the |bounding_box| is
   // a window relative value of |field|.
   void OnQueryFormFieldAutofill(int query_id,
@@ -113,6 +118,10 @@
                                         const gfx::RectF& bounding_box,
                                         const base::TimeTicks timestamp) = 0;
 
+  virtual void OnTextFieldDidScrollImpl(const FormData& form,
+                                        const FormFieldData& field,
+                                        const gfx::RectF& bounding_box) = 0;
+
   virtual void OnQueryFormFieldAutofillImpl(int query_id,
                                             const FormData& form,
                                             const FormFieldData& field,
diff --git a/components/autofill/core/browser/autofill_handler_proxy.cc b/components/autofill/core/browser/autofill_handler_proxy.cc
index c36d839..fd223daa 100644
--- a/components/autofill/core/browser/autofill_handler_proxy.cc
+++ b/components/autofill/core/browser/autofill_handler_proxy.cc
@@ -29,6 +29,13 @@
   provider_->OnTextFieldDidChange(this, form, field, bounding_box, timestamp);
 }
 
+void AutofillHandlerProxy::OnTextFieldDidScrollImpl(
+    const FormData& form,
+    const FormFieldData& field,
+    const gfx::RectF& bounding_box) {
+  provider_->OnTextFieldDidScroll(this, form, field, bounding_box);
+}
+
 void AutofillHandlerProxy::OnQueryFormFieldAutofillImpl(
     int query_id,
     const FormData& form,
diff --git a/components/autofill/core/browser/autofill_handler_proxy.h b/components/autofill/core/browser/autofill_handler_proxy.h
index 00ea955..0a3a039 100644
--- a/components/autofill/core/browser/autofill_handler_proxy.h
+++ b/components/autofill/core/browser/autofill_handler_proxy.h
@@ -50,6 +50,10 @@
                                 const gfx::RectF& bounding_box,
                                 const base::TimeTicks timestamp) override;
 
+  void OnTextFieldDidScrollImpl(const FormData& form,
+                                const FormFieldData& field,
+                                const gfx::RectF& bounding_box) override;
+
   void OnQueryFormFieldAutofillImpl(int query_id,
                                     const FormData& form,
                                     const FormFieldData& field,
diff --git a/components/autofill/core/browser/autofill_manager.h b/components/autofill/core/browser/autofill_manager.h
index 36882ea5..3f71fb7 100644
--- a/components/autofill/core/browser/autofill_manager.h
+++ b/components/autofill/core/browser/autofill_manager.h
@@ -244,6 +244,9 @@
                                 const FormFieldData& field,
                                 const gfx::RectF& bounding_box,
                                 const base::TimeTicks timestamp) override;
+  void OnTextFieldDidScrollImpl(const FormData& form,
+                                const FormFieldData& field,
+                                const gfx::RectF& bounding_box) override {}
   void OnQueryFormFieldAutofillImpl(int query_id,
                                     const FormData& form,
                                     const FormFieldData& field,
diff --git a/components/autofill/core/browser/autofill_metrics_unittest.cc b/components/autofill/core/browser/autofill_metrics_unittest.cc
index b9ef7914..0ca1183 100644
--- a/components/autofill/core/browser/autofill_metrics_unittest.cc
+++ b/components/autofill/core/browser/autofill_metrics_unittest.cc
@@ -756,6 +756,7 @@
     switch (type) {
       case EMPTY_TYPE:
         return "";
+      case NO_SERVER_DATA:
       case UNKNOWN_TYPE:
         return "unknown";
       case COMPANY_NAME:
@@ -803,6 +804,18 @@
   bool IsExampleOf(AutofillMetrics::FieldTypeQualityMetric metric,
                    ServerFieldType predicted_type,
                    ServerFieldType actual_type) {
+    // The server can send either NO_SERVER_DATA or UNKNOWN_TYPE to indicate
+    // that a field is not autofillable:
+    //
+    //   NO_SERVER_DATA
+    //     => A type cannot be determined based on available data.
+    //   UNKNOWN_TYPE
+    //     => field is believed to not have an autofill type.
+    //
+    // Both of these are tabulated as "negative" predictions; so, to simplify
+    // the logic below, map them both to UNKNOWN_TYPE.
+    if (predicted_type == NO_SERVER_DATA)
+      predicted_type = UNKNOWN_TYPE;
     switch (metric) {
       case AutofillMetrics::TRUE_POSITIVE:
         return unknown_equivalent_types_.count(actual_type) == 0 &&
@@ -863,9 +876,9 @@
   ServerFieldType actual_field_type = GetParam().actual_field_type;
   ServerFieldType predicted_type = GetParam().predicted_field_type;
 
-  VLOG(2) << "Test Case = Predicted: "
-          << AutofillType(predicted_type).ToString() << "; "
-          << "Actual: " << AutofillType(actual_field_type).ToString();
+  DVLOG(2) << "Test Case = Predicted: "
+           << AutofillType(predicted_type).ToString() << "; "
+           << "Actual: " << AutofillType(actual_field_type).ToString();
 
   // Set up our form data.
   FormData form;
@@ -898,9 +911,10 @@
   test::CreateTestFormField("Unknown", "Unknown",
                             ValueForType(actual_field_type), "text", &field);
   form.fields.push_back(field);
-  heuristic_types.push_back(predicted_type);
-  server_types.push_back(predicted_type == UNKNOWN_TYPE ? NO_SERVER_DATA
-                                                        : predicted_type);
+  heuristic_types.push_back(predicted_type == NO_SERVER_DATA ? UNKNOWN_TYPE
+                                                             : predicted_type);
+  server_types.push_back(predicted_type);
+
   // Resolve any field type ambiguity.
   if (actual_field_type == AMBIGUOUS_TYPE) {
     if (predicted_type == COMPANY_NAME || predicted_type == NAME_MIDDLE)
@@ -937,6 +951,7 @@
         by_field_type_histogram,
         2 +
             (predicted_type != UNKNOWN_TYPE &&
+             predicted_type != NO_SERVER_DATA &&
              predicted_type != actual_field_type) +
             (unknown_equivalent_types_.count(actual_field_type) == 0));
 
@@ -947,8 +962,8 @@
                                        FieldTypeCross(NAME_LAST, NAME_LAST), 1);
     histogram_tester.ExpectBucketCount(
         crossed_histogram,
-        FieldTypeCross((source == "Server" && predicted_type == UNKNOWN_TYPE
-                            ? NO_SERVER_DATA
+        FieldTypeCross((predicted_type == NO_SERVER_DATA && source != "Server"
+                            ? UNKNOWN_TYPE
                             : predicted_type),
                        actual_field_type),
         1);
@@ -993,7 +1008,7 @@
     // (empty is not a predictable value) and we don't capture false negative
     // mismatches.
     int expected_count_for_predicted_type =
-        (predicted_type != UNKNOWN_TYPE &&
+        (predicted_type != UNKNOWN_TYPE && predicted_type != NO_SERVER_DATA &&
          metric != AutofillMetrics::FALSE_NEGATIVE_MISMATCH)
             ? basic_expected_count
             : 0;
@@ -1020,10 +1035,10 @@
 INSTANTIATE_TEST_CASE_P(
     AutofillMetricsTest,
     QualityMetricsTest,
-    testing::Values(QualityMetricsTestCase{UNKNOWN_TYPE, EMPTY_TYPE},
-                    QualityMetricsTestCase{UNKNOWN_TYPE, UNKNOWN_TYPE},
-                    QualityMetricsTestCase{UNKNOWN_TYPE, AMBIGUOUS_TYPE},
-                    QualityMetricsTestCase{UNKNOWN_TYPE, EMAIL_ADDRESS},
+    testing::Values(QualityMetricsTestCase{NO_SERVER_DATA, EMPTY_TYPE},
+                    QualityMetricsTestCase{NO_SERVER_DATA, UNKNOWN_TYPE},
+                    QualityMetricsTestCase{NO_SERVER_DATA, AMBIGUOUS_TYPE},
+                    QualityMetricsTestCase{NO_SERVER_DATA, EMAIL_ADDRESS},
                     QualityMetricsTestCase{EMAIL_ADDRESS, EMPTY_TYPE},
                     QualityMetricsTestCase{EMAIL_ADDRESS, UNKNOWN_TYPE},
                     QualityMetricsTestCase{EMAIL_ADDRESS, AMBIGUOUS_TYPE},
@@ -1031,7 +1046,11 @@
                     QualityMetricsTestCase{EMAIL_ADDRESS, COMPANY_NAME},
                     QualityMetricsTestCase{COMPANY_NAME, EMAIL_ADDRESS},
                     QualityMetricsTestCase{NAME_MIDDLE, AMBIGUOUS_TYPE},
-                    QualityMetricsTestCase{COMPANY_NAME, AMBIGUOUS_TYPE}));
+                    QualityMetricsTestCase{COMPANY_NAME, AMBIGUOUS_TYPE},
+                    QualityMetricsTestCase{UNKNOWN_TYPE, EMPTY_TYPE},
+                    QualityMetricsTestCase{UNKNOWN_TYPE, UNKNOWN_TYPE},
+                    QualityMetricsTestCase{UNKNOWN_TYPE, AMBIGUOUS_TYPE},
+                    QualityMetricsTestCase{UNKNOWN_TYPE, EMAIL_ADDRESS}));
 
 // Ensures that metrics that measure timing some important Autofill functions
 // actually are recorded and retrieved.
diff --git a/components/autofill/core/browser/autofill_provider.h b/components/autofill/core/browser/autofill_provider.h
index d0776bc6..edc25f92 100644
--- a/components/autofill/core/browser/autofill_provider.h
+++ b/components/autofill/core/browser/autofill_provider.h
@@ -35,6 +35,11 @@
                                     const gfx::RectF& bounding_box,
                                     const base::TimeTicks timestamp) = 0;
 
+  virtual void OnTextFieldDidScroll(AutofillHandlerProxy* handler,
+                                    const FormData& form,
+                                    const FormFieldData& field,
+                                    const gfx::RectF& bounding_box) = 0;
+
   virtual bool OnWillSubmitForm(AutofillHandlerProxy* handler,
                                 const FormData& form,
                                 const base::TimeTicks timestamp) = 0;
diff --git a/components/autofill/core/browser/form_structure.cc b/components/autofill/core/browser/form_structure.cc
index 6bad5882..425a7b0 100644
--- a/components/autofill/core/browser/form_structure.cc
+++ b/components/autofill/core/browser/form_structure.cc
@@ -507,9 +507,6 @@
           current_field->overall_type_prediction());
       query_response_has_no_server_data &= field_type == NO_SERVER_DATA;
 
-      // UNKNOWN_TYPE is reserved for use by the client.
-      DCHECK_NE(field_type, UNKNOWN_TYPE);
-
       ServerFieldType heuristic_type = field->heuristic_type();
       if (heuristic_type != UNKNOWN_TYPE)
         heuristics_detected_fillable_field = true;
diff --git a/components/autofill/core/browser/form_structure_unittest.cc b/components/autofill/core/browser/form_structure_unittest.cc
index d6dcec11..641d9b2 100644
--- a/components/autofill/core/browser/form_structure_unittest.cc
+++ b/components/autofill/core/browser/form_structure_unittest.cc
@@ -3921,6 +3921,62 @@
   EXPECT_EQ(0U, form_structure2.PossibleValues(ADDRESS_BILLING_COUNTRY).size());
 }
 
+// Tests proper resolution heuristic, server and html field types when the
+// server returns NO_SERVER_DATA, UNKNOWN_TYPE, and a valid type.
+TEST_F(FormStructureTest, ParseQueryResponse_UnknownType) {
+  FormData form_data;
+  FormFieldData field;
+  form_data.origin = GURL("http://foo.com");
+  field.form_control_type = "text";
+
+  field.label = ASCIIToUTF16("First Name");
+  field.name = ASCIIToUTF16("fname");
+  form_data.fields.push_back(field);
+
+  field.label = ASCIIToUTF16("Last Name");
+  field.name = ASCIIToUTF16("lname");
+  form_data.fields.push_back(field);
+
+  field.label = ASCIIToUTF16("email");
+  field.name = ASCIIToUTF16("email");
+  field.autocomplete_attribute = "address-level2";
+  form_data.fields.push_back(field);
+
+  FormStructure form(form_data);
+  form.DetermineHeuristicTypes(nullptr /* ukm_service */);
+
+  // Setup the query response.
+  AutofillQueryResponseContents response;
+  std::string response_string;
+  response.add_field()->set_overall_type_prediction(UNKNOWN_TYPE);
+  response.add_field()->set_overall_type_prediction(NO_SERVER_DATA);
+  response.add_field()->set_overall_type_prediction(ADDRESS_HOME_LINE1);
+  ASSERT_TRUE(response.SerializeToString(&response_string));
+
+  // Parse the response and update the field type predictions.
+  std::vector<FormStructure*> forms{&form};
+  FormStructure::ParseQueryResponse(response_string, forms);
+  ASSERT_EQ(form.field_count(), 3U);
+
+  // Validate field 0.
+  EXPECT_EQ(NAME_FIRST, form.field(0)->heuristic_type());
+  EXPECT_EQ(UNKNOWN_TYPE, form.field(0)->overall_server_type());
+  EXPECT_EQ(HTML_TYPE_UNSPECIFIED, form.field(0)->html_type());
+  EXPECT_EQ(UNKNOWN_TYPE, form.field(0)->Type().GetStorableType());
+
+  // Validate field 1.
+  EXPECT_EQ(NAME_LAST, form.field(1)->heuristic_type());
+  EXPECT_EQ(NO_SERVER_DATA, form.field(1)->overall_server_type());
+  EXPECT_EQ(HTML_TYPE_UNSPECIFIED, form.field(1)->html_type());
+  EXPECT_EQ(NAME_LAST, form.field(1)->Type().GetStorableType());
+
+  // Validate field 2. Note: HTML_TYPE_ADDRESS_LEVEL2 -> City
+  EXPECT_EQ(EMAIL_ADDRESS, form.field(2)->heuristic_type());
+  EXPECT_EQ(ADDRESS_HOME_LINE1, form.field(2)->overall_server_type());
+  EXPECT_EQ(HTML_TYPE_ADDRESS_LEVEL2, form.field(2)->html_type());
+  EXPECT_EQ(ADDRESS_HOME_CITY, form.field(2)->Type().GetStorableType());
+}
+
 // TODO(crbug.com/578257): Add more tests for the AutofillQueryResponseContents
 // proto.
 TEST_F(FormStructureTest, ParseQueryResponse) {
@@ -3994,7 +4050,7 @@
   EXPECT_EQ(0U, forms[1]->field(1)->server_predictions()[0].type());
 }
 
-TEST_F(FormStructureTest, ParseQueryResponseAuthorDefinedTypes) {
+TEST_F(FormStructureTest, ParseQueryResponse_AuthorDefinedTypes) {
   FormData form;
   form.origin = GURL("http://foo.com");
   FormFieldData field;
diff --git a/components/printing/test/BUILD.gn b/components/printing/test/BUILD.gn
index aad7715..65e63db 100644
--- a/components/printing/test/BUILD.gn
+++ b/components/printing/test/BUILD.gn
@@ -23,6 +23,7 @@
     "//content/test:test_support",
     "//ipc",
     "//printing",
+    "//printing:test_support",
     "//skia",
     "//testing/gtest",
     "//ui/gfx/geometry",
diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc
index 09333e8..3f5bb15 100644
--- a/content/browser/gpu/gpu_process_host.cc
+++ b/content/browser/gpu/gpu_process_host.cc
@@ -490,7 +490,7 @@
 GpuProcessHost::~GpuProcessHost() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-  SendOutstandingReplies();
+  SendOutstandingReplies(EstablishChannelStatus::GPU_HOST_INVALID);
 
   if (status_ == UNKNOWN) {
     RunRequestGPUInfoCallbacks(gpu::GPUInfo());
@@ -681,7 +681,7 @@
     // Channel is hosed, but we may not get destroyed for a while. Send
     // outstanding channel creation failures now so that the caller can restart
     // with a new process/channel without waiting.
-    SendOutstandingReplies();
+    SendOutstandingReplies(EstablishChannelStatus::GPU_HOST_INVALID);
   }
   return result;
 }
@@ -875,7 +875,7 @@
           cache_key.first, base::Time(), base::Time::Max(), base::Bind([] {}));
     }
   }
-  SendOutstandingReplies();
+  SendOutstandingReplies(EstablishChannelStatus::GPU_HOST_INVALID);
   RecordProcessCrash();
   GpuDataManagerImpl::GetInstance()->ProcessCrashed(
       process_->GetTerminationStatus(true /* known_dead */, nullptr));
@@ -1111,7 +1111,7 @@
   bool current_gpu_type_enabled =
       swiftshader_rendering_ ? gpu_enabled_ : hardware_gpu_enabled_;
   if (!current_gpu_type_enabled) {
-    SendOutstandingReplies();
+    SendOutstandingReplies(EstablishChannelStatus::GPU_ACCESS_DENIED);
     return false;
   }
 
@@ -1132,7 +1132,9 @@
   return true;
 }
 
-void GpuProcessHost::SendOutstandingReplies() {
+void GpuProcessHost::SendOutstandingReplies(
+    EstablishChannelStatus failure_status) {
+  DCHECK_NE(failure_status, EstablishChannelStatus::SUCCESS);
   valid_ = false;
 
   // First send empty channel handles for all EstablishChannel requests.
@@ -1140,8 +1142,7 @@
     auto callback = channel_requests_.front();
     channel_requests_.pop();
     callback.Run(mojo::ScopedMessagePipeHandle(), gpu::GPUInfo(),
-                 gpu::GpuFeatureInfo(),
-                 EstablishChannelStatus::GPU_HOST_INVALID);
+                 gpu::GpuFeatureInfo(), failure_status);
   }
 
   while (!create_gpu_memory_buffer_requests_.empty()) {
diff --git a/content/browser/gpu/gpu_process_host.h b/content/browser/gpu/gpu_process_host.h
index 53eec4a..5efa679 100644
--- a/content/browser/gpu/gpu_process_host.h
+++ b/content/browser/gpu/gpu_process_host.h
@@ -229,7 +229,7 @@
 
   bool LaunchGpuProcess();
 
-  void SendOutstandingReplies();
+  void SendOutstandingReplies(EstablishChannelStatus failure_status);
 
   void RunRequestGPUInfoCallbacks(const gpu::GPUInfo& gpu_info);
 
diff --git a/content/browser/network_service_restart_browsertest.cc b/content/browser/network_service_restart_browsertest.cc
index 52901f2c..a43322d 100644
--- a/content/browser/network_service_restart_browsertest.cc
+++ b/content/browser/network_service_restart_browsertest.cc
@@ -114,10 +114,18 @@
   EXPECT_FALSE(network_context2.encountered_error());
 }
 
+// Flaky on Mac bots. crbug.com/793296
+#if defined(OS_MACOSX)
+#define MAYBE_StoragePartitionImplGetNetworkContext \
+  DISABLED_StoragePartitionImplGetNetworkContext
+#else
+#define MAYBE_StoragePartitionImplGetNetworkContext \
+  StoragePartitionImplGetNetworkContext
+#endif
 // Make sure |StoragePartitionImpl::GetNetworkContext()| returns valid interface
 // after crash.
 IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
-                       StoragePartitionImplGetNetworkContext) {
+                       MAYBE_StoragePartitionImplGetNetworkContext) {
   StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
       BrowserContext::GetDefaultStoragePartition(
           shell()->web_contents()->GetBrowserContext()));
diff --git a/content/shell/renderer/layout_test/layout_test_content_renderer_client.cc b/content/shell/renderer/layout_test/layout_test_content_renderer_client.cc
index a1f790e..96b3648 100644
--- a/content/shell/renderer/layout_test/layout_test_content_renderer_client.cc
+++ b/content/shell/renderer/layout_test/layout_test_content_renderer_client.cc
@@ -30,7 +30,6 @@
 #include "content/shell/test_runner/web_test_runner.h"
 #include "content/shell/test_runner/web_view_test_proxy.h"
 #include "content/test/mock_webclipboard_impl.h"
-#include "gin/modules/module_registry.h"
 #include "media/base/audio_latency.h"
 #include "media/base/mime_util.h"
 #include "media/media_features.h"
diff --git a/gin/BUILD.gn b/gin/BUILD.gn
index 39bd188c..5341919 100644
--- a/gin/BUILD.gn
+++ b/gin/BUILD.gn
@@ -30,15 +30,6 @@
     "isolate_holder.cc",
     "modules/console.cc",
     "modules/console.h",
-    "modules/file_module_provider.cc",
-    "modules/file_module_provider.h",
-    "modules/module_registry.cc",
-    "modules/module_registry.h",
-    "modules/module_registry_observer.h",
-    "modules/module_runner_delegate.cc",
-    "modules/module_runner_delegate.h",
-    "modules/timer.cc",
-    "modules/timer.h",
     "object_template_builder.cc",
     "object_template_builder.h",
     "per_context_data.cc",
@@ -131,20 +122,9 @@
 source_set("gin_test") {
   testonly = true
   sources = [
-    "test/file.cc",
-    "test/file.h",
-    "test/file_runner.cc",
-    "test/file_runner.h",
-    "test/gc.cc",
-    "test/gc.h",
-    "test/gtest.cc",
-    "test/gtest.h",
     "test/v8_test.cc",
     "test/v8_test.h",
   ]
-  data = [
-    "test/expect.js",
-  ]
 
   public_deps = [
     ":gin",
@@ -169,13 +149,10 @@
     "converter_unittest.cc",
     "data_object_builder_unittest.cc",
     "interceptor_unittest.cc",
-    "modules/module_registry_unittest.cc",
-    "modules/timer_unittest.cc",
     "per_context_data_unittest.cc",
     "shell/gin_shell_unittest.cc",
     "shell_runner_unittest.cc",
     "test/run_all_unittests.cc",
-    "test/run_js_tests.cc",
     "v8_isolate_memory_dump_provider_unittest.cc",
     "v8_platform_unittest.cc",
     "wrappable_unittest.cc",
@@ -191,10 +168,7 @@
   configs += [ "//v8:external_startup_data" ]
 
   data = [
-    "modules/module_registry_unittests.js",
     "shell/hello_world.js",
-    "test/file_unittests.js",
-    "test/gtest_unittests.js",
     "../OWNERS",
   ]
 
diff --git a/gin/modules/console.cc b/gin/modules/console.cc
index 63fc41e..8786392b 100644
--- a/gin/modules/console.cc
+++ b/gin/modules/console.cc
@@ -9,41 +9,31 @@
 #include "base/strings/string_util.h"
 #include "gin/arguments.h"
 #include "gin/converter.h"
-#include "gin/object_template_builder.h"
-#include "gin/per_isolate_data.h"
-#include "gin/public/wrapper_info.h"
-
-using v8::ObjectTemplate;
 
 namespace gin {
 
 namespace {
 
-void Log(Arguments* args) {
+void Log(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  Arguments args(info);
   std::vector<std::string> messages;
-  if (!args->GetRemaining(&messages)) {
-    args->ThrowError();
+  if (!args.GetRemaining(&messages)) {
+    args.ThrowError();
     return;
   }
   printf("%s\n", base::JoinString(messages, " ").c_str());
 }
 
-WrapperInfo g_wrapper_info = { kEmbedderNativeGin };
-
 }  // namespace
 
-const char Console::kModuleName[] = "console";
+// static
+void Console::Register(v8::Isolate* isolate,
+                       v8::Local<v8::ObjectTemplate> templ) {
+  v8::Local<v8::FunctionTemplate> log_templ =
+      v8::FunctionTemplate::New(isolate, Log);
+  log_templ->RemovePrototype();
 
-v8::Local<v8::Value> Console::GetModule(v8::Isolate* isolate) {
-  PerIsolateData* data = PerIsolateData::From(isolate);
-  v8::Local<ObjectTemplate> templ = data->GetObjectTemplate(&g_wrapper_info);
-  if (templ.IsEmpty()) {
-    templ = ObjectTemplateBuilder(isolate)
-        .SetMethod("log", Log)
-        .Build();
-    data->SetObjectTemplate(&g_wrapper_info, templ);
-  }
-  return templ->NewInstance(isolate->GetCurrentContext()).ToLocalChecked();
+  templ->Set(StringToSymbol(isolate, "log"), log_templ);
 }
 
 }  // namespace gin
diff --git a/gin/modules/console.h b/gin/modules/console.h
index ff8061ba..4b68aa1 100644
--- a/gin/modules/console.h
+++ b/gin/modules/console.h
@@ -14,8 +14,8 @@
 // we'd like to evolve the API to match window.console in browsers.
 class GIN_EXPORT Console {
  public:
-  static const char kModuleName[];
-  static v8::Local<v8::Value> GetModule(v8::Isolate* isolate);
+  static void Register(v8::Isolate* isolate,
+                       v8::Local<v8::ObjectTemplate> templ);
 };
 
 }  // namespace gin
diff --git a/gin/modules/file_module_provider.cc b/gin/modules/file_module_provider.cc
deleted file mode 100644
index 2edb6088..0000000
--- a/gin/modules/file_module_provider.cc
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "gin/modules/file_module_provider.h"
-
-#include <stddef.h>
-
-#include "base/bind.h"
-#include "base/files/file_util.h"
-#include "base/location.h"
-#include "base/single_thread_task_runner.h"
-#include "base/strings/string_split.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "gin/converter.h"
-
-namespace gin {
-
-namespace {
-
-void AttempToLoadModule(const base::WeakPtr<Runner>& runner,
-                        const std::vector<base::FilePath>& search_paths,
-                        const std::string& id) {
-  if (!runner)
-    return;
-
-  std::vector<std::string> components = base::SplitString(
-      id, "/", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
-
-  base::FilePath path;
-  for (size_t i = 0; i < components.size(); ++i) {
-    // TODO(abarth): Technically the path components can be UTF-8. We don't
-    // handle that case correctly yet.
-    path = path.AppendASCII(components[i]);
-  }
-  path = path.AddExtension(FILE_PATH_LITERAL("js"));
-
-  for (size_t i = 0; i < search_paths.size(); ++i) {
-    std::string source;
-    if (!ReadFileToString(search_paths[i].Append(path), &source))
-      continue;
-
-    Runner::Scope scope(runner.get());
-    runner->Run(source, id);
-    return;
-  }
-  LOG(ERROR) << "Failed to load module from disk: " << id;
-}
-
-}  // namespace
-
-FileModuleProvider::FileModuleProvider(
-    const std::vector<base::FilePath>& search_paths)
-    : search_paths_(search_paths) {
-}
-
-FileModuleProvider::~FileModuleProvider() = default;
-
-void FileModuleProvider::AttempToLoadModules(
-    Runner* runner, const std::set<std::string>& ids) {
-  std::set<std::string> modules = ids;
-  for (std::set<std::string>::const_iterator it = modules.begin();
-       it != modules.end(); ++it) {
-    const std::string& id = *it;
-    if (attempted_ids_.count(id))
-      continue;
-    attempted_ids_.insert(id);
-    base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::Bind(AttempToLoadModule, runner->GetWeakPtr(),
-                              search_paths_, id));
-  }
-}
-
-}  // namespace gin
diff --git a/gin/modules/file_module_provider.h b/gin/modules/file_module_provider.h
deleted file mode 100644
index 7c03887..0000000
--- a/gin/modules/file_module_provider.h
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef GIN_MODULES_FILE_MODULE_PROVIDER_H_
-#define GIN_MODULES_FILE_MODULE_PROVIDER_H_
-
-#include <set>
-#include <string>
-#include <vector>
-
-#include "base/files/file_path.h"
-#include "base/macros.h"
-#include "gin/gin_export.h"
-#include "gin/runner.h"
-
-namespace gin {
-
-// FileModuleProvider knows how to load AMD modules off disk. It searches for
-// modules in the directories indiciated by |search_paths|. Although we still
-// read from the file system on the main thread, we'll eventually want to move
-// the reads to a background thread.
-class GIN_EXPORT FileModuleProvider {
- public:
-  explicit FileModuleProvider(
-      const std::vector<base::FilePath>& search_paths);
-  ~FileModuleProvider();
-
-  // Searches for modules with |ids| in the file system. If found, the modules
-  // will be executed asynchronously by |runner|.
-  void AttempToLoadModules(Runner* runner, const std::set<std::string>& ids);
-
- private:
-  std::vector<base::FilePath> search_paths_;
-
-  // We'll only search for a given module once. We remember the set of modules
-  // we've already looked for in |attempted_ids_|.
-  std::set<std::string> attempted_ids_;
-
-  DISALLOW_COPY_AND_ASSIGN(FileModuleProvider);
-};
-
-}  // namespace gin
-
-#endif  // GIN_MODULES_FILE_MODULE_PROVIDER_H_
diff --git a/gin/modules/module_registry.cc b/gin/modules/module_registry.cc
deleted file mode 100644
index cf61f7d..0000000
--- a/gin/modules/module_registry.cc
+++ /dev/null
@@ -1,289 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "gin/modules/module_registry.h"
-
-#include <stddef.h>
-#include <stdint.h>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "base/logging.h"
-#include "base/memory/ptr_util.h"
-#include "gin/arguments.h"
-#include "gin/converter.h"
-#include "gin/modules/module_registry_observer.h"
-#include "gin/per_context_data.h"
-#include "gin/per_isolate_data.h"
-#include "gin/public/wrapper_info.h"
-#include "gin/runner.h"
-
-using v8::Context;
-using v8::External;
-using v8::Function;
-using v8::FunctionTemplate;
-using v8::Isolate;
-using v8::Local;
-using v8::Object;
-using v8::ObjectTemplate;
-using v8::Persistent;
-using v8::StackTrace;
-using v8::String;
-using v8::Value;
-
-namespace gin {
-
-struct PendingModule {
-  PendingModule();
-  ~PendingModule();
-
-  std::string id;
-  std::vector<std::string> dependencies;
-  Persistent<Value> factory;
-};
-
-PendingModule::PendingModule() = default;
-
-PendingModule::~PendingModule() {
-  factory.Reset();
-}
-
-namespace {
-
-// Key for base::SupportsUserData::Data.
-const char kModuleRegistryKey[] = "ModuleRegistry";
-
-struct ModuleRegistryData : public base::SupportsUserData::Data {
-  std::unique_ptr<ModuleRegistry> registry;
-};
-
-void Define(const v8::FunctionCallbackInfo<Value>& info) {
-  Arguments args(info);
-
-  if (!info.Length())
-    return args.ThrowTypeError("At least one argument is required.");
-
-  std::string id;
-  std::vector<std::string> dependencies;
-  v8::Local<Value> factory;
-
-  if (!args.PeekNext().IsEmpty() && args.PeekNext()->IsString())
-    args.GetNext(&id);
-  if (!args.PeekNext().IsEmpty() && args.PeekNext()->IsArray())
-    args.GetNext(&dependencies);
-  if (!args.GetNext(&factory))
-    return args.ThrowError();
-
-  std::unique_ptr<PendingModule> pending(new PendingModule);
-  pending->id = id;
-  pending->dependencies = dependencies;
-  pending->factory.Reset(args.isolate(), factory);
-
-  ModuleRegistry* registry =
-      ModuleRegistry::From(args.isolate()->GetCurrentContext());
-  registry->AddPendingModule(args.isolate(), std::move(pending));
-}
-
-WrapperInfo g_wrapper_info = { kEmbedderNativeGin };
-
-Local<FunctionTemplate> GetDefineTemplate(Isolate* isolate) {
-  PerIsolateData* data = PerIsolateData::From(isolate);
-  Local<FunctionTemplate> templ = data->GetFunctionTemplate(
-      &g_wrapper_info);
-  if (templ.IsEmpty()) {
-    templ = FunctionTemplate::New(isolate, Define);
-    templ->RemovePrototype();
-    data->SetFunctionTemplate(&g_wrapper_info, templ);
-  }
-  return templ;
-}
-
-}  // namespace
-
-ModuleRegistry::ModuleRegistry(Isolate* isolate)
-    : modules_(isolate, Object::New(isolate)) {
-}
-
-ModuleRegistry::~ModuleRegistry() {
-  modules_.Reset();
-}
-
-// static
-void ModuleRegistry::RegisterGlobals(Isolate* isolate,
-                                     v8::Local<ObjectTemplate> templ) {
-  templ->Set(StringToSymbol(isolate, "define"), GetDefineTemplate(isolate));
-}
-
-// static
-bool ModuleRegistry::InstallGlobals(v8::Isolate* isolate,
-                                    v8::Local<v8::Object> obj) {
-  v8::Local<v8::Function> function;
-  auto maybe_function =
-      GetDefineTemplate(isolate)->GetFunction(isolate->GetCurrentContext());
-  if (!maybe_function.ToLocal(&function))
-    return false;
-  return SetProperty(isolate, obj, StringToSymbol(isolate, "define"), function);
-}
-
-// static
-ModuleRegistry* ModuleRegistry::From(v8::Local<Context> context) {
-  PerContextData* data = PerContextData::From(context);
-  if (!data)
-    return NULL;
-
-  ModuleRegistryData* registry_data = static_cast<ModuleRegistryData*>(
-      data->GetUserData(kModuleRegistryKey));
-  if (!registry_data) {
-    // PerContextData takes ownership of ModuleRegistryData.
-    registry_data = new ModuleRegistryData;
-    registry_data->registry.reset(new ModuleRegistry(context->GetIsolate()));
-    data->SetUserData(kModuleRegistryKey, base::WrapUnique(registry_data));
-  }
-  return registry_data->registry.get();
-}
-
-void ModuleRegistry::AddObserver(ModuleRegistryObserver* observer) {
-  observer_list_.AddObserver(observer);
-}
-
-void ModuleRegistry::RemoveObserver(ModuleRegistryObserver* observer) {
-  observer_list_.RemoveObserver(observer);
-}
-
-void ModuleRegistry::AddBuiltinModule(Isolate* isolate, const std::string& id,
-                                      v8::Local<Value> module) {
-  DCHECK(!id.empty());
-  RegisterModule(isolate, id, module);
-}
-
-void ModuleRegistry::AddPendingModule(Isolate* isolate,
-                                      std::unique_ptr<PendingModule> pending) {
-  const std::string pending_id = pending->id;
-  const std::vector<std::string> pending_dependencies = pending->dependencies;
-  AttemptToLoad(isolate, std::move(pending));
-  for (auto& observer : observer_list_)
-    observer.OnDidAddPendingModule(pending_id, pending_dependencies);
-}
-
-void ModuleRegistry::LoadModule(Isolate* isolate,
-                                const std::string& id,
-                                LoadModuleCallback callback) {
-  if (available_modules_.find(id) != available_modules_.end()) {
-    // Should we call the callback asynchronously?
-    callback.Run(GetModule(isolate, id));
-    return;
-  }
-  waiting_callbacks_.insert(std::make_pair(id, callback));
-
-  for (size_t i = 0; i < pending_modules_.size(); ++i) {
-    if (pending_modules_[i]->id == id)
-      return;
-  }
-
-  unsatisfied_dependencies_.insert(id);
-}
-
-bool ModuleRegistry::RegisterModule(Isolate* isolate,
-                                    const std::string& id,
-                                    v8::Local<Value> module) {
-  if (id.empty() || module.IsEmpty())
-    return false;
-
-  v8::Local<Object> modules = Local<Object>::New(isolate, modules_);
-  if (!SetProperty(isolate, modules, StringToSymbol(isolate, id), module))
-    return false;
-  unsatisfied_dependencies_.erase(id);
-  available_modules_.insert(id);
-
-  std::pair<LoadModuleCallbackMap::iterator, LoadModuleCallbackMap::iterator>
-      range = waiting_callbacks_.equal_range(id);
-  std::vector<LoadModuleCallback> callbacks;
-  callbacks.reserve(waiting_callbacks_.count(id));
-  for (LoadModuleCallbackMap::iterator it = range.first; it != range.second;
-       ++it) {
-    callbacks.push_back(it->second);
-  }
-  waiting_callbacks_.erase(range.first, range.second);
-  for (std::vector<LoadModuleCallback>::iterator it = callbacks.begin();
-       it != callbacks.end();
-       ++it) {
-    // Should we call the callback asynchronously?
-    it->Run(module);
-  }
-  return true;
-}
-
-bool ModuleRegistry::CheckDependencies(PendingModule* pending) {
-  size_t num_missing_dependencies = 0;
-  size_t len = pending->dependencies.size();
-  for (size_t i = 0; i < len; ++i) {
-    const std::string& dependency = pending->dependencies[i];
-    if (available_modules_.count(dependency))
-      continue;
-    unsatisfied_dependencies_.insert(dependency);
-    num_missing_dependencies++;
-  }
-  return num_missing_dependencies == 0;
-}
-
-bool ModuleRegistry::Load(Isolate* isolate,
-                          std::unique_ptr<PendingModule> pending) {
-  if (!pending->id.empty() && available_modules_.count(pending->id))
-    return true;  // We've already loaded this module.
-
-  uint32_t argc = static_cast<uint32_t>(pending->dependencies.size());
-  std::vector<v8::Local<Value> > argv(argc);
-  for (uint32_t i = 0; i < argc; ++i)
-    argv[i] = GetModule(isolate, pending->dependencies[i]);
-
-  v8::Local<Value> module = Local<Value>::New(isolate, pending->factory);
-
-  v8::Local<Function> factory;
-  if (ConvertFromV8(isolate, module, &factory)) {
-    PerContextData* data = PerContextData::From(isolate->GetCurrentContext());
-    Runner* runner = data->runner();
-    module = runner->Call(factory, runner->global(), argc,
-                          argv.empty() ? NULL : &argv.front());
-    if (pending->id.empty())
-      ConvertFromV8(isolate, factory->GetScriptOrigin().ResourceName(),
-                    &pending->id);
-  }
-
-  return RegisterModule(isolate, pending->id, module);
-}
-
-bool ModuleRegistry::AttemptToLoad(Isolate* isolate,
-                                   std::unique_ptr<PendingModule> pending) {
-  if (!CheckDependencies(pending.get())) {
-    pending_modules_.push_back(std::move(pending));
-    return false;
-  }
-  return Load(isolate, std::move(pending));
-}
-
-v8::Local<v8::Value> ModuleRegistry::GetModule(v8::Isolate* isolate,
-                                                const std::string& id) {
-  v8::Local<Object> modules = Local<Object>::New(isolate, modules_);
-  v8::Local<String> key = StringToSymbol(isolate, id);
-  DCHECK(modules->HasOwnProperty(isolate->GetCurrentContext(), key).FromJust());
-  return modules->Get(isolate->GetCurrentContext(), key).ToLocalChecked();
-}
-
-void ModuleRegistry::AttemptToLoadMoreModules(Isolate* isolate) {
-  bool keep_trying = true;
-  while (keep_trying) {
-    keep_trying = false;
-    PendingModuleVector pending_modules;
-    pending_modules.swap(pending_modules_);
-    for (size_t i = 0; i < pending_modules.size(); ++i) {
-      std::unique_ptr<PendingModule> pending(std::move(pending_modules[i]));
-      pending_modules[i] = NULL;
-      if (AttemptToLoad(isolate, std::move(pending)))
-        keep_trying = true;
-    }
-  }
-}
-
-}  // namespace gin
diff --git a/gin/modules/module_registry.h b/gin/modules/module_registry.h
deleted file mode 100644
index c1d3a00..0000000
--- a/gin/modules/module_registry.h
+++ /dev/null
@@ -1,111 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef GIN_MODULES_MODULE_REGISTRY_H_
-#define GIN_MODULES_MODULE_REGISTRY_H_
-
-#include <list>
-#include <map>
-#include <memory>
-#include <set>
-#include <string>
-#include <vector>
-
-#include "base/callback.h"
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "base/observer_list.h"
-#include "gin/gin_export.h"
-#include "v8/include/v8.h"
-
-namespace gin {
-
-class ModuleRegistryObserver;
-struct PendingModule;
-
-// This class implements the Asynchronous Module Definition (AMD) API.
-// https://github.com/amdjs/amdjs-api/wiki/AMD
-//
-// Our implementation isn't complete yet. Missing features:
-//   1) Built-in support for require, exports, and module.
-//   2) Path resoltuion in module names.
-//
-// For these reasons, we don't have an "amd" property on the "define"
-// function. The spec says we should only add that property once our
-// implementation complies with the specification.
-//
-class GIN_EXPORT ModuleRegistry {
- public:
-  typedef base::Callback<void (v8::Local<v8::Value>)> LoadModuleCallback;
-
-  virtual ~ModuleRegistry();
-
-  static ModuleRegistry* From(v8::Local<v8::Context> context);
-
-  static void RegisterGlobals(v8::Isolate* isolate,
-                              v8::Local<v8::ObjectTemplate> templ);
-
-  // Installs the necessary functions needed for modules.
-  // WARNING: this may execute script in the page.
-  static bool InstallGlobals(v8::Isolate* isolate, v8::Local<v8::Object> obj);
-
-  void AddObserver(ModuleRegistryObserver* observer);
-  void RemoveObserver(ModuleRegistryObserver* observer);
-
-  // The caller must have already entered our context.
-  void AddBuiltinModule(v8::Isolate* isolate, const std::string& id,
-                        v8::Local<v8::Value> module);
-
-  // The caller must have already entered our context.
-  void AddPendingModule(v8::Isolate* isolate,
-                        std::unique_ptr<PendingModule> pending);
-
-  void LoadModule(v8::Isolate* isolate,
-                  const std::string& id,
-                  LoadModuleCallback callback);
-
-  // The caller must have already entered our context.
-  void AttemptToLoadMoreModules(v8::Isolate* isolate);
-
-  const std::set<std::string>& available_modules() const {
-    return available_modules_;
-  }
-
-  const std::set<std::string>& unsatisfied_dependencies() const {
-    return unsatisfied_dependencies_;
-  }
-
- private:
-  typedef std::vector<std::unique_ptr<PendingModule>> PendingModuleVector;
-  typedef std::multimap<std::string, LoadModuleCallback> LoadModuleCallbackMap;
-
-  explicit ModuleRegistry(v8::Isolate* isolate);
-
-  bool Load(v8::Isolate* isolate, std::unique_ptr<PendingModule> pending);
-  bool RegisterModule(v8::Isolate* isolate,
-                      const std::string& id,
-                      v8::Local<v8::Value> module);
-
-  bool CheckDependencies(PendingModule* pending);
-  bool AttemptToLoad(v8::Isolate* isolate,
-                     std::unique_ptr<PendingModule> pending);
-
-  v8::Local<v8::Value> GetModule(v8::Isolate* isolate, const std::string& id);
-
-  std::set<std::string> available_modules_;
-  std::set<std::string> unsatisfied_dependencies_;
-
-  LoadModuleCallbackMap waiting_callbacks_;
-
-  PendingModuleVector pending_modules_;
-  v8::Persistent<v8::Object> modules_;
-
-  base::ObserverList<ModuleRegistryObserver> observer_list_;
-
-  DISALLOW_COPY_AND_ASSIGN(ModuleRegistry);
-};
-
-}  // namespace gin
-
-#endif  // GIN_MODULES_MODULE_REGISTRY_H_
diff --git a/gin/modules/module_registry_observer.h b/gin/modules/module_registry_observer.h
deleted file mode 100644
index 68ee4ad..0000000
--- a/gin/modules/module_registry_observer.h
+++ /dev/null
@@ -1,31 +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 GIN_MODULES_MODULE_REGISTRY_OBSERVER_H_
-#define GIN_MODULES_MODULE_REGISTRY_OBSERVER_H_
-
-#include <string>
-#include <vector>
-
-#include "gin/gin_export.h"
-
-namespace gin {
-
-// Notified of interesting events from ModuleRegistry.
-class GIN_EXPORT ModuleRegistryObserver {
- public:
-  // Called from AddPendingModule(). |id| is the id/name of the module and
-  // |dependencies| this list of modules |id| depends upon.
-  virtual void OnDidAddPendingModule(
-      const std::string& id,
-      const std::vector<std::string>& dependencies) = 0;
-
- protected:
-  virtual ~ModuleRegistryObserver() {}
-};
-
-}  // namespace gin
-
-#endif  // GIN_MODULES_MODULE_REGISTRY_OBSERVER_H_
-
diff --git a/gin/modules/module_registry_unittest.cc b/gin/modules/module_registry_unittest.cc
deleted file mode 100644
index 3921539..0000000
--- a/gin/modules/module_registry_unittest.cc
+++ /dev/null
@@ -1,167 +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 "gin/modules/module_registry.h"
-
-#include <stdint.h>
-
-#include <memory>
-
-#include "base/bind.h"
-#include "base/macros.h"
-#include "gin/modules/module_registry_observer.h"
-#include "gin/modules/module_runner_delegate.h"
-#include "gin/public/context_holder.h"
-#include "gin/public/isolate_holder.h"
-#include "gin/shell_runner.h"
-#include "gin/test/v8_test.h"
-#include "v8/include/v8.h"
-
-namespace gin {
-
-namespace {
-
-struct TestHelper {
-  TestHelper(v8::Isolate* isolate)
-      : delegate(std::vector<base::FilePath>()),
-        runner(new ShellRunner(&delegate, isolate)),
-        scope(runner.get()) {
-  }
-
-  ModuleRunnerDelegate delegate;
-  std::unique_ptr<ShellRunner> runner;
-  Runner::Scope scope;
-};
-
-class ModuleRegistryObserverImpl : public ModuleRegistryObserver {
- public:
-  ModuleRegistryObserverImpl() : did_add_count_(0) {}
-
-  void OnDidAddPendingModule(
-      const std::string& id,
-      const std::vector<std::string>& dependencies) override {
-    did_add_count_++;
-    id_ = id;
-    dependencies_ = dependencies;
-  }
-
-  int did_add_count() { return did_add_count_; }
-  const std::string& id() const { return id_; }
-  const std::vector<std::string>& dependencies() const { return dependencies_; }
-
- private:
-  int did_add_count_;
-  std::string id_;
-  std::vector<std::string> dependencies_;
-
-  DISALLOW_COPY_AND_ASSIGN(ModuleRegistryObserverImpl);
-};
-
-void NestedCallback(v8::Local<v8::Value> value) {
-  FAIL() << "Should not be called";
-}
-
-void OnModuleLoaded(TestHelper* helper,
-                    v8::Isolate* isolate,
-                    int64_t* counter,
-                    v8::Local<v8::Value> value) {
-  ASSERT_TRUE(value->IsNumber());
-  v8::Local<v8::Integer> int_value = v8::Local<v8::Integer>::Cast(value);
-  *counter += int_value->Value();
-  ModuleRegistry::From(helper->runner->GetContextHolder()->context())
-      ->LoadModule(isolate, "two", base::Bind(NestedCallback));
-}
-
-void OnModuleLoadedNoOp(v8::Local<v8::Value> value) {
-  ASSERT_TRUE(value->IsNumber());
-}
-
-}  // namespace
-
-typedef V8Test ModuleRegistryTest;
-
-// Verifies ModuleRegistry is not available after ContextHolder has been
-// deleted.
-TEST_F(ModuleRegistryTest, DestroyedWithContext) {
-  v8::Isolate::Scope isolate_scope(instance_->isolate());
-  v8::HandleScope handle_scope(instance_->isolate());
-  v8::Local<v8::Context> context = v8::Context::New(
-      instance_->isolate(), NULL, v8::Local<v8::ObjectTemplate>());
-  {
-    ContextHolder context_holder(instance_->isolate());
-    context_holder.SetContext(context);
-    ModuleRegistry* registry = ModuleRegistry::From(context);
-    EXPECT_TRUE(registry != NULL);
-  }
-  ModuleRegistry* registry = ModuleRegistry::From(context);
-  EXPECT_TRUE(registry == NULL);
-}
-
-// Verifies ModuleRegistryObserver is notified appropriately.
-TEST_F(ModuleRegistryTest, ModuleRegistryObserverTest) {
-  TestHelper helper(instance_->isolate());
-  std::string source =
-     "define('id', ['dep1', 'dep2'], function() {"
-     "  return function() {};"
-     "});";
-
-  ModuleRegistryObserverImpl observer;
-  ModuleRegistry::From(helper.runner->GetContextHolder()->context())->
-      AddObserver(&observer);
-  helper.runner->Run(source, "script");
-  ModuleRegistry::From(helper.runner->GetContextHolder()->context())->
-      RemoveObserver(&observer);
-  EXPECT_EQ(1, observer.did_add_count());
-  EXPECT_EQ("id", observer.id());
-  ASSERT_EQ(2u, observer.dependencies().size());
-  EXPECT_EQ("dep1", observer.dependencies()[0]);
-  EXPECT_EQ("dep2", observer.dependencies()[1]);
-}
-
-// Verifies that multiple LoadModule calls for the same module are handled
-// correctly.
-TEST_F(ModuleRegistryTest, LoadModuleTest) {
-  TestHelper helper(instance_->isolate());
-  int64_t counter = 0;
-  std::string source =
-      "define('one', [], function() {"
-      "  return 1;"
-      "});";
-
-  ModuleRegistry::LoadModuleCallback callback =
-      base::Bind(OnModuleLoaded, &helper, instance_->isolate(), &counter);
-  for (int i = 0; i < 3; i++) {
-    ModuleRegistry::From(helper.runner->GetContextHolder()->context())
-        ->LoadModule(instance_->isolate(), "one", callback);
-  }
-  EXPECT_EQ(0, counter);
-  helper.runner->Run(source, "script");
-  EXPECT_EQ(3, counter);
-}
-
-// Verifies that explicitly loading a module that's already pending does
-// not cause the ModuleRegistry's unsatisfied_dependency set to grow.
-TEST_F(ModuleRegistryTest, UnsatisfiedDependenciesTest) {
-  TestHelper helper(instance_->isolate());
-  std::string source =
-      "define('one', ['no_such_module'], function(nsm) {"
-      "  return 1;"
-      "});";
-  ModuleRegistry* registry =
-    ModuleRegistry::From(helper.runner->GetContextHolder()->context());
-
-  std::set<std::string> no_such_module_set;
-  no_such_module_set.insert("no_such_module");
-
-  // Adds one unsatisfied dependency on "no-such-module".
-  helper.runner->Run(source, "script");
-  EXPECT_EQ(no_such_module_set, registry->unsatisfied_dependencies());
-
-  // Should have no effect on the unsatisfied_dependencies set.
-  ModuleRegistry::LoadModuleCallback callback = base::Bind(OnModuleLoadedNoOp);
-  registry->LoadModule(instance_->isolate(), "one", callback);
-  EXPECT_EQ(no_such_module_set, registry->unsatisfied_dependencies());
-}
-
-}  // namespace gin
diff --git a/gin/modules/module_registry_unittests.js b/gin/modules/module_registry_unittests.js
deleted file mode 100644
index ca70148..0000000
--- a/gin/modules/module_registry_unittests.js
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-define("module0", function() {
-  return {
-    "foo": "bar",
-  }
-});
-
-define("module2", [
-    "gtest",
-    "module0",
-    "module1"
-  ], function(gtest, module0, module1) {
-  gtest.expectEqual(module0.foo, "bar",
-      "module0.foo is " + module0.foo);
-  gtest.expectFalse(module0.bar,
-      "module0.bar is " + module0.bar);
-  gtest.expectEqual(module1.baz, "qux",
-      "module1.baz is " + module1.baz);
-  gtest.expectFalse(module1.qux,
-      "module1.qux is " + module1.qux);
-
-  this.result = "PASS";
-});
-
-define("module1", {
-  "baz": "qux",
-});
diff --git a/gin/modules/module_runner_delegate.cc b/gin/modules/module_runner_delegate.cc
deleted file mode 100644
index 0634fff3..0000000
--- a/gin/modules/module_runner_delegate.cc
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "gin/modules/module_runner_delegate.h"
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "gin/modules/module_registry.h"
-#include "gin/object_template_builder.h"
-#include "gin/public/context_holder.h"
-
-namespace gin {
-
-ModuleRunnerDelegate::ModuleRunnerDelegate(
-  const std::vector<base::FilePath>& search_paths)
-    : module_provider_(search_paths) {
-}
-
-ModuleRunnerDelegate::~ModuleRunnerDelegate() = default;
-
-void ModuleRunnerDelegate::AddBuiltinModule(const std::string& id,
-                                            ModuleGetter getter) {
-  builtin_modules_[id] = base::Bind(getter);
-}
-
-void ModuleRunnerDelegate::AddBuiltinModule(const std::string& id,
-    const ModuleGetterCallback& getter) {
-  builtin_modules_[id] = getter;
-}
-
-void ModuleRunnerDelegate::AttemptToLoadMoreModules(Runner* runner) {
-  ModuleRegistry* registry = ModuleRegistry::From(
-      runner->GetContextHolder()->context());
-  registry->AttemptToLoadMoreModules(runner->GetContextHolder()->isolate());
-  module_provider_.AttempToLoadModules(
-      runner, registry->unsatisfied_dependencies());
-}
-
-v8::Local<v8::ObjectTemplate> ModuleRunnerDelegate::GetGlobalTemplate(
-    ShellRunner* runner,
-    v8::Isolate* isolate) {
-  v8::Local<v8::ObjectTemplate> templ = ObjectTemplateBuilder(isolate).Build();
-  ModuleRegistry::RegisterGlobals(isolate, templ);
-  return templ;
-}
-
-void ModuleRunnerDelegate::DidCreateContext(ShellRunner* runner) {
-  ShellRunnerDelegate::DidCreateContext(runner);
-
-  v8::Local<v8::Context> context = runner->GetContextHolder()->context();
-  ModuleRegistry* registry = ModuleRegistry::From(context);
-
-  v8::Isolate* isolate = runner->GetContextHolder()->isolate();
-
-  for (BuiltinModuleMap::const_iterator it = builtin_modules_.begin();
-       it != builtin_modules_.end(); ++it) {
-    registry->AddBuiltinModule(isolate, it->first, it->second.Run(isolate));
-  }
-}
-
-void ModuleRunnerDelegate::DidRunScript(ShellRunner* runner) {
-  AttemptToLoadMoreModules(runner);
-}
-
-}  // namespace gin
diff --git a/gin/modules/module_runner_delegate.h b/gin/modules/module_runner_delegate.h
deleted file mode 100644
index f49594c..0000000
--- a/gin/modules/module_runner_delegate.h
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef GIN_MODULES_MODULE_RUNNER_DELEGATE_H_
-#define GIN_MODULES_MODULE_RUNNER_DELEGATE_H_
-
-#include <map>
-
-#include "base/callback.h"
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "gin/gin_export.h"
-#include "gin/modules/file_module_provider.h"
-#include "gin/shell_runner.h"
-#include "v8/include/v8.h"
-
-namespace gin {
-
-typedef v8::Local<v8::Value> (*ModuleGetter)(v8::Isolate* isolate);
-typedef base::Callback<v8::Local<v8::Value>(v8::Isolate*)> ModuleGetterCallback;
-
-// Emebedders that use AMD modules will probably want to use a RunnerDelegate
-// that inherits from ModuleRunnerDelegate. ModuleRunnerDelegate lets embedders
-// register built-in modules and routes module requests to FileModuleProvider.
-class GIN_EXPORT ModuleRunnerDelegate : public ShellRunnerDelegate {
- public:
-  explicit ModuleRunnerDelegate(
-      const std::vector<base::FilePath>& search_paths);
-  ~ModuleRunnerDelegate() override;
-
-  void AddBuiltinModule(const std::string& id, ModuleGetter getter);
-  void AddBuiltinModule(const std::string& id,
-                        const ModuleGetterCallback& getter);
-
- protected:
-  void AttemptToLoadMoreModules(Runner* runner);
-
- private:
-  typedef std::map<std::string, ModuleGetterCallback> BuiltinModuleMap;
-
-  // From ShellRunnerDelegate:
-  v8::Local<v8::ObjectTemplate> GetGlobalTemplate(
-      ShellRunner* runner,
-      v8::Isolate* isolate) override;
-  void DidCreateContext(ShellRunner* runner) override;
-  void DidRunScript(ShellRunner* runner) override;
-
-  BuiltinModuleMap builtin_modules_;
-  FileModuleProvider module_provider_;
-
-  DISALLOW_COPY_AND_ASSIGN(ModuleRunnerDelegate);
-};
-
-}  // namespace gin
-
-#endif  // GIN_MODULES_MODULE_RUNNER_DELEGATE_H_
diff --git a/gin/modules/timer.cc b/gin/modules/timer.cc
deleted file mode 100644
index 1f60900..0000000
--- a/gin/modules/timer.cc
+++ /dev/null
@@ -1,112 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "gin/modules/timer.h"
-
-#include "base/bind.h"
-#include "gin/object_template_builder.h"
-#include "gin/per_context_data.h"
-
-namespace gin {
-
-namespace {
-
-v8::Local<v8::Private> GetHiddenPropertyName(v8::Isolate* isolate) {
-  return v8::Private::ForApi(isolate, gin::StringToV8(isolate, "::gin::Timer"));
-}
-
-}  // namespace
-
-// Timer =======================================================================
-
-gin::WrapperInfo Timer::kWrapperInfo = { gin::kEmbedderNativeGin };
-
-// static
-Handle<Timer> Timer::Create(TimerType type, v8::Isolate* isolate, int delay_ms,
-                            v8::Local<v8::Function> function) {
-  return CreateHandle(isolate, new Timer(isolate, type == TYPE_REPEATING,
-                                         delay_ms, function));
-}
-
-ObjectTemplateBuilder Timer::GetObjectTemplateBuilder(v8::Isolate* isolate) {
-  // We use Unretained() here because we directly own timer_, so we know it will
-  // be alive when these methods are called.
-  return Wrappable<Timer>::GetObjectTemplateBuilder(isolate)
-      .SetMethod("cancel",
-                 base::Bind(&base::Timer::Stop, base::Unretained(&timer_)))
-      .SetMethod("reset",
-                 base::Bind(&base::Timer::Reset, base::Unretained(&timer_)));
-}
-
-Timer::Timer(v8::Isolate* isolate, bool repeating, int delay_ms,
-             v8::Local<v8::Function> function)
-    : timer_(false, repeating),
-      runner_(PerContextData::From(
-          isolate->GetCurrentContext())->runner()->GetWeakPtr()),
-      weak_factory_(this) {
-  GetWrapper(runner_->GetContextHolder()->isolate())
-      .ToLocalChecked()
-      ->SetPrivate(isolate->GetCurrentContext(), GetHiddenPropertyName(isolate),
-                   function)
-      .FromJust();
-  timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(delay_ms),
-               base::Bind(&Timer::OnTimerFired, weak_factory_.GetWeakPtr()));
-}
-
-Timer::~Timer() = default;
-
-void Timer::OnTimerFired() {
-  // This can happen in spite of the weak callback because it is possible for
-  // a gin::Handle<> to keep this object alive past when the isolate it is part
-  // of is destroyed.
-  if (!runner_.get()) {
-    return;
-  }
-
-  Runner::Scope scope(runner_.get());
-  v8::Isolate* isolate = runner_->GetContextHolder()->isolate();
-
-  v8::Local<v8::Object> wrapper;
-  if (!GetWrapper(isolate).ToLocal(&wrapper)) {
-    return;
-  }
-
-  v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast(
-      wrapper
-          ->GetPrivate(runner_->GetContextHolder()->context(),
-                       GetHiddenPropertyName(isolate))
-          .ToLocalChecked());
-  runner_->Call(function, v8::Undefined(isolate), 0, NULL);
-}
-
-
-// TimerModule =================================================================
-
-const char TimerModule::kName[] = "timer";
-WrapperInfo TimerModule::kWrapperInfo = { kEmbedderNativeGin };
-
-// static
-Handle<TimerModule> TimerModule::Create(v8::Isolate* isolate) {
-  return CreateHandle(isolate, new TimerModule());
-}
-
-// static
-v8::Local<v8::Value> TimerModule::GetModule(v8::Isolate* isolate) {
-  return Create(isolate)->GetWrapper(isolate).ToLocalChecked();
-}
-
-TimerModule::TimerModule() = default;
-
-TimerModule::~TimerModule() = default;
-
-ObjectTemplateBuilder TimerModule::GetObjectTemplateBuilder(
-    v8::Isolate* isolate) {
-  return Wrappable<TimerModule>::GetObjectTemplateBuilder(isolate)
-      .SetMethod("createOneShot",
-                 base::Bind(&Timer::Create, Timer::TYPE_ONE_SHOT))
-      .SetMethod("createRepeating",
-                 base::Bind(&Timer::Create, Timer::TYPE_REPEATING));
-}
-
-}  // namespace gin
diff --git a/gin/modules/timer.h b/gin/modules/timer.h
deleted file mode 100644
index 1b7f613..0000000
--- a/gin/modules/timer.h
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef GIN_MODULES_TIMER_H_
-#define GIN_MODULES_TIMER_H_
-
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/timer/timer.h"
-#include "gin/gin_export.h"
-#include "gin/handle.h"
-#include "gin/runner.h"
-#include "gin/wrappable.h"
-#include "v8/include/v8.h"
-
-namespace gin {
-
-class ObjectTemplateBuilder;
-
-// A simple scriptable timer that can work in one-shot or repeating mode.
-class GIN_EXPORT Timer : public Wrappable<Timer> {
- public:
-  enum TimerType {
-    TYPE_ONE_SHOT,
-    TYPE_REPEATING
-  };
-
-  static WrapperInfo kWrapperInfo;
-  static Handle<Timer> Create(TimerType type, v8::Isolate* isolate,
-                              int delay_ms, v8::Local<v8::Function> function);
-
-  ObjectTemplateBuilder GetObjectTemplateBuilder(v8::Isolate* isolate) override;
-
- private:
-  Timer(v8::Isolate* isolate, bool repeating, int delay_ms,
-        v8::Local<v8::Function> function);
-  ~Timer() override;
-  void OnTimerFired();
-
-  base::Timer timer_;
-  base::WeakPtr<gin::Runner> runner_;
-  base::WeakPtrFactory<Timer> weak_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(Timer);
-};
-
-
-class GIN_EXPORT TimerModule : public Wrappable<TimerModule> {
- public:
-  static const char kName[];
-  static WrapperInfo kWrapperInfo;
-  static Handle<TimerModule> Create(v8::Isolate* isolate);
-  static v8::Local<v8::Value> GetModule(v8::Isolate* isolate);
-
- private:
-  TimerModule();
-  ~TimerModule() override;
-
-  ObjectTemplateBuilder GetObjectTemplateBuilder(v8::Isolate* isolate) override;
-};
-
-}  // namespace gin
-
-#endif  // GIN_MODULES_TIMER_H_
diff --git a/gin/modules/timer_unittest.cc b/gin/modules/timer_unittest.cc
deleted file mode 100644
index 2490d23..0000000
--- a/gin/modules/timer_unittest.cc
+++ /dev/null
@@ -1,148 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "gin/modules/timer.h"
-
-#include <memory>
-
-#include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
-#include "gin/handle.h"
-#include "gin/object_template_builder.h"
-#include "gin/public/isolate_holder.h"
-#include "gin/shell_runner.h"
-#include "gin/test/v8_test.h"
-#include "gin/try_catch.h"
-#include "gin/wrappable.h"
-#include "v8/include/v8.h"
-
-namespace gin {
-
-namespace {
-
-class Result : public Wrappable<Result> {
- public:
-  static WrapperInfo kWrapperInfo;
-  static Handle<Result> Create(v8::Isolate* isolate) {
-    return CreateHandle(isolate, new Result());
-  }
-
-  int count() const { return count_; }
-  void set_count(int count) { count_ = count; }
-
-  void Quit() { base::RunLoop::QuitCurrentDeprecated(); }
-
- private:
-  Result() : count_(0) {
-  }
-
-  ~Result() override = default;
-
-  ObjectTemplateBuilder GetObjectTemplateBuilder(
-      v8::Isolate* isolate) override {
-    return Wrappable<Result>::GetObjectTemplateBuilder(isolate)
-        .SetProperty("count", &Result::count, &Result::set_count)
-        .SetMethod("quit", &Result::Quit);
-  }
-
-  int count_;
-};
-
-WrapperInfo Result::kWrapperInfo = { gin::kEmbedderNativeGin };
-
-struct TestHelper {
-  TestHelper(v8::Isolate* isolate)
-      : runner(new ShellRunner(&delegate, isolate)),
-        scope(runner.get()),
-        timer_module(TimerModule::Create(isolate)),
-        result(Result::Create(isolate)) {
-    EXPECT_FALSE(runner->global().IsEmpty());
-    runner->global()->Set(StringToV8(isolate, "timer"),
-                          timer_module->GetWrapper(isolate).ToLocalChecked());
-    runner->global()->Set(StringToV8(isolate, "result"),
-                          result->GetWrapper(isolate).ToLocalChecked());
-  }
-
-  ShellRunnerDelegate delegate;
-  std::unique_ptr<ShellRunner> runner;
-  Runner::Scope scope;
-  Handle<TimerModule> timer_module;
-  Handle<Result> result;
-};
-
-}  // namespace
-
-typedef V8Test TimerUnittest;
-
-TEST_F(TimerUnittest, OneShot) {
-  TestHelper helper(instance_->isolate());
-  std::string source =
-     "timer.createOneShot(0, function() {"
-     "  result.count++;"
-     "});";
-
-  helper.runner->Run(source, "script");
-  EXPECT_EQ(0, helper.result->count());
-
-  base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(1, helper.result->count());
-}
-
-TEST_F(TimerUnittest, OneShotCancel) {
-  TestHelper helper(instance_->isolate());
-  std::string source =
-     "var t = timer.createOneShot(0, function() {"
-     "  result.count++;"
-     "});"
-     "t.cancel()";
-
-  helper.runner->Run(source, "script");
-  EXPECT_EQ(0, helper.result->count());
-
-  base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(0, helper.result->count());
-}
-
-TEST_F(TimerUnittest, Repeating) {
-  TestHelper helper(instance_->isolate());
-
-  // TODO(aa): Cannot do: if (++result.count == 3) because of v8 bug. Create
-  // test case and report.
-  std::string source =
-      "var t = timer.createRepeating(0, function() {"
-      "  result.count++;"
-      "  if (result.count == 3) {"
-      "    /* Cancel the timer to prevent a hang when ScopedTaskEnvironment "
-      "       flushes main thread tasks. */"
-      "    t.cancel();"
-      "    result.quit();"
-      "  }"
-      "});";
-
-  helper.runner->Run(source, "script");
-  EXPECT_EQ(0, helper.result->count());
-
-  base::RunLoop().Run();
-  EXPECT_EQ(3, helper.result->count());
-}
-
-TEST_F(TimerUnittest, TimerCallbackToDestroyedRunner) {
-  TestHelper helper(instance_->isolate());
-  std::string source =
-     "timer.createOneShot(0, function() {"
-     "  result.count++;"
-     "});";
-
-  helper.runner->Run(source, "script");
-  EXPECT_EQ(0, helper.result->count());
-
-  // Destroy runner, which should destroy the timer object we created.
-  helper.runner.reset(NULL);
-  base::RunLoop().RunUntilIdle();
-
-  // Timer should not have run because it was deleted.
-  EXPECT_EQ(0, helper.result->count());
-}
-
-}  // namespace gin
diff --git a/gin/runner.h b/gin/runner.h
index a898b03..928275d5 100644
--- a/gin/runner.h
+++ b/gin/runner.h
@@ -25,10 +25,6 @@
   // context by creating an instance of Runner::Scope on the stack.
   virtual void Run(const std::string& source,
                    const std::string& resource_name) = 0;
-  virtual v8::Local<v8::Value> Call(v8::Local<v8::Function> function,
-                                     v8::Local<v8::Value> receiver,
-                                     int argc,
-                                     v8::Local<v8::Value> argv[]) = 0;
   virtual ContextHolder* GetContextHolder() = 0;
 
   v8::Local<v8::Object> global() {
diff --git a/gin/shell/gin_main.cc b/gin/shell/gin_main.cc
index a28ca155..12c74b8 100644
--- a/gin/shell/gin_main.cc
+++ b/gin/shell/gin_main.cc
@@ -18,8 +18,9 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "gin/array_buffer.h"
 #include "gin/modules/console.h"
-#include "gin/modules/module_runner_delegate.h"
+#include "gin/object_template_builder.h"
 #include "gin/public/isolate_holder.h"
+#include "gin/shell_runner.h"
 #include "gin/try_catch.h"
 #include "gin/v8_initializer.h"
 
@@ -40,20 +41,20 @@
   runner->Run(Load(path), path.AsUTF8Unsafe());
 }
 
-std::vector<base::FilePath> GetModuleSearchPaths() {
-  std::vector<base::FilePath> module_base(1);
-  CHECK(base::GetCurrentDirectory(&module_base[0]));
-  return module_base;
-}
-
-class GinShellRunnerDelegate : public ModuleRunnerDelegate {
+class GinShellRunnerDelegate : public ShellRunnerDelegate {
  public:
-  GinShellRunnerDelegate() : ModuleRunnerDelegate(GetModuleSearchPaths()) {
-    AddBuiltinModule(Console::kModuleName, Console::GetModule);
+  GinShellRunnerDelegate() {}
+
+  v8::Local<v8::ObjectTemplate> GetGlobalTemplate(
+      ShellRunner* runner,
+      v8::Isolate* isolate) override {
+    v8::Local<v8::ObjectTemplate> templ =
+        ObjectTemplateBuilder(isolate).Build();
+    gin::Console::Register(isolate, templ);
+    return templ;
   }
 
   void UnhandledException(ShellRunner* runner, TryCatch& try_catch) override {
-    ModuleRunnerDelegate::UnhandledException(runner, try_catch);
     LOG(ERROR) << try_catch.GetStackTrace();
   }
 
diff --git a/gin/shell/hello_world.js b/gin/shell/hello_world.js
index 7216fbd1..6f091000 100644
--- a/gin/shell/hello_world.js
+++ b/gin/shell/hello_world.js
@@ -2,6 +2,4 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-define(["console"], function(console) {
-  console.log("Hello World");
-});
+log("Hello World");
diff --git a/gin/shell_runner.cc b/gin/shell_runner.cc
index b98240a1..f052428 100644
--- a/gin/shell_runner.cc
+++ b/gin/shell_runner.cc
@@ -5,7 +5,6 @@
 #include "gin/shell_runner.h"
 
 #include "gin/converter.h"
-#include "gin/modules/module_registry.h"
 #include "gin/per_context_data.h"
 #include "gin/public/context_holder.h"
 #include "gin/try_catch.h"
@@ -76,24 +75,6 @@
   Run(script);
 }
 
-v8::Local<v8::Value> ShellRunner::Call(v8::Local<v8::Function> function,
-                                        v8::Local<v8::Value> receiver,
-                                        int argc,
-                                        v8::Local<v8::Value> argv[]) {
-  TryCatch try_catch(GetContextHolder()->isolate());
-  delegate_->WillRunScript(this);
-
-  auto maybe_result =
-      function->Call(GetContextHolder()->context(), receiver, argc, argv);
-
-  delegate_->DidRunScript(this);
-  v8::Local<v8::Value> result;
-  if (!maybe_result.ToLocal(&result))
-    delegate_->UnhandledException(this, try_catch);
-
-  return result;
-}
-
 ContextHolder* ShellRunner::GetContextHolder() {
   return context_holder_.get();
 }
diff --git a/gin/shell_runner.h b/gin/shell_runner.h
index f7651f0..10c92df 100644
--- a/gin/shell_runner.h
+++ b/gin/shell_runner.h
@@ -48,10 +48,6 @@
   // Runner overrides:
   void Run(const std::string& source,
            const std::string& resource_name) override;
-  v8::Local<v8::Value> Call(v8::Local<v8::Function> function,
-                             v8::Local<v8::Value> receiver,
-                             int argc,
-                             v8::Local<v8::Value> argv[]) override;
   ContextHolder* GetContextHolder() override;
 
  private:
diff --git a/gin/test/expect.js b/gin/test/expect.js
deleted file mode 100644
index 597b5b1..0000000
--- a/gin/test/expect.js
+++ /dev/null
@@ -1,299 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-define(function() {
-  // Equality function based on isEqual in
-  // Underscore.js 1.5.2
-  // http://underscorejs.org
-  // (c) 2009-2013 Jeremy Ashkenas,
-  //               DocumentCloud,
-  //               and Investigative Reporters & Editors
-  // Underscore may be freely distributed under the MIT license.
-  //
-  function has(obj, key) {
-    return obj.hasOwnProperty(key);
-  }
-  function isFunction(obj) {
-    return typeof obj === 'function';
-  }
-  function isArrayBufferClass(className) {
-    return className == '[object ArrayBuffer]' ||
-        className.match(/\[object \w+\d+(Clamped)?Array\]/);
-  }
-  // Internal recursive comparison function for `isEqual`.
-  function eq(a, b, aStack, bStack) {
-    // Identical objects are equal. `0 === -0`, but they aren't identical.
-    // See the Harmony `egal` proposal:
-    // http://wiki.ecmascript.org/doku.php?id=harmony:egal.
-    if (a === b)
-      return a !== 0 || 1 / a == 1 / b;
-    // A strict comparison is necessary because `null == undefined`.
-    if (a == null || b == null)
-      return a === b;
-    // Compare `[[Class]]` names.
-    var className = toString.call(a);
-    if (className != toString.call(b))
-      return false;
-    switch (className) {
-      // Strings, numbers, dates, and booleans are compared by value.
-      case '[object String]':
-        // Primitives and their corresponding object wrappers are equivalent;
-        // thus, `"5"` is equivalent to `new String("5")`.
-        return a == String(b);
-      case '[object Number]':
-        // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is
-        // performed for other numeric values.
-        return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b);
-      case '[object Date]':
-      case '[object Boolean]':
-        // Coerce dates and booleans to numeric primitive values. Dates are
-        // compared by their millisecond representations. Note that invalid
-        // dates with millisecond representations of `NaN` are not equivalent.
-        return +a == +b;
-      // RegExps are compared by their source patterns and flags.
-      case '[object RegExp]':
-        return a.source == b.source &&
-               a.global == b.global &&
-               a.multiline == b.multiline &&
-               a.ignoreCase == b.ignoreCase;
-    }
-    if (typeof a != 'object' || typeof b != 'object')
-      return false;
-    // Assume equality for cyclic structures. The algorithm for detecting
-    // cyclic structures is adapted from ES 5.1 section 15.12.3, abstract
-    // operation `JO`.
-    var length = aStack.length;
-    while (length--) {
-      // Linear search. Performance is inversely proportional to the number of
-      // unique nested structures.
-      if (aStack[length] == a)
-        return bStack[length] == b;
-    }
-    // Objects with different constructors are not equivalent, but `Object`s
-    // from different frames are.
-    var aCtor = a.constructor, bCtor = b.constructor;
-    if (aCtor !== bCtor && !(isFunction(aCtor) && (aCtor instanceof aCtor) &&
-                             isFunction(bCtor) && (bCtor instanceof bCtor))
-                        && ('constructor' in a && 'constructor' in b)) {
-      return false;
-    }
-    // Add the first object to the stack of traversed objects.
-    aStack.push(a);
-    bStack.push(b);
-    var size = 0, result = true;
-    // Recursively compare Maps, objects and arrays.
-    if (className == '[object Array]' || isArrayBufferClass(className)) {
-      // Compare array lengths to determine if a deep comparison is necessary.
-      size = a.length;
-      result = size == b.length;
-      if (result) {
-        // Deep compare the contents, ignoring non-numeric properties.
-        while (size--) {
-          if (!(result = eq(a[size], b[size], aStack, bStack)))
-            break;
-        }
-      }
-    } else if (className == '[object Map]') {
-      result = a.size == b.size;
-      if (result) {
-        var entries = a.entries();
-        for (var e = entries.next(); result && !e.done; e = entries.next()) {
-          var key = e.value[0];
-          var value = e.value[1];
-          result = b.has(key) && eq(value, b.get(key), aStack, bStack);
-        }
-      }
-    } else {
-      // Deep compare objects.
-      for (var key in a) {
-        if (has(a, key)) {
-          // Count the expected number of properties.
-          size++;
-          // Deep compare each member.
-          if (!(result = has(b, key) && eq(a[key], b[key], aStack, bStack)))
-            break;
-        }
-      }
-      // Ensure that both objects contain the same number of properties.
-      if (result) {
-        for (key in b) {
-          if (has(b, key) && !(size--))
-            break;
-        }
-        result = !size;
-      }
-    }
-    // Remove the first object from the stack of traversed objects.
-    aStack.pop();
-    bStack.pop();
-    return result;
-  };
-
-  function describe(subjects) {
-    var descriptions = [];
-    Object.getOwnPropertyNames(subjects).forEach(function(name) {
-      if (name === "Description")
-        descriptions.push(subjects[name]);
-      else
-        descriptions.push(name + ": " + JSON.stringify(subjects[name]));
-    });
-    return descriptions.join(" ");
-  }
-
-  var predicates = {};
-
-  predicates.toBe = function(actual, expected) {
-    return {
-      "result": actual === expected,
-      "message": describe({
-        "Actual": actual,
-        "Expected": expected,
-      }),
-    };
-  };
-
-  predicates.toEqual = function(actual, expected) {
-    return {
-      "result": eq(actual, expected, [], []),
-      "message": describe({
-        "Actual": actual,
-        "Expected": expected,
-      }),
-    };
-  };
-
-  predicates.toBeDefined = function(actual) {
-    return {
-      "result": typeof actual !== "undefined",
-      "message": describe({
-        "Actual": actual,
-        "Description": "Expected a defined value",
-      }),
-    };
-  };
-
-  predicates.toBeUndefined = function(actual) {
-    // Recall: undefined is just a global variable. :)
-    return {
-      "result": typeof actual === "undefined",
-      "message": describe({
-        "Actual": actual,
-        "Description": "Expected an undefined value",
-      }),
-    };
-  };
-
-  predicates.toBeNull = function(actual) {
-    // Recall: typeof null === "object".
-    return {
-      "result": actual === null,
-      "message": describe({
-        "Actual": actual,
-        "Expected": null,
-      }),
-    };
-  };
-
-  predicates.toBeTruthy = function(actual) {
-    return {
-      "result": !!actual,
-      "message": describe({
-        "Actual": actual,
-        "Description": "Expected a truthy value",
-      }),
-    };
-  };
-
-  predicates.toBeFalsy = function(actual) {
-    return {
-      "result": !!!actual,
-      "message": describe({
-        "Actual": actual,
-        "Description": "Expected a falsy value",
-      }),
-    };
-  };
-
-  predicates.toContain = function(actual, element) {
-    return {
-      "result": (function () {
-        for (var i = 0; i < actual.length; ++i) {
-          if (eq(actual[i], element, [], []))
-            return true;
-        }
-        return false;
-      })(),
-      "message": describe({
-        "Actual": actual,
-        "Element": element,
-      }),
-    };
-  };
-
-  predicates.toBeLessThan = function(actual, reference) {
-    return {
-      "result": actual < reference,
-      "message": describe({
-        "Actual": actual,
-        "Reference": reference,
-      }),
-    };
-  };
-
-  predicates.toBeGreaterThan = function(actual, reference) {
-    return {
-      "result": actual > reference,
-      "message": describe({
-        "Actual": actual,
-        "Reference": reference,
-      }),
-    };
-  };
-
-  predicates.toThrow = function(actual) {
-    return {
-      "result": (function () {
-        if (!isFunction(actual))
-          throw new TypeError;
-        try {
-          actual();
-        } catch (ex) {
-          return true;
-        }
-        return false;
-      })(),
-      "message": "Expected function to throw",
-    };
-  }
-
-  function negate(predicate) {
-    return function() {
-      var outcome = predicate.apply(null, arguments);
-      outcome.result = !outcome.result;
-      return outcome;
-    }
-  }
-
-  function check(predicate) {
-    return function() {
-      var outcome = predicate.apply(null, arguments);
-      if (outcome.result)
-        return;
-      throw outcome.message;
-    };
-  }
-
-  function Condition(actual) {
-    this.not = {};
-    Object.getOwnPropertyNames(predicates).forEach(function(name) {
-      var bound = predicates[name].bind(null, actual);
-      this[name] = check(bound);
-      this.not[name] = check(negate(bound));
-    }, this);
-  }
-
-  return function(actual) {
-    return new Condition(actual);
-  };
-});
diff --git a/gin/test/file.cc b/gin/test/file.cc
deleted file mode 100644
index 38efbb4..0000000
--- a/gin/test/file.cc
+++ /dev/null
@@ -1,88 +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 "gin/test/file.h"
-
-#include <iostream>
-
-#include "base/bind.h"
-#include "base/files/file_enumerator.h"
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/path_service.h"
-#include "gin/arguments.h"
-#include "gin/converter.h"
-#include "gin/object_template_builder.h"
-#include "gin/per_isolate_data.h"
-#include "gin/public/wrapper_info.h"
-
-using v8::ObjectTemplate;
-
-namespace gin {
-
-namespace {
-
-v8::Local<v8::Value> ReadFileToString(gin::Arguments* args) {
-  std::string filename;
-  if (!args->GetNext(&filename))
-    return v8::Null(args->isolate());
-
-  const base::FilePath& path = base::FilePath::FromUTF8Unsafe(filename);
-  std::string contents;
-  if (!ReadFileToString(path, &contents))
-    return v8::Null(args->isolate());
-
-  return gin::Converter<std::string>::ToV8(args->isolate(), contents);
-}
-
-v8::Local<v8::Value> GetSourceRootDirectory(gin::Arguments* args) {
-  base::FilePath path;
-  if (!PathService::Get(base::DIR_SOURCE_ROOT, &path))
-    return v8::Null(args->isolate());
-  return gin::Converter<std::string>::ToV8(args->isolate(),
-                                           path.AsUTF8Unsafe());
-}
-
-v8::Local<v8::Value> GetFilesInDirectory(gin::Arguments* args) {
-  std::string filename;
-  if (!args->GetNext(&filename))
-    return v8::Null(args->isolate());
-
-  const base::FilePath& path = base::FilePath::FromUTF8Unsafe(filename);
-  if (!base::DirectoryExists(path))
-    return v8::Null(args->isolate());
-
-  std::vector<std::string> names;
-  base::FileEnumerator e(path, false, base::FileEnumerator::FILES);
-  for (base::FilePath name = e.Next(); !name.empty(); name = e.Next()) {
-    names.push_back(name.BaseName().AsUTF8Unsafe());
-  }
-
-  v8::Local<v8::Value> v8_names;
-  if (!TryConvertToV8(args->isolate(), names, &v8_names))
-    return v8::Null(args->isolate());
-  return v8_names;
-}
-
-gin::WrapperInfo g_wrapper_info = { gin::kEmbedderNativeGin };
-
-}  // namespace
-
-const char File::kModuleName[] = "file";
-
-v8::Local<v8::Value> File::GetModule(v8::Isolate* isolate) {
-  gin::PerIsolateData* data = gin::PerIsolateData::From(isolate);
-  v8::Local<ObjectTemplate> templ = data->GetObjectTemplate(&g_wrapper_info);
-  if (templ.IsEmpty()) {
-    templ = gin::ObjectTemplateBuilder(isolate)
-        .SetMethod("readFileToString", ReadFileToString)
-        .SetMethod("getFilesInDirectory", GetFilesInDirectory)
-        .SetMethod("getSourceRootDirectory", GetSourceRootDirectory)
-        .Build();
-    data->SetObjectTemplate(&g_wrapper_info, templ);
-  }
-  return templ->NewInstance();
-}
-
-}  // namespace gin
diff --git a/gin/test/file.h b/gin/test/file.h
deleted file mode 100644
index a4acd59..0000000
--- a/gin/test/file.h
+++ /dev/null
@@ -1,21 +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 GIN_TEST_FILE_H_
-#define GIN_TEST_FILE_H_
-
-#include "v8/include/v8.h"
-
-namespace gin {
-
-class File {
- public:
-  static const char kModuleName[];
-  static v8::Local<v8::Value> GetModule(v8::Isolate* isolate);
-};
-
-}  // namespace gin
-
-#endif  // GIN_TEST_FILE_H_
-
diff --git a/gin/test/file_runner.cc b/gin/test/file_runner.cc
deleted file mode 100644
index 39ece62..0000000
--- a/gin/test/file_runner.cc
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "gin/test/file_runner.h"
-
-#include "base/files/file_util.h"
-#include "base/path_service.h"
-#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "gin/array_buffer.h"
-#include "gin/converter.h"
-#include "gin/modules/console.h"
-#include "gin/modules/module_registry.h"
-#include "gin/public/context_holder.h"
-#include "gin/public/isolate_holder.h"
-#include "gin/test/file.h"
-#include "gin/test/gc.h"
-#include "gin/test/gtest.h"
-#include "gin/try_catch.h"
-#include "gin/v8_initializer.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace gin {
-
-namespace {
-
-std::vector<base::FilePath> GetModuleSearchPaths() {
-  std::vector<base::FilePath> search_paths(2);
-  PathService::Get(base::DIR_SOURCE_ROOT, &search_paths[0]);
-  PathService::Get(base::DIR_EXE, &search_paths[1]);
-  search_paths[1] = search_paths[1].AppendASCII("gen");
-  return search_paths;
-}
-
-}  // namespace
-
-FileRunnerDelegate::FileRunnerDelegate()
-    : ModuleRunnerDelegate(GetModuleSearchPaths()) {
-  AddBuiltinModule(Console::kModuleName, Console::GetModule);
-  AddBuiltinModule(GTest::kModuleName, GTest::GetModule);
-  AddBuiltinModule(GC::kModuleName, GC::GetModule);
-  AddBuiltinModule(File::kModuleName, File::GetModule);
-}
-
-FileRunnerDelegate::~FileRunnerDelegate() = default;
-
-void FileRunnerDelegate::UnhandledException(ShellRunner* runner,
-                                            TryCatch& try_catch) {
-  ModuleRunnerDelegate::UnhandledException(runner, try_catch);
-  FAIL() << try_catch.GetStackTrace();
-}
-
-void RunTestFromFile(const base::FilePath& path, FileRunnerDelegate* delegate,
-                     bool run_until_idle) {
-  ASSERT_TRUE(base::PathExists(path)) << path.LossyDisplayName();
-  std::string source;
-  ASSERT_TRUE(ReadFileToString(path, &source));
-
-  base::test::ScopedTaskEnvironment scoped_task_environment;
-
-#ifdef V8_USE_EXTERNAL_STARTUP_DATA
-  gin::V8Initializer::LoadV8Snapshot();
-  gin::V8Initializer::LoadV8Natives();
-#ifdef USE_V8_CONTEXT_SNAPSHOT
-  gin::V8Initializer::LoadV8ContextSnapshot();
-#endif  // USE_V8_CONTEXT_SNAPSHOT
-#endif  // V8_USE_EXTERNAL_STARTUP_DATA
-
-  gin::IsolateHolder::Initialize(gin::IsolateHolder::kStrictMode,
-                                 gin::IsolateHolder::kStableV8Extras,
-                                 gin::ArrayBufferAllocator::SharedInstance());
-
-  gin::IsolateHolder instance(base::ThreadTaskRunnerHandle::Get());
-  gin::ShellRunner runner(delegate, instance.isolate());
-  {
-    gin::Runner::Scope scope(&runner);
-    instance.isolate()->SetCaptureStackTraceForUncaughtExceptions(true);
-    runner.Run(source, path.AsUTF8Unsafe());
-
-    if (run_until_idle) {
-      base::RunLoop().RunUntilIdle();
-    } else {
-      base::RunLoop().Run();
-    }
-
-    v8::Local<v8::Value> result = runner.global()->Get(
-        StringToSymbol(runner.GetContextHolder()->isolate(), "result"));
-    EXPECT_EQ("PASS", V8ToString(result));
-  }
-}
-
-}  // namespace gin
diff --git a/gin/test/file_runner.h b/gin/test/file_runner.h
deleted file mode 100644
index b20859a..0000000
--- a/gin/test/file_runner.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef GIN_TEST_FILE_RUNNER_H_
-#define GIN_TEST_FILE_RUNNER_H_
-
-#include "base/compiler_specific.h"
-#include "base/files/file_path.h"
-#include "base/macros.h"
-#include "gin/modules/module_runner_delegate.h"
-#include "gin/runner.h"
-
-namespace gin {
-
-// FileRunnerDelegate is a simple RunnerDelegate that's useful for running
-// tests. The FileRunnerDelegate provides built-in modules for "console" and
-// "gtest" that are useful when writing unit tests.
-//
-// TODO(abarth): Rename FileRunnerDelegate to TestRunnerDelegate.
-class FileRunnerDelegate : public ModuleRunnerDelegate {
- public:
-  FileRunnerDelegate();
-  ~FileRunnerDelegate() override;
-
- private:
-  // From ModuleRunnerDelegate:
-  void UnhandledException(ShellRunner* runner, TryCatch& try_catch) override;
-
-  DISALLOW_COPY_AND_ASSIGN(FileRunnerDelegate);
-};
-
-void RunTestFromFile(const base::FilePath& path, FileRunnerDelegate* delegate,
-                     bool run_until_idle = true);
-
-}  // namespace gin
-
-#endif  // GIN_TEST_FILE_RUNNER_H_
diff --git a/gin/test/file_unittests.js b/gin/test/file_unittests.js
deleted file mode 100644
index 8c25806..0000000
--- a/gin/test/file_unittests.js
+++ /dev/null
@@ -1,37 +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.
-
-define([
-    "gin/test/expect",
-    "file"
-  ], function(expect, file) {
-
-  function isString(x) {
-    return toString.call(x) === '[object String]'
-  }
-
-  var rootDir = file.getSourceRootDirectory();
-  expect(isString(rootDir)).toBeTruthy();
-
-  var noArgsNull = file.getFilesInDirectory();
-  expect(noArgsNull).toBeNull();
-
-  var files = file.getFilesInDirectory(rootDir);
-  expect(Array.isArray(files)).toBeTruthy();
-
-  var nsdNull = file.getFilesInDirectory(rootDir + "/no_such_dir");
-  expect(nsdNull).toBeNull();
-
-  var owners = file.readFileToString(rootDir + "/OWNERS");
-  expect(isString(owners)).toBeTruthy();
-  expect(owners.length).toBeGreaterThan(0);
-
-  noArgsNull = file.readFileToString();
-  expect(noArgsNull).toBeNull();
-
-  var nsfNull = file.readFileToString(rootDir + "/no_such_file");
-  expect(nsfNull).toBeNull();
-
-  this.result = "PASS";
-});
diff --git a/gin/test/gc.cc b/gin/test/gc.cc
deleted file mode 100644
index 4cd67e19..0000000
--- a/gin/test/gc.cc
+++ /dev/null
@@ -1,41 +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 "gin/test/gc.h"
-
-#include "base/bind.h"
-#include "base/logging.h"
-#include "gin/arguments.h"
-#include "gin/converter.h"
-#include "gin/function_template.h"
-#include "gin/object_template_builder.h"
-#include "gin/per_isolate_data.h"
-#include "gin/public/wrapper_info.h"
-#include "gin/wrappable.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace gin {
-
-namespace {
-WrapperInfo g_wrapper_info = { kEmbedderNativeGin };
-}  // namespace
-
-const char GC::kModuleName[] = "gc";
-
-v8::Local<v8::Value> GC::GetModule(v8::Isolate* isolate) {
-  PerIsolateData* data = PerIsolateData::From(isolate);
-  v8::Local<v8::ObjectTemplate> templ =
-      data->GetObjectTemplate(&g_wrapper_info);
-  if (templ.IsEmpty()) {
-    templ = ObjectTemplateBuilder(isolate)
-        .SetMethod("collectGarbage",
-                   base::Bind(&v8::Isolate::LowMemoryNotification,
-                              base::Unretained(isolate)))
-        .Build();
-    data->SetObjectTemplate(&g_wrapper_info, templ);
-  }
-  return templ->NewInstance();
-}
-
-}  // namespace gin
diff --git a/gin/test/gc.h b/gin/test/gc.h
deleted file mode 100644
index 25917ef..0000000
--- a/gin/test/gc.h
+++ /dev/null
@@ -1,21 +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 GIN_TEST_GC_H_
-#define GIN_TEST_GC_H_
-
-#include "v8/include/v8.h"
-
-namespace gin {
-
-// This module provides bindings to the garbage collector.
-class GC {
- public:
-  static const char kModuleName[];
-  static v8::Local<v8::Value> GetModule(v8::Isolate* isolate);
-};
-
-}  // namespace gin
-
-#endif  // GIN_TEST_GC_H_
diff --git a/gin/test/gtest.cc b/gin/test/gtest.cc
deleted file mode 100644
index 76aaf1f..0000000
--- a/gin/test/gtest.cc
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "gin/test/gtest.h"
-
-#include "base/bind.h"
-#include "base/logging.h"
-#include "gin/arguments.h"
-#include "gin/converter.h"
-#include "gin/function_template.h"
-#include "gin/object_template_builder.h"
-#include "gin/per_isolate_data.h"
-#include "gin/public/wrapper_info.h"
-#include "gin/wrappable.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace gin {
-
-namespace {
-
-void Fail(const std::string& description) {
-  FAIL() << description;
-}
-
-void ExpectTrue(bool condition, const std::string& description) {
-  EXPECT_TRUE(condition) << description;
-}
-
-void ExpectFalse(bool condition, const std::string& description) {
-  EXPECT_FALSE(condition) << description;
-}
-
-void ExpectEqual(const v8::Local<v8::Value> expected,
-                 const v8::Local<v8::Value> actual,
-                 const std::string& description) {
-  EXPECT_TRUE(expected->StrictEquals(actual)) << description;
-}
-
-WrapperInfo g_wrapper_info = { kEmbedderNativeGin };
-
-}  // namespace
-
-const char GTest::kModuleName[] = "gtest";
-
-v8::Local<v8::Value> GTest::GetModule(v8::Isolate* isolate) {
-  PerIsolateData* data = PerIsolateData::From(isolate);
-  v8::Local<v8::ObjectTemplate> templ =
-      data->GetObjectTemplate(&g_wrapper_info);
-  if (templ.IsEmpty()) {
-    templ = ObjectTemplateBuilder(isolate)
-        .SetMethod("fail", Fail)
-        .SetMethod("expectTrue", ExpectTrue)
-        .SetMethod("expectFalse", ExpectFalse)
-        .SetMethod("expectEqual", ExpectEqual)
-        .Build();
-    data->SetObjectTemplate(&g_wrapper_info, templ);
-  }
-  return templ->NewInstance();
-}
-
-}  // namespace gin
diff --git a/gin/test/gtest.h b/gin/test/gtest.h
deleted file mode 100644
index 8f4332d0..0000000
--- a/gin/test/gtest.h
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef GIN_TEST_GTEST_H_
-#define GIN_TEST_GTEST_H_
-
-#include "v8/include/v8.h"
-
-namespace gin {
-
-// This module provides bindings to gtest. Most tests should use an idiomatic
-// JavaScript testing API, but this module is available for tests that need a
-// low-level integration with gtest.
-class GTest {
- public:
-  static const char kModuleName[];
-  static v8::Local<v8::Value> GetModule(v8::Isolate* isolate);
-};
-
-}  // namespace gin
-
-#endif  // GIN_TEST_GTEST_H_
diff --git a/gin/test/gtest_unittests.js b/gin/test/gtest_unittests.js
deleted file mode 100644
index 1d566d5..0000000
--- a/gin/test/gtest_unittests.js
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-define(["gtest"], function(gtest) {
-  gtest.expectTrue(true, "true is true");
-  gtest.expectFalse(false, "false is false");
-  gtest.expectTrue(this, "this is " + this);
-
-  this.result = "PASS";
-});
diff --git a/gin/test/run_js_tests.cc b/gin/test/run_js_tests.cc
deleted file mode 100644
index b83dc9f2..0000000
--- a/gin/test/run_js_tests.cc
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/files/file_util.h"
-#include "base/path_service.h"
-#include "gin/test/file_runner.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace gin {
-namespace {
-
-base::FilePath BasePath() {
-  base::FilePath path;
-  PathService::Get(base::DIR_SOURCE_ROOT, &path);
-  return path.AppendASCII("gin");
-}
-
-void RunTest(const base::FilePath& path) {
-  FileRunnerDelegate delegate;
-  RunTestFromFile(path, &delegate);
-}
-
-TEST(JSTest, File) {
-  RunTest(BasePath()
-          .AppendASCII("test")
-          .AppendASCII("file_unittests.js"));
-}
-
-TEST(JSTest, GTest) {
-  RunTest(BasePath()
-          .AppendASCII("test")
-          .AppendASCII("gtest_unittests.js"));
-}
-
-TEST(JSTest, ModuleRegistry) {
-  RunTest(BasePath()
-          .AppendASCII("modules")
-          .AppendASCII("module_registry_unittests.js"));
-}
-
-}  // namespace
-}  // gin
diff --git a/ios/chrome/app/main_controller.mm b/ios/chrome/app/main_controller.mm
index fc999c3ff..ebefb77 100644
--- a/ios/chrome/app/main_controller.mm
+++ b/ios/chrome/app/main_controller.mm
@@ -114,7 +114,7 @@
 #import "ios/chrome/browser/ui/commands/open_url_command.h"
 #import "ios/chrome/browser/ui/commands/show_signin_command.h"
 #import "ios/chrome/browser/ui/commands/start_voice_search_command.h"
-#import "ios/chrome/browser/ui/download/download_manager_controller.h"
+#import "ios/chrome/browser/ui/download/legacy_download_manager_controller.h"
 #import "ios/chrome/browser/ui/external_file_remover_factory.h"
 #import "ios/chrome/browser/ui/external_file_remover_impl.h"
 #import "ios/chrome/browser/ui/first_run/first_run_util.h"
@@ -1138,7 +1138,7 @@
   [[DeferredInitializationRunner sharedInstance]
       enqueueBlockNamed:kDeleteDownloads
                   block:^{
-                    [DownloadManagerController clearDownloadsDirectory];
+                    [LegacyDownloadManagerController clearDownloadsDirectory];
                   }];
 }
 
diff --git a/ios/chrome/browser/prerender/BUILD.gn b/ios/chrome/browser/prerender/BUILD.gn
index 64f3b1c..160f1cf3 100644
--- a/ios/chrome/browser/prerender/BUILD.gn
+++ b/ios/chrome/browser/prerender/BUILD.gn
@@ -62,6 +62,7 @@
   ]
   deps = [
     "//base",
+    "//ios/chrome/browser/ui:ui_util",
     "//ios/chrome/browser/ui/content_suggestions:content_suggestions_constant",
     "//ios/chrome/browser/ui/omnibox:omnibox_internal",
     "//ios/chrome/test/app:test_support",
diff --git a/ios/chrome/browser/prerender/prerender_egtest.mm b/ios/chrome/browser/prerender/prerender_egtest.mm
index 5bbcbe8..98b2bc66 100644
--- a/ios/chrome/browser/prerender/prerender_egtest.mm
+++ b/ios/chrome/browser/prerender/prerender_egtest.mm
@@ -10,6 +10,7 @@
 #import "ios/chrome/browser/ui/content_suggestions/ntp_home_constant.h"
 #import "ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.h"
 #import "ios/chrome/browser/ui/omnibox/truncating_attributed_label.h"
+#include "ios/chrome/browser/ui/ui_util.h"
 #import "ios/chrome/test/app/history_test_util.h"
 #import "ios/chrome/test/app/tab_test_util.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
@@ -52,6 +53,15 @@
 
 // Test that tapping the prerendered suggestions opens it.
 - (void)testTapPrerenderSuggestions {
+  // TODO(crbug.com/793306): Re-enable the test on iOS 11 iPad once the
+  // alternate letters problem is fixed.
+  if (IsIPadIdiom()) {
+    if (@available(iOS 11, *)) {
+      EARL_GREY_TEST_DISABLED(
+          @"Disabled for iPad due to alternate letters educational screen.");
+    }
+  }
+
   chrome_test_util::ClearBrowsingHistory();
   [[GREYUIThreadExecutor sharedInstance] drainUntilIdle];
   // Set server up.
diff --git a/ios/chrome/browser/ui/BUILD.gn b/ios/chrome/browser/ui/BUILD.gn
index b815387..698f69f 100644
--- a/ios/chrome/browser/ui/BUILD.gn
+++ b/ios/chrome/browser/ui/BUILD.gn
@@ -318,6 +318,7 @@
     "//ios/chrome/browser/ui/fullscreen",
     "//ios/chrome/browser/ui/fullscreen:legacy_fullscreen",
     "//ios/chrome/browser/ui/fullscreen:new_fullscreen",
+    "//ios/chrome/browser/ui/fullscreen:new_fullscreen_ui",
     "//ios/chrome/browser/ui/history",
     "//ios/chrome/browser/ui/history_popup:coordinator",
     "//ios/chrome/browser/ui/history_popup/requirements",
diff --git a/ios/chrome/browser/ui/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view_controller.mm
index 95453e9a..7c512768 100644
--- a/ios/chrome/browser/ui/browser_view_controller.mm
+++ b/ios/chrome/browser/ui/browser_view_controller.mm
@@ -138,7 +138,7 @@
 #import "ios/chrome/browser/ui/context_menu/context_menu_coordinator.h"
 #import "ios/chrome/browser/ui/dialogs/dialog_presenter.h"
 #import "ios/chrome/browser/ui/dialogs/java_script_dialog_presenter_impl.h"
-#import "ios/chrome/browser/ui/download/download_manager_controller.h"
+#import "ios/chrome/browser/ui/download/legacy_download_manager_controller.h"
 #import "ios/chrome/browser/ui/elements/activity_overlay_coordinator.h"
 #import "ios/chrome/browser/ui/external_file_controller.h"
 #import "ios/chrome/browser/ui/external_search/external_search_coordinator.h"
@@ -147,6 +147,9 @@
 #import "ios/chrome/browser/ui/fullscreen/fullscreen_controller.h"
 #import "ios/chrome/browser/ui/fullscreen/fullscreen_controller_factory.h"
 #import "ios/chrome/browser/ui/fullscreen/fullscreen_features.h"
+#import "ios/chrome/browser/ui/fullscreen/fullscreen_scroll_end_animator.h"
+#import "ios/chrome/browser/ui/fullscreen/fullscreen_ui_element.h"
+#import "ios/chrome/browser/ui/fullscreen/fullscreen_ui_updater.h"
 #import "ios/chrome/browser/ui/fullscreen/legacy_fullscreen_controller.h"
 #import "ios/chrome/browser/ui/history_popup/requirements/tab_history_presentation.h"
 #import "ios/chrome/browser/ui/history_popup/tab_history_legacy_coordinator.h"
@@ -397,6 +400,7 @@
                                     CRWNativeContentProvider,
                                     CRWWebStateDelegate,
                                     DialogPresenterDelegate,
+                                    FullscreenUIElement,
                                     LegacyFullscreenControllerDelegate,
                                     InfobarContainerStateDelegate,
                                     KeyCommandsPlumbing,
@@ -588,6 +592,9 @@
   // The forwarder for web scroll view interation events.
   WebScrollViewMainContentUIForwarder* _webMainContentUIForwarder;
 
+  // The updater that adjusts the toolbar's layout for fullscreen events.
+  std::unique_ptr<FullscreenUIUpdater> _fullscreenUIUpdater;
+
   // Coordinator for the External Search UI.
   ExternalSearchCoordinator* _externalSearchCoordinator;
 
@@ -1183,9 +1190,10 @@
   if (base::FeatureList::IsEnabled(fullscreen::features::kNewFullscreen)) {
     // TODO(crbug.com/790886): Use the Browser's broadcaster once Browsers are
     // supported.
-    ChromeBroadcaster* broadcaster = FullscreenControllerFactory::GetInstance()
-                                         ->GetForBrowserState(_browserState)
-                                         ->broadcaster();
+    FullscreenController* fullscreenController =
+        FullscreenControllerFactory::GetInstance()->GetForBrowserState(
+            _browserState);
+    ChromeBroadcaster* broadcaster = fullscreenController->broadcaster();
     if (_broadcasting) {
       _toolbarUIUpdater = [[LegacyToolbarUIUpdater alloc]
           initWithToolbarUI:[[ToolbarUIState alloc] init]
@@ -1193,12 +1201,18 @@
                webStateList:[_model webStateList]];
       [_toolbarUIUpdater startUpdating];
       StartBroadcastingToolbarUI(_toolbarUIUpdater.toolbarUI, broadcaster);
+
       _mainContentUIUpdater = [[MainContentUIStateUpdater alloc]
           initWithState:[[MainContentUIState alloc] init]];
       _webMainContentUIForwarder = [[WebScrollViewMainContentUIForwarder alloc]
           initWithUpdater:_mainContentUIUpdater
              webStateList:[_model webStateList]];
       StartBroadcastingMainContentUI(self, broadcaster);
+
+      _fullscreenUIUpdater = base::MakeUnique<FullscreenUIUpdater>(self);
+      fullscreenController->AddObserver(_fullscreenUIUpdater.get());
+
+      fullscreenController->SetWebStateList([_model webStateList]);
     } else {
       StopBroadcastingToolbarUI(broadcaster);
       StopBroadcastingMainContentUI(broadcaster);
@@ -1207,6 +1221,9 @@
       _mainContentUIUpdater = nil;
       [_webMainContentUIForwarder disconnect];
       _webMainContentUIForwarder = nil;
+      fullscreenController->RemoveObserver(_fullscreenUIUpdater.get());
+      _fullscreenUIUpdater = nullptr;
+      fullscreenController->SetWebStateList(nullptr);
     }
   }
 }
@@ -1919,6 +1936,7 @@
   [_dispatcher startDispatchingToTarget:_toolbarCoordinator
                             forProtocol:@protocol(OmniboxFocuser)];
   [_toolbarCoordinator setTabCount:[_model count]];
+  [_toolbarCoordinator start];
   [self updateBroadcastState];
   if (_voiceSearchController)
     _voiceSearchController->SetDelegate(
@@ -3561,8 +3579,8 @@
 - (id<CRWNativeContent>)controllerForUnhandledContentAtURL:(const GURL&)URL
                                                   webState:
                                                       (web::WebState*)webState {
-  DownloadManagerController* downloadController =
-      [[DownloadManagerController alloc] initWithWebState:webState
+  LegacyDownloadManagerController* downloadController =
+      [[LegacyDownloadManagerController alloc] initWithWebState:webState
                                               downloadURL:URL
                                        baseViewController:self];
   [downloadController start];
@@ -3587,6 +3605,80 @@
   }
 }
 
+#pragma mark - FullscreenUIElement methods
+
+- (void)updateForFullscreenProgress:(CGFloat)progress {
+  [self updateHeadersForFullscreenProgress:progress];
+  [self updateFootersForFullscreenProgress:progress];
+  [self updateContentViewTopPaddingForFullscreenProgress:progress];
+}
+
+- (void)updateForFullscreenEnabled:(BOOL)enabled {
+  if (!enabled)
+    [self updateForFullscreenProgress:1.0];
+}
+
+- (void)finishFullscreenScrollWithAnimator:
+    (FullscreenScrollEndAnimator*)animator {
+  BOOL showingToolbar = animator.finalProgress > animator.startProgress;
+  CGFloat finalProgress = animator.finalProgress;
+  // WKWebView does not re-render its content until its model layer's bounds
+  // have been updated at the end of the animation.  If the animator is going
+  // to hide the toolbar, update the content view's top padding early so that
+  // content is correctly rendered behind the toolbar that's being animated
+  // away.
+  if (!showingToolbar)
+    [self updateContentViewTopPaddingForFullscreenProgress:finalProgress];
+  [animator addAnimations:^{
+    [self updateHeadersForFullscreenProgress:finalProgress];
+    [self updateFootersForFullscreenProgress:finalProgress];
+  }];
+  // If the toolbar is being animated to become visible, update the content view
+  // top padding in the completion block so that fixed-position elements can be
+  // properly laid out in the new viewport.
+  if (showingToolbar) {
+    __weak FullscreenScrollEndAnimator* weakAnimator = animator;
+    [animator addCompletion:^(UIViewAnimatingPosition finalPosition) {
+      [self updateContentViewTopPaddingForFullscreenProgress:
+                [weakAnimator progressForAnimatingPosition:finalPosition]];
+    }];
+  }
+}
+
+#pragma mark - FullscreenUIElement helpers
+
+// Translates the header views up and down according to |progress|, where a
+// progress of 1.0 fully shows the headers and a progress of 0.0 fully hides
+// them.
+- (void)updateHeadersForFullscreenProgress:(CGFloat)progress {
+  [self setFramesForHeaders:[self headerViews]
+                   atOffset:(1.0 - progress) * [self toolbarHeight]];
+}
+
+// Translates the footer view up and down according to |progress|, where a
+// progress of 1.0 fully shows the footer and a progress of 0.0 fully hides it.
+- (void)updateFootersForFullscreenProgress:(CGFloat)progress {
+  if (![_model currentTab].isVoiceSearchResultsTab)
+    return;
+
+  UIView* footerView = [self footerView];
+  DCHECK(footerView);
+  CGRect frame = footerView.frame;
+  frame.origin.y = CGRectGetMaxY(footerView.superview.bounds) -
+                   progress * CGRectGetHeight(frame);
+  footerView.frame = frame;
+}
+
+// Updates the top padding of the web view proxy.  This either resets the frame
+// of the WKWebView or the contentInsets of the WKWebView's UIScrollView,
+// depending on the the proxy's |shouldUseInsetForTopPadding| property.
+- (void)updateContentViewTopPaddingForFullscreenProgress:(CGFloat)progress {
+  if (self.currentWebState) {
+    self.currentWebState->GetWebViewProxy().topContentPadding =
+        progress * [self toolbarHeight];
+  }
+}
+
 #pragma mark - Context menu methods
 
 - (void)searchByImageAtURL:(const GURL&)url
diff --git a/ios/chrome/browser/ui/download/BUILD.gn b/ios/chrome/browser/ui/download/BUILD.gn
index f58af832..ee62fe9a 100644
--- a/ios/chrome/browser/ui/download/BUILD.gn
+++ b/ios/chrome/browser/ui/download/BUILD.gn
@@ -5,8 +5,8 @@
 source_set("download") {
   configs += [ "//build/config/compiler:enable_arc" ]
   sources = [
-    "download_manager_controller.h",
-    "download_manager_controller.mm",
+    "legacy_download_manager_controller.h",
+    "legacy_download_manager_controller.mm",
   ]
   deps = [
     "resources:download_manager_controller_xib",
@@ -38,7 +38,7 @@
   configs += [ "//build/config/compiler:enable_arc" ]
   testonly = true
   sources = [
-    "download_manager_controller_unittest.mm",
+    "legacy_download_manager_controller_unittest.mm",
   ]
   deps = [
     ":download",
diff --git a/ios/chrome/browser/ui/download/download_manager_controller.h b/ios/chrome/browser/ui/download/legacy_download_manager_controller.h
similarity index 83%
rename from ios/chrome/browser/ui/download/download_manager_controller.h
rename to ios/chrome/browser/ui/download/legacy_download_manager_controller.h
index 645de47..b3a129f 100644
--- a/ios/chrome/browser/ui/download/download_manager_controller.h
+++ b/ios/chrome/browser/ui/download/legacy_download_manager_controller.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef IOS_CHROME_BROWSER_UI_DOWNLOAD_DOWNLOAD_MANAGER_CONTROLLER_H_
-#define IOS_CHROME_BROWSER_UI_DOWNLOAD_DOWNLOAD_MANAGER_CONTROLLER_H_
+#ifndef IOS_CHROME_BROWSER_UI_DOWNLOAD_LEGACY_DOWNLOAD_MANAGER_CONTROLLER_H_
+#define IOS_CHROME_BROWSER_UI_DOWNLOAD_LEGACY_DOWNLOAD_MANAGER_CONTROLLER_H_
 
 #import <UIKit/UIKit.h>
 
@@ -18,7 +18,7 @@
 // the option to download it and open it in another app. This controller is
 // displayed when a URL is loaded that contains a file type that UIWebView
 // cannot display itself.
-@interface DownloadManagerController
+@interface LegacyDownloadManagerController
     : NativeContentController<UIDocumentInteractionControllerDelegate>
 
 // Initializes a controller for content from |url| using |webState| to provide
@@ -39,4 +39,4 @@
 
 @end
 
-#endif  // IOS_CHROME_BROWSER_UI_DOWNLOAD_DOWNLOAD_MANAGER_CONTROLLER_H_
+#endif  // IOS_CHROME_BROWSER_UI_DOWNLOAD_LEGACY_DOWNLOAD_MANAGER_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/download/download_manager_controller.mm b/ios/chrome/browser/ui/download/legacy_download_manager_controller.mm
similarity index 98%
rename from ios/chrome/browser/ui/download/download_manager_controller.mm
rename to ios/chrome/browser/ui/download/legacy_download_manager_controller.mm
index 3b946b6..9c87133 100644
--- a/ios/chrome/browser/ui/download/download_manager_controller.mm
+++ b/ios/chrome/browser/ui/download/legacy_download_manager_controller.mm
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#import "ios/chrome/browser/ui/download/download_manager_controller.h"
+#import "ios/chrome/browser/ui/download/legacy_download_manager_controller.h"
 
 #include <stdint.h>
 #include <memory>
@@ -55,7 +55,7 @@
 using net::URLRequestContextGetter;
 using net::URLRequestStatus;
 
-@interface DownloadManagerController ()
+@interface LegacyDownloadManagerController ()
 
 // Creates the portrait and landscape mode constraints that are switched every
 // time the interface is rotated.
@@ -190,7 +190,7 @@
 // Calls -openGoogleDriveInAppStore to allow the user to install Google Drive.
 - (IBAction)googleDriveButtonTapped:(id)sender;
 
-// Cleans up this DownloadManagerController, and deletes its file from the
+// Cleans up this LegacyDownloadManagerController, and deletes its file from the
 // downloads directory if it has been created there.
 - (void)dealloc;
 
@@ -331,14 +331,14 @@
 // request to get information about the file.
 class DownloadHeadDelegate : public URLFetcherDelegate {
  public:
-  explicit DownloadHeadDelegate(DownloadManagerController* owner)
+  explicit DownloadHeadDelegate(LegacyDownloadManagerController* owner)
       : owner_(owner) {}
   void OnURLFetchComplete(const URLFetcher* source) override {
     [owner_ onHeadFetchComplete];
   };
 
  private:
-  __weak DownloadManagerController* owner_;
+  __weak LegacyDownloadManagerController* owner_;
   DISALLOW_COPY_AND_ASSIGN(DownloadHeadDelegate);
 };
 
@@ -346,7 +346,7 @@
 // request to download the contents of the file.
 class DownloadContentDelegate : public URLFetcherDelegate {
  public:
-  explicit DownloadContentDelegate(DownloadManagerController* owner)
+  explicit DownloadContentDelegate(LegacyDownloadManagerController* owner)
       : owner_(owner) {}
   void OnURLFetchDownloadProgress(const URLFetcher* source,
                                   int64_t current,
@@ -359,13 +359,13 @@
   };
 
  private:
-  __weak DownloadManagerController* owner_;
+  __weak LegacyDownloadManagerController* owner_;
   DISALLOW_COPY_AND_ASSIGN(DownloadContentDelegate);
 };
 
 }  // namespace
 
-@interface DownloadManagerController () {
+@interface LegacyDownloadManagerController () {
   int _downloadManagerId;
 
   // Coordinator for displaying the alert informing the user that no application
@@ -495,7 +495,7 @@
 
 @end
 
-@implementation DownloadManagerController
+@implementation LegacyDownloadManagerController
 
 @synthesize documentContainer = _documentContainer;
 @synthesize progressBar = _progressBar;
@@ -1057,7 +1057,7 @@
   if (tabHelper) {
     NSString* googleDriveButtonTitle =
         l10n_util::GetNSString(IDS_IOS_DOWNLOAD_MANAGER_UPLOAD_TO_GOOGLE_DRIVE);
-    __weak DownloadManagerController* weakSelf = self;
+    __weak LegacyDownloadManagerController* weakSelf = self;
     [_alertCoordinator addItemWithTitle:googleDriveButtonTitle
                                  action:^{
                                    [weakSelf openGoogleDriveInAppStore];
@@ -1206,12 +1206,12 @@
 - (void)beginStartingContentDownload {
   // Ensure the directory that downloaded files are saved to exists.
   base::FilePath downloadsDirectoryPath;
-  if (![DownloadManagerController
+  if (![LegacyDownloadManagerController
           fetchDownloadsDirectoryFilePath:&downloadsDirectoryPath]) {
     [self displayError];
     return;
   }
-  __weak DownloadManagerController* weakSelf = self;
+  __weak LegacyDownloadManagerController* weakSelf = self;
   base::PostTaskWithTraitsAndReplyWithResult(
       FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_BLOCKING},
       base::BindBlockArc(^{
@@ -1228,7 +1228,7 @@
     return;
   }
   base::FilePath downloadsDirectoryPath;
-  if (![DownloadManagerController
+  if (![LegacyDownloadManagerController
           fetchDownloadsDirectoryFilePath:&downloadsDirectoryPath]) {
     [self displayError];
     return;
@@ -1270,7 +1270,7 @@
       newProgressFrame.size.height - oldProgressFrame.size.height > 1) {
     __weak UIView* weakProgressBar = _progressBar;
     if (completionAnimation) {
-      __weak DownloadManagerController* weakSelf = self;
+      __weak LegacyDownloadManagerController* weakSelf = self;
       [UIView animateWithDuration:kProgressBarAnimationDuration
           animations:^{
             [weakProgressBar setFrame:newProgressFrame];
@@ -1557,10 +1557,10 @@
 }
 
 - (NSString*)getNetworkActivityKey {
-  return
-      [NSString stringWithFormat:
-                    @"DownloadManagerController.NetworkActivityIndicatorKey.%d",
-                    _downloadManagerId];
+  return [NSString
+      stringWithFormat:
+          @"LegacyDownloadManagerController.NetworkActivityIndicatorKey.%d",
+          _downloadManagerId];
 }
 
 + (BOOL)fetchDownloadsDirectoryFilePath:(base::FilePath*)path {
@@ -1576,7 +1576,7 @@
       FROM_HERE, {base::MayBlock(), base::TaskPriority::BACKGROUND},
       base::BindBlockArc(^{
         base::FilePath downloadsDirectory;
-        if (![DownloadManagerController
+        if (![LegacyDownloadManagerController
                 fetchDownloadsDirectoryFilePath:&downloadsDirectory]) {
           return;
         }
diff --git a/ios/chrome/browser/ui/download/download_manager_controller_unittest.mm b/ios/chrome/browser/ui/download/legacy_download_manager_controller_unittest.mm
similarity index 87%
rename from ios/chrome/browser/ui/download/download_manager_controller_unittest.mm
rename to ios/chrome/browser/ui/download/legacy_download_manager_controller_unittest.mm
index 51eb802..a7b63a5a 100644
--- a/ios/chrome/browser/ui/download/download_manager_controller_unittest.mm
+++ b/ios/chrome/browser/ui/download/legacy_download_manager_controller_unittest.mm
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#import "ios/chrome/browser/ui/download/download_manager_controller.h"
+#import "ios/chrome/browser/ui/download/legacy_download_manager_controller.h"
 
 #import <UIKit/UIKit.h>
 
@@ -29,7 +29,7 @@
 using net::HttpResponseHeaders;
 using net::URLRequestStatus;
 
-@interface DownloadManagerController (ExposedForTesting)
+@interface LegacyDownloadManagerController (ExposedForTesting)
 - (UIView*)documentContainer;
 - (UIView*)progressBar;
 - (UIImageView*)documentIcon;
@@ -51,7 +51,7 @@
 
 const GURL kTestURL = GURL("http://www.example.com/test_download_file.txt");
 
-class DownloadManagerControllerTest : public ChromeWebTest {
+class LegacyDownloadManagerControllerTest : public ChromeWebTest {
  protected:
   void SetUp() override {
     ChromeWebTest::SetUp();
@@ -62,15 +62,15 @@
         [OCMockObject niceMockForProtocol:@protocol(StoreKitLauncher)];
     helper->SetLauncher(mock_launcher);
     _controller =
-        [[DownloadManagerController alloc] initWithWebState:web_state()
+        [[LegacyDownloadManagerController alloc] initWithWebState:web_state()
                                                 downloadURL:kTestURL
                                          baseViewController:nil];
   }
   std::unique_ptr<net::TestURLFetcherFactory> _fetcher_factory;
-  __strong DownloadManagerController* _controller;
+  __strong LegacyDownloadManagerController* _controller;
 };
 
-TEST_F(DownloadManagerControllerTest, TestXibViewConnections) {
+TEST_F(LegacyDownloadManagerControllerTest, TestXibViewConnections) {
   EXPECT_TRUE([_controller documentContainer]);
   EXPECT_TRUE([_controller progressBar]);
   EXPECT_TRUE([_controller documentIcon]);
@@ -87,7 +87,7 @@
   EXPECT_TRUE([_controller googleDriveButton]);
 }
 
-TEST_F(DownloadManagerControllerTest, TestStart) {
+TEST_F(LegacyDownloadManagerControllerTest, TestStart) {
   [_controller start];
   EXPECT_TRUE(
       [[UIApplication sharedApplication] isNetworkActivityIndicatorVisible]);
@@ -96,7 +96,7 @@
   EXPECT_EQ(kTestURL, fetcher->GetOriginalURL());
 }
 
-TEST_F(DownloadManagerControllerTest, TestOnHeadFetchCompleteSuccess) {
+TEST_F(LegacyDownloadManagerControllerTest, TestOnHeadFetchCompleteSuccess) {
   [_controller start];
   net::TestURLFetcher* fetcher = _fetcher_factory->GetFetcherByID(0);
 
@@ -120,7 +120,7 @@
   EXPECT_FALSE([_controller downloadButton].hidden);
 }
 
-TEST_F(DownloadManagerControllerTest, TestOnHeadFetchCompleteFailure) {
+TEST_F(LegacyDownloadManagerControllerTest, TestOnHeadFetchCompleteFailure) {
   [_controller start];
   net::TestURLFetcher* fetcher = _fetcher_factory->GetFetcherByID(0);
 
diff --git a/ios/chrome/browser/ui/download/resources/DownloadManagerController.xib b/ios/chrome/browser/ui/download/resources/DownloadManagerController.xib
index ab400a6..9e79819 100644
--- a/ios/chrome/browser/ui/download/resources/DownloadManagerController.xib
+++ b/ios/chrome/browser/ui/download/resources/DownloadManagerController.xib
@@ -4,7 +4,7 @@
         <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
     </dependencies>
     <objects>
-        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="DownloadManagerController">
+        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="LegacyDownloadManagerController">
             <connections>
                 <outlet property="actionBar" destination="mf4-ti-xzw" id="e6W-4V-boT"/>
                 <outlet property="actionBarBorder" destination="vi5-3Q-93W" id="Dgb-9u-X2x"/>
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_controller.h b/ios/chrome/browser/ui/fullscreen/fullscreen_controller.h
index 01ccdfa..5d89062 100644
--- a/ios/chrome/browser/ui/fullscreen/fullscreen_controller.h
+++ b/ios/chrome/browser/ui/fullscreen/fullscreen_controller.h
@@ -17,6 +17,7 @@
 class FullscreenMediator;
 class FullscreenModel;
 class FullscreenWebStateListObserver;
+class WebStateList;
 
 // An object that observes scrolling events in the main content area and
 // calculates how much of the toolbar should be visible as a result.  When the
@@ -34,6 +35,13 @@
   // ChromeBroadcaster.
   ChromeBroadcaster* broadcaster() { return broadcaster_; }
 
+  // The WebStateList for the Browser whose fullscreen state is managed by this
+  // controller.
+  // TODO(crbug.com/790886): Once FullscreenController is a BrowserUserData,
+  // remove this, as the Browser's WebStateList can be used directly rather than
+  // being set.
+  void SetWebStateList(WebStateList* web_state_list);
+
   // Adds and removes FullscreenControllerObservers.
   void AddObserver(FullscreenControllerObserver* observer);
   void RemoveObserver(FullscreenControllerObserver* observer);
@@ -56,6 +64,9 @@
 
   // The broadcaster that drives the model.
   __strong ChromeBroadcaster* broadcaster_ = nil;
+  // The WebStateList for the Browser whose fullscreen is managed by this
+  // object.
+  WebStateList* web_state_list_ = nullptr;
   // The model used to calculate fullscreen state.
   std::unique_ptr<FullscreenModel> model_;
   // The bridge used to forward brodcasted UI to |model_|.
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_controller.mm b/ios/chrome/browser/ui/fullscreen/fullscreen_controller.mm
index 9c768f98..f6425d65 100644
--- a/ios/chrome/browser/ui/fullscreen/fullscreen_controller.mm
+++ b/ios/chrome/browser/ui/fullscreen/fullscreen_controller.mm
@@ -34,6 +34,16 @@
 
 FullscreenController::~FullscreenController() = default;
 
+void FullscreenController::SetWebStateList(WebStateList* web_state_list) {
+  if (web_state_list_observer_)
+    web_state_list_observer_->Disconnect();
+  web_state_list_ = web_state_list;
+  web_state_list_observer_ =
+      web_state_list_ ? base::MakeUnique<FullscreenWebStateListObserver>(
+                            model_.get(), web_state_list_)
+                      : nullptr;
+}
+
 void FullscreenController::AddObserver(FullscreenControllerObserver* observer) {
   mediator_->AddObserver(observer);
 }
@@ -57,6 +67,8 @@
 
 void FullscreenController::Shutdown() {
   mediator_->Disconnect();
+  if (web_state_list_observer_)
+    web_state_list_observer_->Disconnect();
   [broadcaster_ removeObserver:bridge_
                    forSelector:@selector(broadcastContentScrollOffset:)];
   [broadcaster_ removeObserver:bridge_
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_mediator.h b/ios/chrome/browser/ui/fullscreen/fullscreen_mediator.h
index 906bffa..2798f99 100644
--- a/ios/chrome/browser/ui/fullscreen/fullscreen_mediator.h
+++ b/ios/chrome/browser/ui/fullscreen/fullscreen_mediator.h
@@ -38,12 +38,11 @@
   // FullscreenModelObserver:
   void FullscreenModelProgressUpdated(FullscreenModel* model) override;
   void FullscreenModelEnabledStateChanged(FullscreenModel* model) override;
+  void FullscreenModelScrollEventStarted(FullscreenModel* model) override;
   void FullscreenModelScrollEventEnded(FullscreenModel* model) override;
 
   // Stops the current scroll end animation if one is in progress.
   void StopAnimating();
-  // Performs cleanup tasks for the animator.
-  void CleanUpAnimator();
 
   // The controller.
   FullscreenController* controller_ = nullptr;
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_mediator.mm b/ios/chrome/browser/ui/fullscreen/fullscreen_mediator.mm
index d26f28d..df787a3 100644
--- a/ios/chrome/browser/ui/fullscreen/fullscreen_mediator.mm
+++ b/ios/chrome/browser/ui/fullscreen/fullscreen_mediator.mm
@@ -54,6 +54,12 @@
   }
 }
 
+void FullscreenMediator::FullscreenModelScrollEventStarted(
+    FullscreenModel* model) {
+  DCHECK_EQ(model_, model);
+  StopAnimating();
+}
+
 void FullscreenMediator::FullscreenModelScrollEventEnded(
     FullscreenModel* model) {
   DCHECK_EQ(model_, model);
@@ -61,7 +67,11 @@
   animator_ = [[FullscreenScrollEndAnimator alloc]
       initWithStartProgress:model_->progress()];
   [animator_ addCompletion:^(UIViewAnimatingPosition finalPosition) {
-    CleanUpAnimator();
+    DCHECK(finalPosition == UIViewAnimatingPositionEnd ||
+           finalPosition == UIViewAnimatingPositionCurrent);
+    model_->AnimationEndedWithProgress(
+        [animator_ progressForAnimatingPosition:finalPosition]);
+    animator_ = nil;
   }];
   for (auto& observer : observers_) {
     observer.FullscreenScrollEventEnded(controller_, animator_);
@@ -75,11 +85,13 @@
 
   DCHECK_EQ(animator_.state, UIViewAnimatingStateActive);
   [animator_ stopAnimation:NO];
-  [animator_ finishAnimationAtPosition:UIViewAnimatingPositionCurrent];
-}
 
-void FullscreenMediator::CleanUpAnimator() {
-  DCHECK(animator_);
-  model_->AnimationEndedWithProgress(animator_.currentProgress);
-  animator_ = nil;
+  // Property animators throw exceptions if they are deallocated in the
+  // UIViewAnimatingStateStopped state.  Since the cleanup occurring in the
+  // animator's completion block occurs before |-finishAnimationAtPosition:|
+  // resets the state to UIViewAnimatingStateInactive, the animator is retained
+  // here so that it can be deallocated when reset to inactive.
+  FullscreenScrollEndAnimator* animator = animator_;
+  [animator_ finishAnimationAtPosition:UIViewAnimatingPositionCurrent];
+  animator = nil;
 }
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_model.h b/ios/chrome/browser/ui/fullscreen/fullscreen_model.h
index 217ca62..46ac581 100644
--- a/ios/chrome/browser/ui/fullscreen/fullscreen_model.h
+++ b/ios/chrome/browser/ui/fullscreen/fullscreen_model.h
@@ -104,6 +104,8 @@
   bool scrolling_ = false;
   // Whether the main content is being dragged.
   bool dragging_ = false;
+  // The number of FullscreenModelObserver callbacks currently being executed.
+  size_t observer_callback_count_ = 0;
 
   DISALLOW_COPY_AND_ASSIGN(FullscreenModel);
 };
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_model.mm b/ios/chrome/browser/ui/fullscreen/fullscreen_model.mm
index 974a934e..f23c3e2 100644
--- a/ios/chrome/browser/ui/fullscreen/fullscreen_model.mm
+++ b/ios/chrome/browser/ui/fullscreen/fullscreen_model.mm
@@ -14,11 +14,26 @@
 #error "This file requires ARC support."
 #endif
 
+namespace {
+// Object that increments |counter| by 1 for its lifetime.
+class ScopedIncrementer {
+ public:
+  explicit ScopedIncrementer(size_t* counter) : counter_(counter) {
+    ++(*counter_);
+  }
+  ~ScopedIncrementer() { --(*counter_); }
+
+ private:
+  size_t* counter_;
+};
+}
+
 FullscreenModel::FullscreenModel() = default;
 FullscreenModel::~FullscreenModel() = default;
 
 void FullscreenModel::IncrementDisabledCounter() {
   if (++disabled_counter_ == 1U) {
+    ScopedIncrementer disabled_incrementer(&observer_callback_count_);
     for (auto& observer : observers_) {
       observer.FullscreenModelEnabledStateChanged(this);
     }
@@ -28,6 +43,7 @@
 void FullscreenModel::DecrementDisabledCounter() {
   DCHECK_GT(disabled_counter_, 0U);
   if (!--disabled_counter_) {
+    ScopedIncrementer enabled_incrementer(&observer_callback_count_);
     for (auto& observer : observers_) {
       observer.FullscreenModelEnabledStateChanged(this);
     }
@@ -64,7 +80,7 @@
   if (!has_base_offset())
     UpdateBaseOffset();
 
-  if (scrolling_) {
+  if (scrolling_ && !observer_callback_count_) {
     CGFloat delta = base_offset_ - y_content_offset_;
     SetProgress(1.0 + delta / toolbar_height_);
   } else {
@@ -81,6 +97,7 @@
     return;
   scrolling_ = scrolling;
   if (!scrolling_) {
+    ScopedIncrementer scroll_ended_incrementer(&observer_callback_count_);
     for (auto& observer : observers_) {
       observer.FullscreenModelScrollEventEnded(this);
     }
@@ -95,9 +112,13 @@
   if (dragging_ == dragging)
     return;
   dragging_ = dragging;
-  // Update the base offset when dragging occurs.
-  if (dragging_)
+  if (dragging_) {
+    ScopedIncrementer scroll_started_incrementer(&observer_callback_count_);
+    for (auto& observer : observers_) {
+      observer.FullscreenModelScrollEventStarted(this);
+    }
     UpdateBaseOffset();
+  }
 }
 
 bool FullscreenModel::IsScrollViewDragging() const {
@@ -110,6 +131,8 @@
   if (AreCGFloatsEqual(progress_, progress))
     return;
   progress_ = progress;
+
+  ScopedIncrementer progress_incrementer(&observer_callback_count_);
   for (auto& observer : observers_) {
     observer.FullscreenModelProgressUpdated(this);
   }
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_model_observer.h b/ios/chrome/browser/ui/fullscreen/fullscreen_model_observer.h
index d966324..6d32dcb 100644
--- a/ios/chrome/browser/ui/fullscreen/fullscreen_model_observer.h
+++ b/ios/chrome/browser/ui/fullscreen/fullscreen_model_observer.h
@@ -23,6 +23,9 @@
   // Invoked when |model| is enabled or disabled.
   virtual void FullscreenModelEnabledStateChanged(FullscreenModel* model) {}
 
+  // Invoked when a scroll event being tracked by |model| has started.
+  virtual void FullscreenModelScrollEventStarted(FullscreenModel* model) {}
+
   // Invoked when a scroll event being tracked by |model| has ended.
   virtual void FullscreenModelScrollEventEnded(FullscreenModel* model) {}
 
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_scroll_end_animator.h b/ios/chrome/browser/ui/fullscreen/fullscreen_scroll_end_animator.h
index c16d3669..ee508a2 100644
--- a/ios/chrome/browser/ui/fullscreen/fullscreen_scroll_end_animator.h
+++ b/ios/chrome/browser/ui/fullscreen/fullscreen_scroll_end_animator.h
@@ -30,6 +30,9 @@
     NS_UNAVAILABLE;
 - (instancetype)init NS_UNAVAILABLE;
 
+// Returns the progress value corresponding with |position|.
+- (CGFloat)progressForAnimatingPosition:(UIViewAnimatingPosition)position;
+
 @end
 
 #endif  // IOS_CLEAN_CHROME_BROWSER_UI_FULLSCREEN_FULLSCREEN_SCROLL_END_ANIMATOR_H_
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_scroll_end_animator.mm b/ios/chrome/browser/ui/fullscreen/fullscreen_scroll_end_animator.mm
index 48daadb2..33f35a59 100644
--- a/ios/chrome/browser/ui/fullscreen/fullscreen_scroll_end_animator.mm
+++ b/ios/chrome/browser/ui/fullscreen/fullscreen_scroll_end_animator.mm
@@ -19,6 +19,8 @@
 @interface FullscreenScrollEndAnimator () {
   // The bezier backing the timing curve.
   std::unique_ptr<gfx::CubicBezier> _bezier;
+  // The current progress value that was recorded when the animator was stopped.
+  CGFloat _progressUponStopping;
 }
 @end
 
@@ -48,11 +50,37 @@
 #pragma mark Accessors
 
 - (CGFloat)currentProgress {
+  if (self.state == UIViewAnimatingStateStopped)
+    return _progressUponStopping;
   CGFloat interpolationFraction = _bezier->Solve(self.fractionComplete);
   CGFloat range = self.finalProgress - self.startProgress;
   return self.startProgress + interpolationFraction * range;
 }
 
+#pragma mark Public
+
+- (CGFloat)progressForAnimatingPosition:(UIViewAnimatingPosition)position {
+  switch (position) {
+    case UIViewAnimatingPositionStart:
+      return self.startProgress;
+    case UIViewAnimatingPositionEnd:
+      return self.finalProgress;
+    case UIViewAnimatingPositionCurrent:
+      return self.currentProgress;
+  }
+}
+
+#pragma mark UIViewAnimating
+
+- (void)stopAnimation:(BOOL)withoutFinishing {
+  // Record the progress value when transitioning from the active to stopped
+  // state.  This allows |currentProgress| to return the correct value after
+  // stopping, as |fractionComplete| is reset to 0.0 for stopped animators.
+  if (self.state == UIViewAnimatingStateActive)
+    _progressUponStopping = self.currentProgress;
+  [super stopAnimation:withoutFinishing];
+}
+
 #pragma mark UIViewPropertyAnimator
 
 - (BOOL)isInterruptible {
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_web_state_list_observer.mm b/ios/chrome/browser/ui/fullscreen/fullscreen_web_state_list_observer.mm
index a79dba5..94207252 100644
--- a/ios/chrome/browser/ui/fullscreen/fullscreen_web_state_list_observer.mm
+++ b/ios/chrome/browser/ui/fullscreen/fullscreen_web_state_list_observer.mm
@@ -20,6 +20,7 @@
   DCHECK(model_);
   DCHECK(web_state_list_);
   web_state_list_->AddObserver(this);
+  web_state_observer_.SetWebState(web_state_list_->GetActiveWebState());
 }
 
 FullscreenWebStateListObserver::~FullscreenWebStateListObserver() {
diff --git a/ios/chrome/browser/ui/fullscreen/legacy_fullscreen_controller.mm b/ios/chrome/browser/ui/fullscreen/legacy_fullscreen_controller.mm
index 0d246252..e0fa789 100644
--- a/ios/chrome/browser/ui/fullscreen/legacy_fullscreen_controller.mm
+++ b/ios/chrome/browser/ui/fullscreen/legacy_fullscreen_controller.mm
@@ -391,9 +391,6 @@
                       scrollingToOffset:0.0f];
   } else {
     if (!visible && ![webViewProxy_ shouldUseInsetForTopPadding]) {
-      // The header will be hidden, so if the content view is not using the
-      // content inset, it is necessary to decrease the top padding, so more
-      // content is visible to the user.
       CGFloat newTopContentPadding = self.headerHeight - headerPosition;
       CGFloat topContentPaddingChange =
           [webViewProxy_ topContentPadding] - newTopContentPadding;
diff --git a/ios/chrome/browser/ui/main_content/main_content_ui_state.mm b/ios/chrome/browser/ui/main_content/main_content_ui_state.mm
index 3ae7cac..76cbf2f 100644
--- a/ios/chrome/browser/ui/main_content/main_content_ui_state.mm
+++ b/ios/chrome/browser/ui/main_content/main_content_ui_state.mm
@@ -85,6 +85,7 @@
 - (void)scrollViewWillBeginDraggingWithGesture:
     (UIPanGestureRecognizer*)panGesture {
   self.state.dragging = YES;
+  self.state.decelerating = NO;
   self.panGesture = panGesture;
 }
 
diff --git a/ios/chrome/browser/ui/main_content/web_scroll_view_main_content_ui_forwarder.mm b/ios/chrome/browser/ui/main_content/web_scroll_view_main_content_ui_forwarder.mm
index c8d3897e..936f8d0 100644
--- a/ios/chrome/browser/ui/main_content/web_scroll_view_main_content_ui_forwarder.mm
+++ b/ios/chrome/browser/ui/main_content/web_scroll_view_main_content_ui_forwarder.mm
@@ -56,7 +56,9 @@
 }
 
 - (void)dealloc {
-  [self disconnect];
+  // |-disconnect| must be called before deallocation.
+  DCHECK(!_bridge);
+  DCHECK(!_proxy);
 }
 
 #pragma mark Accessors
diff --git a/ios/chrome/browser/ui/omnibox/BUILD.gn b/ios/chrome/browser/ui/omnibox/BUILD.gn
index e0803e0..4e77cd7 100644
--- a/ios/chrome/browser/ui/omnibox/BUILD.gn
+++ b/ios/chrome/browser/ui/omnibox/BUILD.gn
@@ -94,6 +94,7 @@
     "//ios/chrome/browser/sessions",
     "//ios/chrome/browser/ui",
     "//ios/chrome/browser/ui/commands",
+    "//ios/chrome/browser/ui/toolbar/clean:toolbar_components_ui",
     "//ios/chrome/browser/ui/toolbar/public",
     "//ios/chrome/browser/ui/toolbar/public:toolbar_base_feature",
     "//ios/chrome/common",
diff --git a/ios/chrome/browser/ui/omnibox/location_bar_view.h b/ios/chrome/browser/ui/omnibox/location_bar_view.h
index 5e71bbfc..9960083d 100644
--- a/ios/chrome/browser/ui/omnibox/location_bar_view.h
+++ b/ios/chrome/browser/ui/omnibox/location_bar_view.h
@@ -54,14 +54,12 @@
 // Perform animations for expanding the omnibox. This animation can be seen on
 // an iPhone when the omnibox is focused. It involves sliding the leading button
 // out and fading its alpha.
-- (void)addExpandOmniboxAnimations:(UIViewPropertyAnimator*)animator
-    API_AVAILABLE(ios(10.0));
+- (void)addExpandOmniboxAnimations:(UIViewPropertyAnimator*)animator;
 
 // Perform animations for expanding the omnibox. This animation can be seen on
 // an iPhone when the omnibox is defocused. It involves sliding the leading
 // button in and fading its alpha.
-- (void)addContractOmniboxAnimations:(UIViewPropertyAnimator*)animator
-    API_AVAILABLE(ios(10.0));
+- (void)addContractOmniboxAnimations:(UIViewPropertyAnimator*)animator;
 
 @end
 
diff --git a/ios/chrome/browser/ui/omnibox/location_bar_view.mm b/ios/chrome/browser/ui/omnibox/location_bar_view.mm
index b812b9f3..523a487 100644
--- a/ios/chrome/browser/ui/omnibox/location_bar_view.mm
+++ b/ios/chrome/browser/ui/omnibox/location_bar_view.mm
@@ -221,49 +221,21 @@
       }];
 }
 
-- (void)addExpandOmniboxAnimations:(UIViewPropertyAnimator*)animator
-    API_AVAILABLE(ios(10.0)) {
-  UIView* leadingView = [self leadingButton];
-  leadingView.alpha = 1;
-  self.leadingButtonLeadingConstraint.constant = -100;
-  [animator addAnimations:^{
-    leadingView.alpha = 0;
-
-    [self setNeedsLayout];
-    [self layoutIfNeeded];
-  }];
-
-  [animator addCompletion:^(UIViewAnimatingPosition finalPosition) {
-    [self setLeadingButtonHidden:YES];
-    [self setNeedsLayout];
-    [self layoutIfNeeded];
-  }];
-
+- (void)addExpandOmniboxAnimations:(UIViewPropertyAnimator*)animator {
+  // TODO(crbug.com/791455): Due to crbug.com/774121 |self.leadingButton| is
+  // hidden in line 151 before the animation starts. For this reason any
+  // animation we try doing on |self.leadingButton| will not be visible.
   [self.textField addExpandOmniboxAnimations:animator];
 }
 
-- (void)addContractOmniboxAnimations:(UIViewPropertyAnimator*)animator
-    API_AVAILABLE(ios(10.0)) {
+- (void)addContractOmniboxAnimations:(UIViewPropertyAnimator*)animator {
   [self setLeadingButtonHidden:NO];
-
-  UIView* leadingView = [self leadingButton];
-
-  // Move the leadingButton outside of the bounds; this constraint will be
-  // created from scratch when the button is shown.
-  self.leadingButtonLeadingConstraint.constant = leadingView.frame.size.width;
-  leadingView.alpha = 0;
-
+  self.leadingButton.alpha = 0;
   [animator addAnimations:^{
-    // Fade out the alpha and apply the constraint change above.
-    leadingView.alpha = 1;
-    [self setNeedsLayout];
+    self.leadingButton.alpha = 1;
+    [self setLeadingButtonHidden:YES];
     [self layoutIfNeeded];
-  }
-              delayFactor:ios::material::kDuration2];
-  [animator addCompletion:^(UIViewAnimatingPosition finalPosition) {
-    [self setLeadingButtonHidden:NO];
   }];
-
   [self.textField addContractOmniboxAnimations:animator];
 }
 
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.h b/ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.h
index 0f20c86..d1f1103 100644
--- a/ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.h
+++ b/ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.h
@@ -80,12 +80,10 @@
 // Called when animations added by |-animateFadeWithStyle:| can be removed.
 - (void)cleanUpFadeAnimations;
 
-// New animations API. Currently are behind a flag since they require iOS 10
-// APIs to work. They replace all animations above.
-- (void)addExpandOmniboxAnimations:(UIViewPropertyAnimator*)animator
-    API_AVAILABLE(ios(10.0));
-- (void)addContractOmniboxAnimations:(UIViewPropertyAnimator*)animator
-    API_AVAILABLE(ios(10.0));
+// New animations API, currently behind clean-toolbar flag.
+// They replace all animations above.
+- (void)addExpandOmniboxAnimations:(UIViewPropertyAnimator*)animator;
+- (void)addContractOmniboxAnimations:(UIViewPropertyAnimator*)animator;
 
 // Initial touch on the Omnibox triggers a "pre-edit" state. The current
 // URL is shown without any insertion point. First character typed replaces
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.mm b/ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.mm
index 3e40a3e..1190d8b 100644
--- a/ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.mm
+++ b/ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.mm
@@ -21,6 +21,7 @@
 #include "ios/chrome/browser/ui/omnibox/omnibox_util.h"
 #import "ios/chrome/browser/ui/reversed_animation.h"
 #include "ios/chrome/browser/ui/rtl_geometry.h"
+#import "ios/chrome/browser/ui/toolbar/clean/toolbar_constants.h"
 #import "ios/chrome/browser/ui/toolbar/public/toolbar_controller_base_feature.h"
 #import "ios/chrome/browser/ui/toolbar/public/web_toolbar_controller_constants.h"
 #include "ios/chrome/browser/ui/ui_util.h"
@@ -301,37 +302,41 @@
                                   [self fadeAnimationLayers]);
 }
 
-- (void)addExpandOmniboxAnimations:(UIViewPropertyAnimator*)animator
-    API_AVAILABLE(ios(10.0)) {
-  __weak OmniboxTextFieldIOS* weakSelf = self;
-  [self rightView].alpha = 0;
+- (void)addExpandOmniboxAnimations:(UIViewPropertyAnimator*)animator {
+  // Hide the rightView button so its not visibile on its initial layout
+  // while the expan animation is happening.
+  self.rightView.hidden = YES;
+  self.rightView.frame = [self rightViewRectForBounds:self.bounds];
+  [animator addAnimations:^{
+    [self layoutIfNeeded];
+    [self.rightView layoutIfNeeded];
+  }];
+
   [animator addCompletion:^(UIViewAnimatingPosition finalPosition) {
-    UIView* trailingView = [weakSelf rightView];
-    CGRect finalTrailingViewFrame = trailingView.frame;
-    trailingView.frame =
-        CGRectLayoutOffset(trailingView.frame, kPositionAnimationLeadingOffset);
+    self.rightView.hidden = NO;
+    self.rightView.alpha = 0;
+    self.rightView.frame =
+        CGRectLayoutOffset(self.rightView.frame, kToolbarButtonAnimationOffset);
     [UIViewPropertyAnimator
         runningPropertyAnimatorWithDuration:0.2
                                       delay:0.1
                                     options:UIViewAnimationOptionCurveEaseOut
                                  animations:^{
-                                   trailingView.alpha = 1.0;
-                                   trailingView.frame = finalTrailingViewFrame;
+                                   self.rightView.alpha = 1.0;
+                                   self.rightView.frame = CGRectLayoutOffset(
+                                       self.rightView.frame,
+                                       -kToolbarButtonAnimationOffset);
                                  }
                                  completion:nil];
   }];
 }
 
-- (void)addContractOmniboxAnimations:(UIViewPropertyAnimator*)animator
-    API_AVAILABLE(ios(10.0)) {
-  UIView* trailingView = [self rightView];
+- (void)addContractOmniboxAnimations:(UIViewPropertyAnimator*)animator {
   [animator addAnimations:^{
-    trailingView.alpha = 0;
-    trailingView.frame.origin = CGPointMake(
-        trailingView.frame.origin.x + kPositionAnimationLeadingOffset,
-        trailingView.frame.origin.y);
+    self.rightView.alpha = 0;
+    self.rightView.frame =
+        CGRectLayoutOffset(self.rightView.frame, kToolbarButtonAnimationOffset);
   }];
-
   [animator addCompletion:^(UIViewAnimatingPosition finalPosition) {
     self.rightView = nil;
   }];
diff --git a/ios/chrome/browser/ui/toolbar/BUILD.gn b/ios/chrome/browser/ui/toolbar/BUILD.gn
index 56b4a345..0d34dfd 100644
--- a/ios/chrome/browser/ui/toolbar/BUILD.gn
+++ b/ios/chrome/browser/ui/toolbar/BUILD.gn
@@ -72,6 +72,9 @@
     "//ios/chrome/browser/ui/colors",
     "//ios/chrome/browser/ui/commands",
     "//ios/chrome/browser/ui/fancy_ui",
+    "//ios/chrome/browser/ui/fullscreen",
+    "//ios/chrome/browser/ui/fullscreen:new_fullscreen",
+    "//ios/chrome/browser/ui/fullscreen:new_fullscreen_ui",
     "//ios/chrome/browser/ui/history",
     "//ios/chrome/browser/ui/history_popup/requirements",
     "//ios/chrome/browser/ui/keyboard",
diff --git a/ios/chrome/browser/ui/toolbar/clean/BUILD.gn b/ios/chrome/browser/ui/toolbar/clean/BUILD.gn
index 54ea7da..38f83f8 100644
--- a/ios/chrome/browser/ui/toolbar/clean/BUILD.gn
+++ b/ios/chrome/browser/ui/toolbar/clean/BUILD.gn
@@ -33,6 +33,8 @@
     "//ios/chrome/browser/ui/commands",
     "//ios/chrome/browser/ui/commands",
     "//ios/chrome/browser/ui/coordinators",
+    "//ios/chrome/browser/ui/fullscreen",
+    "//ios/chrome/browser/ui/fullscreen:new_fullscreen",
     "//ios/chrome/browser/ui/history_popup/requirements",
     "//ios/chrome/browser/ui/omnibox",
     "//ios/chrome/browser/ui/omnibox:omnibox_internal",
@@ -69,6 +71,7 @@
     "//ios/chrome/browser/ui/activity_services/requirements",
     "//ios/chrome/browser/ui/bubble",
     "//ios/chrome/browser/ui/commands",
+    "//ios/chrome/browser/ui/fullscreen:new_fullscreen_ui",
     "//ios/chrome/browser/ui/history_popup/requirements",
     "//ios/chrome/browser/ui/toolbar/public",
     "//ios/chrome/browser/ui/voice",
diff --git a/ios/chrome/browser/ui/toolbar/clean/toolbar_coordinator.mm b/ios/chrome/browser/ui/toolbar/clean/toolbar_coordinator.mm
index 3a1181c..d8aaf95 100644
--- a/ios/chrome/browser/ui/toolbar/clean/toolbar_coordinator.mm
+++ b/ios/chrome/browser/ui/toolbar/clean/toolbar_coordinator.mm
@@ -7,6 +7,7 @@
 #import <CoreLocation/CoreLocation.h>
 
 #include "base/mac/foundation_util.h"
+#include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/user_metrics.h"
 #include "base/metrics/user_metrics_action.h"
@@ -20,6 +21,10 @@
 #include "ios/chrome/browser/chrome_url_constants.h"
 #include "ios/chrome/browser/reading_list/reading_list_model_factory.h"
 #include "ios/chrome/browser/search_engines/template_url_service_factory.h"
+#import "ios/chrome/browser/ui/fullscreen/fullscreen_controller.h"
+#import "ios/chrome/browser/ui/fullscreen/fullscreen_controller_factory.h"
+#import "ios/chrome/browser/ui/fullscreen/fullscreen_features.h"
+#import "ios/chrome/browser/ui/fullscreen/fullscreen_ui_updater.h"
 #include "ios/chrome/browser/ui/omnibox/location_bar_controller.h"
 #include "ios/chrome/browser/ui/omnibox/location_bar_controller_impl.h"
 #include "ios/chrome/browser/ui/omnibox/location_bar_delegate.h"
@@ -58,6 +63,8 @@
 @interface ToolbarCoordinator ()<LocationBarDelegate, OmniboxPopupPositioner> {
   std::unique_ptr<LocationBarControllerImpl> _locationBar;
   std::unique_ptr<OmniboxPopupViewIOS> _popupView;
+  // Observer that updates |toolbarViewController| for fullscreen events.
+  std::unique_ptr<FullscreenControllerObserver> _fullscreenObserver;
 }
 
 // The View Controller managed by this coordinator.
@@ -177,6 +184,14 @@
   self.toolbarViewController.locationBarView = self.locationBarView;
   self.toolbarViewController.dispatcher = self.dispatcher;
 
+  if (base::FeatureList::IsEnabled(fullscreen::features::kNewFullscreen)) {
+    _fullscreenObserver =
+        base::MakeUnique<FullscreenUIUpdater>(self.toolbarViewController);
+    FullscreenControllerFactory::GetInstance()
+        ->GetForBrowserState(self.browserState)
+        ->AddObserver(_fullscreenObserver.get());
+  }
+
   DCHECK(self.toolbarViewController.toolsMenuButton);
   self.toolsMenuButtonObserverBridge = [[ToolsMenuButtonObserverBridge alloc]
       initWithModel:ReadingListModelFactory::GetForBrowserState(
@@ -202,6 +217,13 @@
   _locationBar.reset();
   self.locationBarView = nil;
   [self stopObservingTTSNotifications];
+
+  if (base::FeatureList::IsEnabled(fullscreen::features::kNewFullscreen)) {
+    FullscreenControllerFactory::GetInstance()
+        ->GetForBrowserState(self.browserState)
+        ->RemoveObserver(_fullscreenObserver.get());
+    _fullscreenObserver = nullptr;
+  }
 }
 
 #pragma mark - Public
diff --git a/ios/chrome/browser/ui/toolbar/clean/toolbar_view_controller.h b/ios/chrome/browser/ui/toolbar/clean/toolbar_view_controller.h
index f29bc53..0fa0458 100644
--- a/ios/chrome/browser/ui/toolbar/clean/toolbar_view_controller.h
+++ b/ios/chrome/browser/ui/toolbar/clean/toolbar_view_controller.h
@@ -9,6 +9,7 @@
 
 #import "ios/chrome/browser/ui/activity_services/requirements/activity_service_positioner.h"
 #import "ios/chrome/browser/ui/bubble/bubble_view_anchor_point_provider.h"
+#import "ios/chrome/browser/ui/fullscreen/fullscreen_ui_element.h"
 #import "ios/chrome/browser/ui/toolbar/clean/toolbar_consumer.h"
 
 @protocol ApplicationCommands;
@@ -22,6 +23,7 @@
 @interface ToolbarViewController
     : UIViewController<ActivityServicePositioner,
                        BubbleViewAnchorPointProvider,
+                       FullscreenUIElement,
                        ToolbarConsumer>
 
 - (instancetype)initWithDispatcher:
diff --git a/ios/chrome/browser/ui/toolbar/clean/toolbar_view_controller.mm b/ios/chrome/browser/ui/toolbar/clean/toolbar_view_controller.mm
index a809e05..526ff58 100644
--- a/ios/chrome/browser/ui/toolbar/clean/toolbar_view_controller.mm
+++ b/ios/chrome/browser/ui/toolbar/clean/toolbar_view_controller.mm
@@ -10,6 +10,7 @@
 #import "ios/chrome/browser/ui/commands/browser_commands.h"
 #import "ios/chrome/browser/ui/commands/history_popup_commands.h"
 #import "ios/chrome/browser/ui/commands/start_voice_search_command.h"
+#import "ios/chrome/browser/ui/fullscreen/fullscreen_scroll_end_animator.h"
 #include "ios/chrome/browser/ui/rtl_geometry.h"
 #import "ios/chrome/browser/ui/toolbar/clean/toolbar_button.h"
 #import "ios/chrome/browser/ui/toolbar/clean/toolbar_button_factory.h"
@@ -141,13 +142,28 @@
   // the StackView.
   self.contractButton.hidden = NO;
   self.contractButton.alpha = 0;
+
+  [UIViewPropertyAnimator
+      runningPropertyAnimatorWithDuration:ios::material::kDuration2
+                                    delay:0
+                                  options:UIViewAnimationOptionCurveEaseIn
+                               animations:^{
+                                 [self
+                                     setHorizontalTranslationOffset:
+                                         kToolbarButtonAnimationOffset
+                                                         forButtons:
+                                                  self.leadingStackViewButtons];
+                                 [self
+                                     setHorizontalTranslationOffset:
+                                         -kToolbarButtonAnimationOffset
+                                                         forButtons:
+                                                 self.trailingStackViewButtons];
+                                 [self setAllVisibleToolbarButtonsOpacity:0];
+                               }
+                               completion:nil];
+
   [animator addAnimations:^{
     [self.view layoutIfNeeded];
-    [self setHorizontalTranslationOffset:-kToolbarButtonAnimationOffset
-                              forButtons:self.leadingStackViewButtons];
-    [self setHorizontalTranslationOffset:kToolbarButtonAnimationOffset
-                              forButtons:self.trailingStackViewButtons];
-    [self setAllVisibleToolbarButtonsOpacity:0];
   }];
   // When the locationBarContainer has been expanded the Contract button will
   // fade in.
@@ -356,35 +372,48 @@
         constraintEqualToConstant:kToolbarShadowHeight],
   ]];
 
-  // Stack views directly in view constraints. Main StackViews.
+  // Stack views constraints.
   // Layout: |[leadingStackView]-[locationBarContainer]-[trailingStackView]|.
+  // Safe Area constraints.
   CGFloat leadingMargin = IsIPadIdiom() ? kLeadingMarginIPad : 0;
   UILayoutGuide* viewSafeAreaGuide = SafeAreaLayoutGuideForView(self.view);
-  NSArray* stackViewRegularConstraints = @[
+  [NSLayoutConstraint activateConstraints:@[
     [self.leadingStackView.leadingAnchor
         constraintEqualToAnchor:viewSafeAreaGuide.leadingAnchor
                        constant:leadingMargin],
     [self.trailingStackView.trailingAnchor
         constraintEqualToAnchor:viewSafeAreaGuide.trailingAnchor]
-  ];
+  ]];
+  // Stackviews and locationBar Spacing constraints. These will be disabled when
+  // expanding the omnibox.
+  NSArray<NSLayoutConstraint*>* stackViewSpacingConstraint = [NSLayoutConstraint
+      constraintsWithVisualFormat:
+          @"H:[leadingStack]-(spacing)-[locationBar]-(spacing)-[trailingStack]"
+                          options:0
+                          metrics:@{
+                            @"spacing" : @(kHorizontalMargin)
+                          }
+                            views:@{
+                              @"leadingStack" : self.leadingStackView,
+                              @"locationBar" : self.locationBarContainer,
+                              @"trailingStack" : self.trailingStackView
+                            }];
   [self.regularToolbarConstraints
-      addObjectsFromArray:stackViewRegularConstraints];
-  [NSLayoutConstraint activateConstraints:stackViewRegularConstraints];
+      addObjectsFromArray:stackViewSpacingConstraint];
+  // Vertical constraints.
+  [NSLayoutConstraint activateConstraints:stackViewSpacingConstraint];
   ApplyVisualConstraintsWithMetrics(
       @[
-        @"H:[leadingStack]-(spacing)-[locationBar]-(spacing)-[trailingStack]",
         @"V:[leadingStack(height)]-(margin)-|",
         @"V:[trailingStack(height)]-(margin)-|"
       ],
       @{
         @"leadingStack" : self.leadingStackView,
-        @"locationBar" : self.locationBarContainer,
         @"trailingStack" : self.trailingStackView
       },
       @{
         @"height" : @(kToolbarHeight - 2 * kButtonVerticalMargin),
         @"margin" : @(kButtonVerticalMargin),
-        @"spacing" : @(kHorizontalMargin)
       });
 
   // LocationBarContainer constraints.
@@ -752,6 +781,27 @@
                                             toView:self.toolsMenuButton.window];
 }
 
+#pragma mark - FullscreenUIElement
+
+- (void)updateForFullscreenProgress:(CGFloat)progress {
+  self.leadingStackView.alpha = progress;
+  self.locationBarContainer.alpha = progress;
+  self.trailingStackView.alpha = progress;
+}
+
+- (void)updateForFullscreenEnabled:(BOOL)enabled {
+  if (!enabled)
+    [self updateForFullscreenProgress:1.0];
+}
+
+- (void)finishFullscreenScrollWithAnimator:
+    (FullscreenScrollEndAnimator*)animator {
+  CGFloat finalProgress = animator.finalProgress;
+  [animator addAnimations:^() {
+    [self updateForFullscreenProgress:finalProgress];
+  }];
+}
+
 #pragma mark - Helper Methods
 
 // Updates all Buttons visibility to match any recent WebState change.
diff --git a/ios/chrome/browser/ui/toolbar/legacy_toolbar_coordinator.h b/ios/chrome/browser/ui/toolbar/legacy_toolbar_coordinator.h
index 6eb62c48..e42d540f 100644
--- a/ios/chrome/browser/ui/toolbar/legacy_toolbar_coordinator.h
+++ b/ios/chrome/browser/ui/toolbar/legacy_toolbar_coordinator.h
@@ -9,6 +9,7 @@
 
 #import "ios/chrome/browser/chrome_coordinator.h"
 #import "ios/chrome/browser/ui/bubble/bubble_view_anchor_point_provider.h"
+#import "ios/chrome/browser/ui/fullscreen/fullscreen_ui_element.h"
 #import "ios/chrome/browser/ui/ntp/incognito_view_controller_delegate.h"
 #import "ios/chrome/browser/ui/side_swipe/side_swipe_toolbar_interacting.h"
 #import "ios/chrome/browser/ui/toolbar/omnibox_focuser.h"
@@ -37,7 +38,8 @@
                   ActivityServicePositioner,
                   QRScannerResultLoading,
                   BubbleViewAnchorPointProvider,
-                  ToolsMenuPresentationProvider>
+                  ToolsMenuPresentationProvider,
+                  FullscreenUIElement>
 
 - (void)setToolsMenuIsVisibleForToolsMenuButton:(BOOL)isVisible;
 - (void)start;
diff --git a/ios/chrome/browser/ui/toolbar/legacy_toolbar_coordinator.mm b/ios/chrome/browser/ui/toolbar/legacy_toolbar_coordinator.mm
index 70c978e..b169e67 100644
--- a/ios/chrome/browser/ui/toolbar/legacy_toolbar_coordinator.mm
+++ b/ios/chrome/browser/ui/toolbar/legacy_toolbar_coordinator.mm
@@ -4,7 +4,13 @@
 
 #import "ios/chrome/browser/ui/toolbar/legacy_toolbar_coordinator.h"
 
+#include "base/memory/ptr_util.h"
+#import "ios/chrome/browser/tabs/tab_model.h"
 #import "ios/chrome/browser/ui/commands/toolbar_commands.h"
+#import "ios/chrome/browser/ui/fullscreen/fullscreen_controller.h"
+#import "ios/chrome/browser/ui/fullscreen/fullscreen_controller_factory.h"
+#import "ios/chrome/browser/ui/fullscreen/fullscreen_features.h"
+#import "ios/chrome/browser/ui/fullscreen/fullscreen_ui_updater.h"
 #import "ios/chrome/browser/ui/toolbar/clean/toolbar_button_updater.h"
 #import "ios/chrome/browser/ui/toolbar/omnibox_focuser.h"
 #import "ios/chrome/browser/ui/toolbar/web_toolbar_controller.h"
@@ -19,6 +25,8 @@
 @interface LegacyToolbarCoordinator () {
   // Coordinator for the tools menu UI.
   ToolsMenuCoordinator* _toolsMenuCoordinator;
+  // The fullscreen updater.
+  std::unique_ptr<FullscreenUIUpdater> _fullscreenUpdater;
 }
 
 @property(nonatomic, strong) id<Toolbar> toolbarController;
@@ -54,7 +62,24 @@
   }
   return self;
 }
+
+- (void)start {
+  if (base::FeatureList::IsEnabled(fullscreen::features::kNewFullscreen)) {
+    _fullscreenUpdater =
+        base::MakeUnique<FullscreenUIUpdater>(self.toolbarController);
+    FullscreenControllerFactory::GetInstance()
+        ->GetForBrowserState(self.tabModel.browserState)
+        ->AddObserver(_fullscreenUpdater.get());
+  }
+}
+
 - (void)stop {
+  if (base::FeatureList::IsEnabled(fullscreen::features::kNewFullscreen)) {
+    FullscreenControllerFactory::GetInstance()
+        ->GetForBrowserState(self.tabModel.browserState)
+        ->RemoveObserver(_fullscreenUpdater.get());
+    _fullscreenUpdater = nullptr;
+  }
   self.toolbarController = nil;
 }
 
diff --git a/ios/chrome/browser/ui/toolbar/toolbar_adapter.mm b/ios/chrome/browser/ui/toolbar/toolbar_adapter.mm
index 72a0d01..79e9a40 100644
--- a/ios/chrome/browser/ui/toolbar/toolbar_adapter.mm
+++ b/ios/chrome/browser/ui/toolbar/toolbar_adapter.mm
@@ -183,6 +183,21 @@
       anchorPointForToolsMenuButton:direction];
 }
 
+#pragma mark - FullscreenUIElement
+
+// FullscreenUIElements in this adapter are no-ops.  ToolbarCoordinator updates
+// its view controller's UI for fullscreen events.
+
+- (void)updateForFullscreenProgress:(CGFloat)progress {
+}
+
+- (void)updateForFullscreenEnabled:(BOOL)enabled {
+}
+
+- (void)finishFullscreenScrollWithAnimator:
+    (FullscreenScrollEndAnimator*)animator {
+}
+
 #pragma mark - ToolsMenuPresentationProvider
 
 - (UIButton*)presentingButtonForToolsMenuCoordinator:
diff --git a/ios/chrome/browser/ui/toolbar/toolbar_controller.h b/ios/chrome/browser/ui/toolbar/toolbar_controller.h
index 31ce060..11f8de6 100644
--- a/ios/chrome/browser/ui/toolbar/toolbar_controller.h
+++ b/ios/chrome/browser/ui/toolbar/toolbar_controller.h
@@ -10,6 +10,7 @@
 #import "base/mac/scoped_nsobject.h"
 #import "ios/chrome/browser/ui/activity_services/requirements/activity_service_positioner.h"
 #import "ios/chrome/browser/ui/bubble/bubble_view_anchor_point_provider.h"
+#import "ios/chrome/browser/ui/fullscreen/fullscreen_ui_element.h"
 #import "ios/chrome/browser/ui/toolbar/legacy_toolbar_view.h"
 #import "ios/chrome/browser/ui/toolbar/public/abstract_toolbar.h"
 #import "ios/chrome/browser/ui/toolbar/public/toolbar_controller_constants.h"
@@ -25,9 +26,10 @@
 // buttons (forwarding to the delegate). This is not intended to be used
 // on its own, but to be subclassed by more specific toolbars that provide
 // more buttons in the empty space.
-@interface ToolbarController : UIViewController<ActivityServicePositioner,
+@interface ToolbarController : UIViewController<AbstractToolbar,
+                                                ActivityServicePositioner,
                                                 BubbleViewAnchorPointProvider,
-                                                AbstractToolbar,
+                                                FullscreenUIElement,
                                                 ToolsMenuPresentationProvider>
 
 // The top-level toolbar view.
diff --git a/ios/chrome/browser/ui/toolbar/toolbar_controller.mm b/ios/chrome/browser/ui/toolbar/toolbar_controller.mm
index 3974f40c..9a505e6 100644
--- a/ios/chrome/browser/ui/toolbar/toolbar_controller.mm
+++ b/ios/chrome/browser/ui/toolbar/toolbar_controller.mm
@@ -18,6 +18,7 @@
 #include "ios/chrome/browser/ui/bubble/bubble_util.h"
 #import "ios/chrome/browser/ui/commands/application_commands.h"
 #import "ios/chrome/browser/ui/commands/browser_commands.h"
+#import "ios/chrome/browser/ui/fullscreen/fullscreen_scroll_end_animator.h"
 #import "ios/chrome/browser/ui/image_util.h"
 #import "ios/chrome/browser/ui/reversed_animation.h"
 #include "ios/chrome/browser/ui/rtl_geometry.h"
@@ -165,6 +166,7 @@
 
     contentView_ = [[UIView alloc] initWithFrame:viewFrame];
     contentView_.translatesAutoresizingMaskIntoConstraints = NO;
+    contentView_.layer.allowsGroupOpacity = YES;
     [self.view addSubview:contentView_];
     NSLayoutConstraint* safeAreaLeading = nil;
     NSLayoutConstraint* safeAreaTrailing = nil;
@@ -757,6 +759,25 @@
                                            toView:toolsMenuButton_.window];
 }
 
+#pragma mark - FullscreenUIElement
+
+- (void)updateForFullscreenProgress:(CGFloat)progress {
+  self.contentView.alpha = progress;
+}
+
+- (void)updateForFullscreenEnabled:(BOOL)enabled {
+  if (!enabled)
+    [self updateForFullscreenProgress:1.0];
+}
+
+- (void)finishFullscreenScrollWithAnimator:
+    (FullscreenScrollEndAnimator*)animator {
+  CGFloat finalProgress = animator.finalProgress;
+  [animator addAnimations:^() {
+    [self updateForFullscreenProgress:finalProgress];
+  }];
+}
+
 #pragma mark - CAAnimationDelegate
 // WebToolbarController conforms to CAAnimationDelegate.
 - (void)animationDidStart:(CAAnimation*)anim {
diff --git a/ios/chrome/browser/ui/toolbar/web_toolbar_controller.mm b/ios/chrome/browser/ui/toolbar/web_toolbar_controller.mm
index d5aaabc87..2959f54d 100644
--- a/ios/chrome/browser/ui/toolbar/web_toolbar_controller.mm
+++ b/ios/chrome/browser/ui/toolbar/web_toolbar_controller.mm
@@ -44,6 +44,7 @@
 #import "ios/chrome/browser/ui/commands/browser_commands.h"
 #import "ios/chrome/browser/ui/commands/external_search_commands.h"
 #import "ios/chrome/browser/ui/commands/start_voice_search_command.h"
+#import "ios/chrome/browser/ui/fullscreen/fullscreen_features.h"
 #import "ios/chrome/browser/ui/image_util.h"
 #include "ios/chrome/browser/ui/omnibox/location_bar_controller.h"
 #include "ios/chrome/browser/ui/omnibox/location_bar_controller_impl.h"
@@ -527,7 +528,8 @@
 
   [self startObservingTTSNotifications];
 
-  [self.view setDelegate:self];
+  if (!base::FeatureList::IsEnabled(fullscreen::features::kNewFullscreen))
+    [self.view setDelegate:self];
 
   if (idiom == IPHONE_IDIOM) {
     [[self stackButton] addTarget:dispatcher
diff --git a/ios/web/web_state/ui/crw_web_view_content_view.mm b/ios/web/web_state/ui/crw_web_view_content_view.mm
index 4fc5200..c0b8802 100644
--- a/ios/web/web_state/ui/crw_web_view_content_view.mm
+++ b/ios/web/web_state/ui/crw_web_view_content_view.mm
@@ -5,6 +5,8 @@
 #import "ios/web/public/web_state/ui/crw_web_view_content_view.h"
 
 #import <WebKit/WebKit.h>
+#include <cmath>
+#include <limits>
 
 #include "base/logging.h"
 
@@ -116,30 +118,31 @@
 }
 
 - (void)setTopContentPadding:(CGFloat)newTopPadding {
-  if (!self.shouldUseInsetForTopPadding) {
-    if (_topContentPadding != newTopPadding) {
-      // Update the content offset of the scroll view to match the padding
-      // that will be included in the frame.
-      CGFloat paddingChange = newTopPadding - _topContentPadding;
-      CGPoint contentOffset = [_scrollView contentOffset];
-      contentOffset.y += paddingChange;
-      [_scrollView setContentOffset:contentOffset];
-      _topContentPadding = newTopPadding;
-      // Update web view frame immediately to make |topContentPadding|
-      // animatable.
-      [self updateWebViewFrame];
-      // Setting WKWebView frame can mistakenly reset contentOffset. Change it
-      // back to the initial value if necessary.
-      // TODO(crbug.com/645857): Remove this workaround once WebKit bug is
-      // fixed.
-      if ([_scrollView contentOffset].y != contentOffset.y) {
-        [_scrollView setContentOffset:contentOffset];
-      }
-    }
-  } else {
+  CGFloat delta = std::fabs(_topContentPadding - newTopPadding);
+  if (delta <= std::numeric_limits<CGFloat>::epsilon())
+    return;
+  if (self.shouldUseInsetForTopPadding) {
     UIEdgeInsets inset = [_scrollView contentInset];
     inset.top = newTopPadding;
     [_scrollView setContentInset:inset];
+  } else {
+    // Update the content offset of the scroll view to match the padding
+    // that will be included in the frame.
+    CGFloat paddingChange = newTopPadding - _topContentPadding;
+    CGPoint contentOffset = [_scrollView contentOffset];
+    contentOffset.y += paddingChange;
+    [_scrollView setContentOffset:contentOffset];
+    _topContentPadding = newTopPadding;
+    // Update web view frame immediately to make |topContentPadding|
+    // animatable.
+    [self updateWebViewFrame];
+    // Setting WKWebView frame can mistakenly reset contentOffset. Change it
+    // back to the initial value if necessary.
+    // TODO(crbug.com/645857): Remove this workaround once WebKit bug is
+    // fixed.
+    if ([_scrollView contentOffset].y != contentOffset.y) {
+      [_scrollView setContentOffset:contentOffset];
+    }
   }
 }
 
diff --git a/net/url_request/url_request_context_builder.cc b/net/url_request/url_request_context_builder.cc
index 0d566da4..6bdf43ed 100644
--- a/net/url_request/url_request_context_builder.cc
+++ b/net/url_request/url_request_context_builder.cc
@@ -150,6 +150,12 @@
 
   ~ContainerURLRequestContext() override {
 #if BUILDFLAG(ENABLE_REPORTING)
+    // Destroy the NetworkErrorLoggingDelegate so that destroying the
+    // ReportingService (which might abort in-flight URLRequests, generating
+    // network errors) won't recursively try to queue more network error
+    // reports.
+    storage_.set_network_error_logging_delegate(nullptr);
+
     // Destroy the ReportingService before the rest of the URLRequestContext, so
     // it cancels any pending requests it may have.
     storage_.set_reporting_service(nullptr);
diff --git a/printing/BUILD.gn b/printing/BUILD.gn
index 71ea5f6..086afa4 100644
--- a/printing/BUILD.gn
+++ b/printing/BUILD.gn
@@ -33,12 +33,6 @@
     "backend/printing_info_win.h",
     "emf_win.cc",
     "emf_win.h",
-    "image.cc",
-    "image.h",
-    "image_android.cc",
-    "image_linux.cc",
-    "image_mac.cc",
-    "image_win.cc",
     "metafile.cc",
     "metafile.h",
     "metafile_skia_wrapper.cc",
@@ -242,10 +236,6 @@
       "pdf_transform.h",
     ]
   }
-
-  if (is_fuchsia) {
-    sources += [ "image_fuchsia.cc" ]
-  }
 }
 
 static_library("test_support") {
@@ -253,12 +243,25 @@
   sources = [
     "backend/test_print_backend.cc",
     "backend/test_print_backend.h",
+    "image.cc",
+    "image.h",
+    "image_android.cc",
+    "image_linux.cc",
+    "image_mac.cc",
+    "image_win.cc",
   ]
+  if (is_fuchsia) {
+    sources += [ "image_fuchsia.cc" ]
+  }
+
   public_deps = [
     "//printing",
+    "//ui/gfx/geometry",
   ]
   deps = [
     "//base",
+    "//skia",
+    "//ui/gfx",
   ]
 }
 
diff --git a/printing/image.h b/printing/image.h
index 0245185f..13ac4d5 100644
--- a/printing/image.h
+++ b/printing/image.h
@@ -12,7 +12,6 @@
 #include <vector>
 
 #include "base/logging.h"
-#include "printing/printing_export.h"
 #include "ui/gfx/geometry/size.h"
 
 namespace base {
@@ -25,7 +24,7 @@
 
 // Lightweight raw-bitmap management. The image, once initialized, is immutable.
 // The main purpose is testing image contents.
-class PRINTING_EXPORT Image {
+class Image {
  public:
   // Creates the image from the metafile.  Deduces bounds based on bounds in
   // metafile.  If loading fails size().IsEmpty() will be true.
diff --git a/printing/image_android.cc b/printing/image_android.cc
index 544cf07..2ae4c3a 100644
--- a/printing/image_android.cc
+++ b/printing/image_android.cc
@@ -7,6 +7,7 @@
 namespace printing {
 
 bool Image::LoadMetafile(const Metafile& metafile) {
+  NOTIMPLEMENTED();
   return false;
 }
 
diff --git a/printing/image_linux.cc b/printing/image_linux.cc
index d89c4e9..6ccb2139 100644
--- a/printing/image_linux.cc
+++ b/printing/image_linux.cc
@@ -7,6 +7,7 @@
 namespace printing {
 
 bool Image::LoadMetafile(const Metafile& metafile) {
+  NOTIMPLEMENTED();
   return false;
 }
 
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json
index 0a72917..74c59ef 100644
--- a/testing/buildbot/chromium.chromiumos.json
+++ b/testing/buildbot/chromium.chromiumos.json
@@ -1150,6 +1150,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "ozone_x11_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "pdf_unittests"
       },
       {
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl
index 689ae0a..c69ff89 100644
--- a/testing/buildbot/gn_isolate_map.pyl
+++ b/testing/buildbot/gn_isolate_map.pyl
@@ -834,6 +834,10 @@
     "label": "//ui/ozone/gl:ozone_gl_unittests",
     "type": "console_test_launcher",
   },
+  "ozone_x11_unittests": {
+    "label": "//ui/ozone:ozone_x11_unittests",
+    "type": "windowed_test_launcher",
+  },
   "pdf_fuzzers": {
     "label": "//pdf/pdfium/fuzzers:pdf_fuzzers",
     "type": "additional_compile_target",
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index 03dbaa6b..21e9ccd 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -477,6 +477,7 @@
       ],
     },
     'ozone_unittests': {},
+    'ozone_x11_unittests': {},
     'views_mus_unittests': {},
     'views_mus_interactive_ui_tests': {},
     'viz_content_browsertests': {
diff --git a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
index a6bf57d..fe725b46 100644
--- a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
+++ b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
@@ -42809,6 +42809,18 @@
      {}
     ]
    ],
+   "css/css-multicol/multicol-gap-fraction-002.html": [
+    [
+     "/css/css-multicol/multicol-gap-fraction-002.html",
+     [
+      [
+       "/css/reference/nothing.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "css/css-multicol/multicol-gap-large-001.xht": [
     [
      "/css/css-multicol/multicol-gap-large-001.xht",
@@ -46757,6 +46769,198 @@
      {}
     ]
    ],
+   "css/css-style-attr/style-attr-braces-001.xht": [
+    [
+     "/css/css-style-attr/style-attr-braces-001.xht",
+     [
+      [
+       "/css/css-style-attr/reference/ref-green-on-green.xht",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-style-attr/style-attr-braces-002-quirks.htm": [
+    [
+     "/css/css-style-attr/style-attr-braces-002-quirks.htm",
+     [
+      [
+       "/css/css-style-attr/reference/ref-green-on-green.xht",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-style-attr/style-attr-braces-002.xht": [
+    [
+     "/css/css-style-attr/style-attr-braces-002.xht",
+     [
+      [
+       "/css/css-style-attr/reference/ref-green-on-green.xht",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-style-attr/style-attr-braces-003.xht": [
+    [
+     "/css/css-style-attr/style-attr-braces-003.xht",
+     [
+      [
+       "/css/css-style-attr/reference/ref-green-on-green.xht",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-style-attr/style-attr-cascade-001.xht": [
+    [
+     "/css/css-style-attr/style-attr-cascade-001.xht",
+     [
+      [
+       "/css/css-style-attr/reference/ref-green.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-style-attr/style-attr-cascade-002.xht": [
+    [
+     "/css/css-style-attr/style-attr-cascade-002.xht",
+     [
+      [
+       "/css/css-style-attr/reference/ref-green.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-style-attr/style-attr-cascade-003.xht": [
+    [
+     "/css/css-style-attr/style-attr-cascade-003.xht",
+     [
+      [
+       "/css/css-style-attr/reference/ref-green.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-style-attr/style-attr-cascade-004.xht": [
+    [
+     "/css/css-style-attr/style-attr-cascade-004.xht",
+     [
+      [
+       "/css/css-style-attr/reference/ref-white-on-green-background.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-style-attr/style-attr-cascade-005.xht": [
+    [
+     "/css/css-style-attr/style-attr-cascade-005.xht",
+     [
+      [
+       "/css/css-style-attr/reference/ref-white-on-green-background.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-style-attr/style-attr-cascade-006.xht": [
+    [
+     "/css/css-style-attr/style-attr-cascade-006.xht",
+     [
+      [
+       "/css/css-style-attr/reference/ref-green.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-style-attr/style-attr-cascade-007.xht": [
+    [
+     "/css/css-style-attr/style-attr-cascade-007.xht",
+     [
+      [
+       "/css/css-style-attr/reference/style-attr-cascade-007.xht",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-style-attr/style-attr-specificity-001.xht": [
+    [
+     "/css/css-style-attr/style-attr-specificity-001.xht",
+     [
+      [
+       "/css/css-style-attr/reference/ref-green-on-green.xht",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-style-attr/style-attr-specificity-002.xht": [
+    [
+     "/css/css-style-attr/style-attr-specificity-002.xht",
+     [
+      [
+       "/css/css-style-attr/reference/ref-green-on-green.xht",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-style-attr/style-attr-urls-001.xht": [
+    [
+     "/css/css-style-attr/style-attr-urls-001.xht",
+     [
+      [
+       "/css/css-style-attr/reference/ref-green-on-green.xht",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-style-attr/style-attr-urls-002.xht": [
+    [
+     "/css/css-style-attr/style-attr-urls-002.xht",
+     [
+      [
+       "/css/css-style-attr/reference/ref-green-on-green.xht",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-style-attr/style-attr-urls-003.xht": [
+    [
+     "/css/css-style-attr/style-attr-urls-003.xht",
+     [
+      [
+       "/css/css-style-attr/reference/ref-green-on-green2.xht",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "css/css-tables/floats/floats-wrap-bfc-006b.xht": [
     [
      "/css/css-tables/floats/floats-wrap-bfc-006b.xht",
@@ -109452,11 +109656,6 @@
      {}
     ]
    ],
-   "css/css-multicol/multicol-fill-auto-ref.xht": [
-    [
-     {}
-    ]
-   ],
    "css/css-multicol/multicol-fill-balance-001-ref.xht": [
     [
      {}
@@ -111022,6 +111221,231 @@
      {}
     ]
    ],
+   "css/css-style-attr/reference/ref-green-on-green.xht": [
+    [
+     {}
+    ]
+   ],
+   "css/css-style-attr/reference/ref-green-on-green2.xht": [
+    [
+     {}
+    ]
+   ],
+   "css/css-style-attr/reference/ref-green.html": [
+    [
+     {}
+    ]
+   ],
+   "css/css-style-attr/reference/ref-white-on-green-background.html": [
+    [
+     {}
+    ]
+   ],
+   "css/css-style-attr/reference/style-attr-cascade-007.xht": [
+    [
+     {}
+    ]
+   ],
+   "css/css-style-attr/support/1x1-green.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-style-attr/support/1x1-lime.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-style-attr/support/1x1-maroon.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-style-attr/support/1x1-navy.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-style-attr/support/1x1-red.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-style-attr/support/1x1-white.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-style-attr/support/60x60-gg-rr.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-style-attr/support/60x60-green.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-style-attr/support/60x60-red.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-style-attr/support/a-green.css": [
+    [
+     {}
+    ]
+   ],
+   "css/css-style-attr/support/b-green.css": [
+    [
+     {}
+    ]
+   ],
+   "css/css-style-attr/support/c-red.css": [
+    [
+     {}
+    ]
+   ],
+   "css/css-style-attr/support/cat.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-style-attr/support/pattern-grg-rgr-grg.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-style-attr/support/pattern-grg-rrg-rgg.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-style-attr/support/pattern-rgr-grg-rgr.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-style-attr/support/pattern-tr.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-style-attr/support/ruler-h-50%.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-style-attr/support/ruler-h-50px.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-style-attr/support/ruler-v-100px.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-style-attr/support/ruler-v-50px.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-style-attr/support/square-purple.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-style-attr/support/square-teal.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-style-attr/support/square-white.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-style-attr/support/support/README": [
+    [
+     {}
+    ]
+   ],
+   "css/css-style-attr/support/support/swatch-green.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-style-attr/support/support/swatch-red.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-style-attr/support/swatch-blue.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-style-attr/support/swatch-green.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-style-attr/support/swatch-lime.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-style-attr/support/swatch-orange.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-style-attr/support/swatch-red.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-style-attr/support/swatch-white.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-style-attr/support/swatch-yellow.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-style-attr/support/test-bl.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-style-attr/support/test-br.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-style-attr/support/test-inner-half-size.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-style-attr/support/test-outer.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-style-attr/support/test-tl.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-style-attr/support/test-tr.png": [
+    [
+     {}
+    ]
+   ],
    "css/css-syntax/OWNERS": [
     [
      {}
@@ -120582,6 +121006,11 @@
      {}
     ]
    ],
+   "css/reference/nothing.html": [
+    [
+     {}
+    ]
+   ],
    "css/reference/only_pass_parens_semicolon.html": [
     [
      {}
@@ -140572,6 +141001,16 @@
      {}
     ]
    ],
+   "mimesniff/mime-types/parsing.any-expected.txt": [
+    [
+     {}
+    ]
+   ],
+   "mimesniff/mime-types/parsing.any.worker-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "mimesniff/mime-types/resources/generated-mime-types.json": [
     [
      {}
@@ -188836,6 +189275,20 @@
      {}
     ]
    ],
+   "mimesniff/mime-types/parsing.any.js": [
+    [
+     "/mimesniff/mime-types/parsing.any.html",
+     {
+      "timeout": "long"
+     }
+    ],
+    [
+     "/mimesniff/mime-types/parsing.any.worker.html",
+     {
+      "timeout": "long"
+     }
+    ]
+   ],
    "mixed-content/audio-tag/http-csp/cross-origin-http/top-level/keep-scheme-redirect/optionally-blockable/opt-in-blocks.https.html": [
     [
      "/mixed-content/audio-tag/http-csp/cross-origin-http/top-level/keep-scheme-redirect/optionally-blockable/opt-in-blocks.https.html",
@@ -266271,10 +266724,6 @@
    "f63446929f6a4a1f7ba2dba47af786c487fa03d7",
    "support"
   ],
-  "css/css-multicol/multicol-fill-auto-ref.xht": [
-   "d97337c9c5fe4ff3ab4472b1c0f9f459f9d7cf8e",
-   "support"
-  ],
   "css/css-multicol/multicol-fill-balance-001-ref.xht": [
    "dfdc227760f0fb524232d65ee792f108d32fc7de",
    "support"
@@ -266319,6 +266768,10 @@
    "9d12dc2b311ab4bf2dfda4565fcdfab0008754c5",
    "reftest"
   ],
+  "css/css-multicol/multicol-gap-fraction-002.html": [
+   "67b2d75607ac68ad08012ad282ac4234946a1051",
+   "reftest"
+  ],
   "css/css-multicol/multicol-gap-large-001-ref.xht": [
    "a502a720a1ac5a28f3857caf36ccb2a9fec02776",
    "support"
@@ -269347,6 +269800,250 @@
    "5bb192165bcb7d9a619d86dbff61831fc8de71cb",
    "support"
   ],
+  "css/css-style-attr/reference/ref-green-on-green.xht": [
+   "3db4dec22e96cce52c575f4adb7a05f79917d4ea",
+   "support"
+  ],
+  "css/css-style-attr/reference/ref-green-on-green2.xht": [
+   "9a4067fbea6534ad20a0354457eb7ade8053bbf6",
+   "support"
+  ],
+  "css/css-style-attr/reference/ref-green.html": [
+   "8bc36f756c7ae32af5c52021c92bb04d1a0de876",
+   "support"
+  ],
+  "css/css-style-attr/reference/ref-white-on-green-background.html": [
+   "ae526af2bb69429c5c8e7036dcfd79c6cc00f7ee",
+   "support"
+  ],
+  "css/css-style-attr/reference/style-attr-cascade-007.xht": [
+   "1f4454897158d0a677832ac8e8e6e2d9190c10df",
+   "support"
+  ],
+  "css/css-style-attr/style-attr-braces-001.xht": [
+   "fc9473d5492cc58e5ebaf44ae3981a05bae132aa",
+   "reftest"
+  ],
+  "css/css-style-attr/style-attr-braces-002-quirks.htm": [
+   "134c9965cb75e87bb97a52040088755dbaf4eaa0",
+   "reftest"
+  ],
+  "css/css-style-attr/style-attr-braces-002.xht": [
+   "c393e217b8e0f5b2bf329931440369caa7de959b",
+   "reftest"
+  ],
+  "css/css-style-attr/style-attr-braces-003.xht": [
+   "d15816a22022609d0a127fc49fda4b0c56a2b4ee",
+   "reftest"
+  ],
+  "css/css-style-attr/style-attr-cascade-001.xht": [
+   "4d594acf436612e9ee6a378dbdf10671e286099c",
+   "reftest"
+  ],
+  "css/css-style-attr/style-attr-cascade-002.xht": [
+   "470926a6b6e174c1d217f2000001debe2d41913f",
+   "reftest"
+  ],
+  "css/css-style-attr/style-attr-cascade-003.xht": [
+   "ac31e81175c9571d7932ce227b54cbdf03c0dca9",
+   "reftest"
+  ],
+  "css/css-style-attr/style-attr-cascade-004.xht": [
+   "5cc034e3c039eaffb2042848ec3658c8af8f4c61",
+   "reftest"
+  ],
+  "css/css-style-attr/style-attr-cascade-005.xht": [
+   "1ae6ff87e9d7ebf270db8afbcf5c1b87468d9c7d",
+   "reftest"
+  ],
+  "css/css-style-attr/style-attr-cascade-006.xht": [
+   "dce3b7864fbaab8923134214316ad572a07e629f",
+   "reftest"
+  ],
+  "css/css-style-attr/style-attr-cascade-007.xht": [
+   "7d317232b9ff6927e9bdb2c109440766dd766641",
+   "reftest"
+  ],
+  "css/css-style-attr/style-attr-specificity-001.xht": [
+   "d9a5a0cd09a11cdf3dd328635b3297343e1bab5f",
+   "reftest"
+  ],
+  "css/css-style-attr/style-attr-specificity-002.xht": [
+   "e4ffe1819f2278b4b0174e407eafc9d3599d0d34",
+   "reftest"
+  ],
+  "css/css-style-attr/style-attr-urls-001.xht": [
+   "8669763b2dfa908532723b6c6673cc9641d88a8d",
+   "reftest"
+  ],
+  "css/css-style-attr/style-attr-urls-002.xht": [
+   "3c30040c9a89a256fece892ce8b4611adbf48304",
+   "reftest"
+  ],
+  "css/css-style-attr/style-attr-urls-003.xht": [
+   "3131ef4985d72c3a70461d451ff0f6b2a253895f",
+   "reftest"
+  ],
+  "css/css-style-attr/support/1x1-green.png": [
+   "51e7b6974a09eda6cb31337717c5eaeb9c44b443",
+   "support"
+  ],
+  "css/css-style-attr/support/1x1-lime.png": [
+   "b040eb633a35c0648ad72a2902361faf25bc419d",
+   "support"
+  ],
+  "css/css-style-attr/support/1x1-maroon.png": [
+   "f78757e5ebe897bd618d100718385c84e00f2369",
+   "support"
+  ],
+  "css/css-style-attr/support/1x1-navy.png": [
+   "a3fd80b2c79866fd343e18eef5a51ed6e835e53e",
+   "support"
+  ],
+  "css/css-style-attr/support/1x1-red.png": [
+   "b8da86921d04ba42f42b0a60b03c5c2172f58c2b",
+   "support"
+  ],
+  "css/css-style-attr/support/1x1-white.png": [
+   "71b246439f915ad21c7d39414d9f85c8ed73b4ca",
+   "support"
+  ],
+  "css/css-style-attr/support/60x60-gg-rr.png": [
+   "e4843d42a26189132e1bdd53e8618521330baeca",
+   "support"
+  ],
+  "css/css-style-attr/support/60x60-green.png": [
+   "2f8eb2409b0a18e0bff90725ec7eedc16e7be448",
+   "support"
+  ],
+  "css/css-style-attr/support/60x60-red.png": [
+   "415b835abaaab822aab11880354296e7356bbb0a",
+   "support"
+  ],
+  "css/css-style-attr/support/a-green.css": [
+   "a9716c222274ba868bfd06c05e28cb7762d93245",
+   "support"
+  ],
+  "css/css-style-attr/support/b-green.css": [
+   "eb78a4d12f35b4249051826ea000c53d04df80b7",
+   "support"
+  ],
+  "css/css-style-attr/support/c-red.css": [
+   "dc288b7aa49b57e0abf803741e78582ba5ceffdb",
+   "support"
+  ],
+  "css/css-style-attr/support/cat.png": [
+   "461fd17b274662b88500cdf42bab7f3b79e6019d",
+   "support"
+  ],
+  "css/css-style-attr/support/pattern-grg-rgr-grg.png": [
+   "cfb6ecc271c296c69b133a81f350a777b608bea4",
+   "support"
+  ],
+  "css/css-style-attr/support/pattern-grg-rrg-rgg.png": [
+   "27080d4df556f59d4b501e03f2847bd9da5756a9",
+   "support"
+  ],
+  "css/css-style-attr/support/pattern-rgr-grg-rgr.png": [
+   "c100a35c361205932c506f1b3399753b91e4c45e",
+   "support"
+  ],
+  "css/css-style-attr/support/pattern-tr.png": [
+   "c1e687deee7b79ae091f2b42c4f6cff430076444",
+   "support"
+  ],
+  "css/css-style-attr/support/ruler-h-50%.png": [
+   "9364be82a07500d6684a275174bcf5185444cb52",
+   "support"
+  ],
+  "css/css-style-attr/support/ruler-h-50px.png": [
+   "b3d7cc680b20a5fc44ea93f7df6d33894bc7b09b",
+   "support"
+  ],
+  "css/css-style-attr/support/ruler-v-100px.png": [
+   "d8b49696edb2bd614e9c00f96e7862798b6e621f",
+   "support"
+  ],
+  "css/css-style-attr/support/ruler-v-50px.png": [
+   "eb299dc261ec04c8f2c11afb6f7a1c2ec147587b",
+   "support"
+  ],
+  "css/css-style-attr/support/square-purple.png": [
+   "ef0619128f22e05920930420b7d96f91f860d904",
+   "support"
+  ],
+  "css/css-style-attr/support/square-teal.png": [
+   "92efae44b710cf1ddd9ba96e593dae03fb2519c4",
+   "support"
+  ],
+  "css/css-style-attr/support/square-white.png": [
+   "2f93fcc1462ba32b9b7899e5e78c869e529e68ee",
+   "support"
+  ],
+  "css/css-style-attr/support/support/README": [
+   "18698bf71d328054eba0b473486058bc9286c1a4",
+   "support"
+  ],
+  "css/css-style-attr/support/support/swatch-green.png": [
+   "eedea3e9a99c18f5fc2de3796be2c6f9da2ea07d",
+   "support"
+  ],
+  "css/css-style-attr/support/support/swatch-red.png": [
+   "c51a03a807743f59e3027371ccfbd8e80235a485",
+   "support"
+  ],
+  "css/css-style-attr/support/swatch-blue.png": [
+   "e79958e10feeeed3db88dee9bae9ea80055593c5",
+   "support"
+  ],
+  "css/css-style-attr/support/swatch-green.png": [
+   "c51a03a807743f59e3027371ccfbd8e80235a485",
+   "support"
+  ],
+  "css/css-style-attr/support/swatch-lime.png": [
+   "ee2cc3dcd6d8dda7c0e4ef3bbc7e63c74118211d",
+   "support"
+  ],
+  "css/css-style-attr/support/swatch-orange.png": [
+   "10768a5177b772013e628c7397ae64725057295d",
+   "support"
+  ],
+  "css/css-style-attr/support/swatch-red.png": [
+   "eedea3e9a99c18f5fc2de3796be2c6f9da2ea07d",
+   "support"
+  ],
+  "css/css-style-attr/support/swatch-white.png": [
+   "5bccb1922de065e551d7d106e6493bb91040f3da",
+   "support"
+  ],
+  "css/css-style-attr/support/swatch-yellow.png": [
+   "9cc73897c2e1fc45f5224d81d02a6b87bf72b1fa",
+   "support"
+  ],
+  "css/css-style-attr/support/test-bl.png": [
+   "16e4eaa4864c10e72433e575f59c9b67763fe06a",
+   "support"
+  ],
+  "css/css-style-attr/support/test-br.png": [
+   "37f65e7a21d9b9b2daa508f193b8f665c58a1ce9",
+   "support"
+  ],
+  "css/css-style-attr/support/test-inner-half-size.png": [
+   "4ed63dd2bb54a8efc166719e00e1e27406b0ee59",
+   "support"
+  ],
+  "css/css-style-attr/support/test-outer.png": [
+   "a0b8dfa40065b27f1d939ce0aab39ada3933c574",
+   "support"
+  ],
+  "css/css-style-attr/support/test-tl.png": [
+   "956e5156fd8c0e75b1c0f3b8b3b900b653663f74",
+   "support"
+  ],
+  "css/css-style-attr/support/test-tr.png": [
+   "078e1dd6dd61d36cec239ed75d02051f61fe60a5",
+   "support"
+  ],
   "css/css-syntax/OWNERS": [
    "495f99b874611fd8f82f2e33bc4b7d930cc60fde",
    "support"
@@ -290303,6 +291000,10 @@
    "4aced258fbe6ada965f2a0707fad78878af7f162",
    "support"
   ],
+  "css/reference/nothing.html": [
+   "c761e386839fbcc7eb1fc9c66f8839b3cd15ec95",
+   "support"
+  ],
   "css/reference/only_pass_parens_semicolon.html": [
    "eec4a0a2b3f8f77c8b7c124e33617ce42c6e5209",
    "support"
@@ -321079,6 +321780,18 @@
    "baa985ca1fd0aed6644d9d1cef21764cfe826a8b",
    "testharness"
   ],
+  "mimesniff/mime-types/parsing.any-expected.txt": [
+   "102170f15a37599e9e4346371fe6c6a6626540ea",
+   "support"
+  ],
+  "mimesniff/mime-types/parsing.any.js": [
+   "b40a3e56406cd6f3303877b1da07a74d0d2f9deb",
+   "testharness"
+  ],
+  "mimesniff/mime-types/parsing.any.worker-expected.txt": [
+   "102170f15a37599e9e4346371fe6c6a6626540ea",
+   "support"
+  ],
   "mimesniff/mime-types/resources/generated-mime-types.json": [
    "e4610646e4a1a417e9fccf868150aed3c5688942",
    "support"
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-multicol/multicol-fill-auto-ref.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-multicol/multicol-fill-auto-ref.xht
deleted file mode 100644
index b287fb2..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-multicol/multicol-fill-auto-ref.xht
+++ /dev/null
@@ -1,53 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
-"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<title>multicolumn | column-gap</title>
-<link rel="author" title="Opera Software ASA" href="http://www.opera.com/"/>
-<style type="text/css"><![CDATA[
-body>div {
-	font-family: ahem;
-	font-size: 0.5em;
-	line-height: 1em;
-	color: black;
-	height: 12em;
-	width: 100em;
-
-}
-div div {
-	float: left;
-	width: 26em;
-	margin-right: 5em;
-}
-]]></style>
-</head>
-
-<body>
-
-<div>
-	<div>one two three four
-	five six seven eight
-	nine ten eleven twelve
-	thirtn fourtn fiftn sixtn
-	seventn eightn ninetn twenty
-	hundred thousand million billion
-	trillion
-	one two three four
-	five six seven eight
-	nine ten eleven twelve
-	thirtn fourtn fiftn sixtn
-	seventn eightn ninetn twenty
-	hundred</div>
-	<div>thousand million billion
-	trillion
-	one two three four
-	five six seven eight
-	nine ten eleven twelve
-	thirtn fourtn fiftn sixtn
-	seventn eightn ninetn twenty
-	hundred thousand million billion
-	trillion</div>
-</div>
-
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mimesniff/mime-types/parsing.any-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/mimesniff/mime-types/parsing.any-expected.txt
new file mode 100644
index 0000000..77f8830
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/mimesniff/mime-types/parsing.any-expected.txt
@@ -0,0 +1,1871 @@
+This is a testharness.js-based test.
+Found 1857 tests; 697 PASS, 1160 FAIL, 0 TIMEOUT, 0 NOTRUN.
+PASS Loading data…
+PASS text/html;charset=gbk (Blob/File)
+PASS text/html;charset=gbk (Request/Response)
+FAIL TEXT/HTML;CHARSET=GBK (Blob/File) assert_equals: Blob expected "text/html;charset=GBK" but got "text/html;charset=gbk"
+FAIL TEXT/HTML;CHARSET=GBK (Request/Response) assert_equals: expected "text/html;charset=GBK" but got "text/html;charset=gbk"
+FAIL text/html;charset=gbk( (Blob/File) assert_equals: Blob expected "text/html;charset=\"gbk(\"" but got "text/html;charset=gbk("
+FAIL text/html;charset=gbk( (Request/Response) assert_equals: expected "text/html;charset=\"gbk(\"" but got "text/html;charset=gbk("
+FAIL text/html;x=(;charset=gbk (Blob/File) assert_equals: Blob expected "text/html;x=\"(\";charset=gbk" but got "text/html;x=(;charset=gbk"
+FAIL text/html;x=(;charset=gbk (Request/Response) assert_equals: expected "text/html;x=\"(\";charset=gbk" but got "text/html;x=(;charset=gbk"
+FAIL text/html;charset=gbk;charset=windows-1255 (Blob/File) assert_equals: Blob expected "text/html;charset=gbk" but got "text/html;charset=gbk;charset=windows-1255"
+FAIL text/html;charset=gbk;charset=windows-1255 (Request/Response) assert_equals: expected "text/html;charset=gbk" but got "text/html;charset=gbk;charset=windows-1255"
+FAIL text/html;charset =gbk (Blob/File) assert_equals: Blob expected "text/html" but got "text/html;charset =gbk"
+FAIL text/html;charset =gbk (Request/Response) assert_equals: expected "text/html" but got "text/html;charset =gbk"
+FAIL text/html ;charset=gbk (Blob/File) assert_equals: Blob expected "text/html;charset=gbk" but got "text/html ;charset=gbk"
+FAIL text/html ;charset=gbk (Request/Response) assert_equals: expected "text/html;charset=gbk" but got "text/html ;charset=gbk"
+FAIL text/html; charset=gbk (Blob/File) assert_equals: Blob expected "text/html;charset=gbk" but got "text/html; charset=gbk"
+FAIL text/html; charset=gbk (Request/Response) assert_equals: expected "text/html;charset=gbk" but got "text/html; charset=gbk"
+FAIL text/html;charset= gbk (Blob/File) assert_equals: Blob expected "text/html;charset=\" gbk\"" but got "text/html;charset= gbk"
+FAIL text/html;charset= gbk (Request/Response) assert_equals: expected "text/html;charset=\" gbk\"" but got "text/html;charset= gbk"
+PASS text/html;charset='gbk' (Blob/File)
+PASS text/html;charset='gbk' (Request/Response)
+PASS text/html;charset='gbk (Blob/File)
+PASS text/html;charset='gbk (Request/Response)
+PASS text/html;charset=gbk' (Blob/File)
+PASS text/html;charset=gbk' (Request/Response)
+FAIL text/html;test;charset=gbk (Blob/File) assert_equals: Blob expected "text/html;charset=gbk" but got "text/html;test;charset=gbk"
+FAIL text/html;test;charset=gbk (Request/Response) assert_equals: expected "text/html;charset=gbk" but got "text/html;test;charset=gbk"
+FAIL text/html;test=;charset=gbk (Blob/File) assert_equals: Blob expected "text/html;charset=gbk" but got "text/html;test=;charset=gbk"
+FAIL text/html;test=;charset=gbk (Request/Response) assert_equals: expected "text/html;charset=gbk" but got "text/html;test=;charset=gbk"
+FAIL text/html;';charset=gbk (Blob/File) assert_equals: Blob expected "text/html;charset=gbk" but got "text/html;';charset=gbk"
+FAIL text/html;';charset=gbk (Request/Response) assert_equals: expected "text/html;charset=gbk" but got "text/html;';charset=gbk"
+FAIL text/html;";charset=gbk (Blob/File) assert_equals: Blob expected "text/html;charset=gbk" but got "text/html;\";charset=gbk"
+FAIL text/html;";charset=gbk (Request/Response) assert_equals: expected "text/html;charset=gbk" but got "text/html;\";charset=gbk"
+FAIL text/html ; ; charset=gbk (Blob/File) assert_equals: Blob expected "text/html;charset=gbk" but got "text/html ; ; charset=gbk"
+FAIL text/html ; ; charset=gbk (Request/Response) assert_equals: expected "text/html;charset=gbk" but got "text/html ; ; charset=gbk"
+FAIL text/html;;;;charset=gbk (Blob/File) assert_equals: Blob expected "text/html;charset=gbk" but got "text/html;;;;charset=gbk"
+FAIL text/html;;;;charset=gbk (Request/Response) assert_equals: expected "text/html;charset=gbk" but got "text/html;;;;charset=gbk"
+FAIL text/html;charset="gbk" (Blob/File) assert_equals: Blob expected "text/html;charset=gbk" but got "text/html;charset=\"gbk\""
+FAIL text/html;charset="gbk" (Request/Response) assert_equals: expected "text/html;charset=gbk" but got "text/html;charset=\"gbk\""
+FAIL text/html;charset="gbk (Blob/File) assert_equals: Blob expected "text/html;charset=gbk" but got "text/html;charset=\"gbk"
+FAIL text/html;charset="gbk (Request/Response) assert_equals: expected "text/html;charset=gbk" but got "text/html;charset=\"gbk"
+FAIL text/html;charset=gbk" (Blob/File) assert_equals: Blob expected "text/html;charset=\"gbk\\\"\"" but got "text/html;charset=gbk\""
+FAIL text/html;charset=gbk" (Request/Response) assert_equals: expected "text/html;charset=\"gbk\\\"\"" but got "text/html;charset=gbk\""
+PASS text/html;charset=" gbk" (Blob/File)
+PASS text/html;charset=" gbk" (Request/Response)
+FAIL text/html;charset="\ gbk" (Blob/File) assert_equals: Blob expected "text/html;charset=\" gbk\"" but got "text/html;charset=\"\\ gbk\""
+FAIL text/html;charset="\ gbk" (Request/Response) assert_equals: expected "text/html;charset=\" gbk\"" but got "text/html;charset=\"\\ gbk\""
+FAIL text/html;charset="\g\b\k" (Blob/File) assert_equals: Blob expected "text/html;charset=gbk" but got "text/html;charset=\"\\g\b\k\""
+FAIL text/html;charset="\g\b\k" (Request/Response) assert_equals: expected "text/html;charset=gbk" but got "text/html;charset=\"\\g\b\k\""
+FAIL text/html;charset="gbk"x (Blob/File) assert_equals: Blob expected "text/html;charset=gbk" but got "text/html;charset=\"gbk\"x"
+FAIL text/html;charset="gbk"x (Request/Response) assert_equals: expected "text/html;charset=gbk" but got "text/html;charset=\"gbk\"x"
+FAIL text/html;charset={gbk} (Blob/File) assert_equals: Blob expected "text/html;charset=\"{gbk}\"" but got "text/html;charset={gbk}"
+FAIL text/html;charset={gbk} (Request/Response) assert_equals: expected "text/html;charset=\"{gbk}\"" but got "text/html;charset={gbk}"
+PASS text/html;0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789=x;charset=gbk (Blob/File)
+PASS text/html;0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789=x;charset=gbk (Request/Response)
+PASS 0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789/0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 (Blob/File)
+PASS 0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789/0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 (Request/Response)
+FAIL !#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz;!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz=!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz (Blob/File) assert_equals: Blob expected "!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz/!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz;!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz=!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" but got "!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz/!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz;!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz=!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
+FAIL !#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz;!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz=!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz (Request/Response) assert_equals: expected "!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz/!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz;!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz=!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" but got "!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz/!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz;!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz=!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
+FAIL x/x;x="	 !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ" (Blob/File) assert_equals: Blob expected "x/x;x=\"\t !\\\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ\"" but got ""
+FAIL x/x;x="	 !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ" (Request/Response) assert_equals: expected "x/x;x=\"\t !\\\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ\"" but got ""
+FAIL x/x;test (Blob/File) assert_equals: Blob expected "x/x" but got "x/x;test"
+FAIL x/x;test (Request/Response) assert_equals: expected "x/x" but got "x/x;test"
+FAIL x/x;test="\ (Blob/File) assert_equals: Blob expected "x/x;test=\"\\\\"" but got "x/x;test=\"\\"
+FAIL x/x;test="\ (Request/Response) assert_equals: expected "x/x;test=\"\\\\"" but got "x/x;test=\"\\"
+FAIL x/x;x=  (Blob/File) assert_equals: Blob expected "x/x" but got "x/x;x= "
+FAIL x/x;x=  (Request/Response) assert_equals: expected "x/x" but got "x/x;x="
+FAIL x/x;x=	 (Blob/File) assert_equals: Blob expected "x/x" but got ""
+FAIL x/x;x=	 (Request/Response) assert_equals: expected "x/x" but got "x/x;x="
+FAIL text/html;test=ÿ;charset=gbk (Blob/File) assert_equals: Blob expected "text/html;test=\"ÿ\";charset=gbk" but got ""
+FAIL text/html;test=ÿ;charset=gbk (Request/Response) assert_equals: expected "text/html;test=\"ÿ\";charset=gbk" but got ""
+FAIL x/x;test=�;x=x (Blob/File) assert_equals: Blob expected "x/x;x=x" but got ""
+PASS x/x;test=�;x=x (Request/Response)
+PASS  (Blob/File)
+PASS  (Request/Response)
+PASS 	 (Blob/File)
+PASS 	 (Request/Response)
+FAIL bogus (Blob/File) assert_equals: Blob expected "" but got "bogus"
+FAIL bogus (Request/Response) assert_equals: expected "" but got "bogus"
+FAIL bogus/ (Blob/File) assert_equals: Blob expected "" but got "bogus/"
+FAIL bogus/ (Request/Response) assert_equals: expected "" but got "bogus/"
+FAIL bogus/  (Blob/File) assert_equals: Blob expected "" but got "bogus/ "
+FAIL bogus/  (Request/Response) assert_equals: expected "" but got "bogus/"
+FAIL bogus/bogus/; (Blob/File) assert_equals: Blob expected "" but got "bogus/bogus/;"
+FAIL bogus/bogus/; (Request/Response) assert_equals: expected "" but got "bogus/bogus/;"
+FAIL </> (Blob/File) assert_equals: Blob expected "" but got "</>"
+FAIL </> (Request/Response) assert_equals: expected "" but got "</>"
+FAIL (/) (Blob/File) assert_equals: Blob expected "" but got "(/)"
+FAIL (/) (Request/Response) assert_equals: expected "" but got "(/)"
+FAIL text/html(;doesnot=matter (Blob/File) assert_equals: Blob expected "" but got "text/html(;doesnot=matter"
+FAIL text/html(;doesnot=matter (Request/Response) assert_equals: expected "" but got "text/html(;doesnot=matter"
+FAIL {/} (Blob/File) assert_equals: Blob expected "" but got "{/}"
+FAIL {/} (Request/Response) assert_equals: expected "" but got "{/}"
+PASS Ā/Ā (Blob/File)
+PASS Ā/Ā (Request/Response)
+PASS \0/x (Blob/File)
+PASS \0/x (Request/Response)
+PASS x/\0 (Blob/File)
+PASS x/\0 (Request/Response)
+FAIL x/x;\0=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+PASS x/x;\0=x;bonus=x (Request/Response)
+FAIL x/x;x=\0;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+PASS x/x;x=\0;bonus=x (Request/Response)
+FAIL x/x;x="\0";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+PASS x/x;x="\0";bonus=x (Request/Response)
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS 	/x (Blob/File)
+FAIL 	/x (Request/Response) assert_equals: expected "" but got "/x"
+PASS x/	 (Blob/File)
+FAIL x/	 (Request/Response) assert_equals: expected "" but got "x/"
+FAIL x/x;	=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;	=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS 
+/x (Blob/File)
+FAIL 
+/x (Request/Response) assert_throws: function "() => new Request("about:blank", { headers: [["Content-Type", val.input]] })" did not throw
+PASS x/
+ (Blob/File)
+FAIL x/
+ (Request/Response) assert_throws: function "() => new Request("about:blank", { headers: [["Content-Type", val.input]] })" did not throw
+FAIL x/x;
+=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+PASS x/x;
+=x;bonus=x (Request/Response)
+FAIL x/x;x=
+;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+PASS x/x;x=
+;bonus=x (Request/Response)
+FAIL x/x;x="
+";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+PASS x/x;x="
+";bonus=x (Request/Response)
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS \r/x (Blob/File)
+FAIL \r/x (Request/Response) assert_throws: function "() => new Request("about:blank", { headers: [["Content-Type", val.input]] })" did not throw
+PASS x/\r (Blob/File)
+FAIL x/\r (Request/Response) assert_throws: function "() => new Request("about:blank", { headers: [["Content-Type", val.input]] })" did not throw
+FAIL x/x;\r=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+PASS x/x;\r=x;bonus=x (Request/Response)
+FAIL x/x;x=\r;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+PASS x/x;x=\r;bonus=x (Request/Response)
+FAIL x/x;x="\r";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+PASS x/x;x="\r";bonus=x (Request/Response)
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL  /x (Blob/File) assert_equals: Blob expected "" but got " /x"
+FAIL  /x (Request/Response) assert_equals: expected "" but got "/x"
+FAIL x/  (Blob/File) assert_equals: Blob expected "" but got "x/ "
+FAIL x/  (Request/Response) assert_equals: expected "" but got "x/"
+FAIL x/x; =x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got "x/x; =x;bonus=x"
+FAIL x/x; =x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got "x/x; =x;bonus=x"
+FAIL "/x (Blob/File) assert_equals: Blob expected "" but got "\"/x"
+FAIL "/x (Request/Response) assert_equals: expected "" but got "\"/x"
+FAIL x/" (Blob/File) assert_equals: Blob expected "" but got "x/\""
+FAIL x/" (Request/Response) assert_equals: expected "" but got "x/\""
+FAIL x/x;"=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got "x/x;\"=x;bonus=x"
+FAIL x/x;"=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got "x/x;\"=x;bonus=x"
+FAIL (/x (Blob/File) assert_equals: Blob expected "" but got "(/x"
+FAIL (/x (Request/Response) assert_equals: expected "" but got "(/x"
+FAIL x/( (Blob/File) assert_equals: Blob expected "" but got "x/("
+FAIL x/( (Request/Response) assert_equals: expected "" but got "x/("
+FAIL x/x;(=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got "x/x;(=x;bonus=x"
+FAIL x/x;(=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got "x/x;(=x;bonus=x"
+FAIL x/x;x=(;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"(\";bonus=x" but got "x/x;x=(;bonus=x"
+FAIL x/x;x=(;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"(\";bonus=x" but got "x/x;x=(;bonus=x"
+PASS x/x;x="(";bonus=x (Blob/File)
+PASS x/x;x="(";bonus=x (Request/Response)
+FAIL )/x (Blob/File) assert_equals: Blob expected "" but got ")/x"
+FAIL )/x (Request/Response) assert_equals: expected "" but got ")/x"
+FAIL x/) (Blob/File) assert_equals: Blob expected "" but got "x/)"
+FAIL x/) (Request/Response) assert_equals: expected "" but got "x/)"
+FAIL x/x;)=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got "x/x;)=x;bonus=x"
+FAIL x/x;)=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got "x/x;)=x;bonus=x"
+FAIL x/x;x=);bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\")\";bonus=x" but got "x/x;x=);bonus=x"
+FAIL x/x;x=);bonus=x (Request/Response) assert_equals: expected "x/x;x=\")\";bonus=x" but got "x/x;x=);bonus=x"
+PASS x/x;x=")";bonus=x (Blob/File)
+PASS x/x;x=")";bonus=x (Request/Response)
+FAIL ,/x (Blob/File) assert_equals: Blob expected "" but got ",/x"
+FAIL ,/x (Request/Response) assert_equals: expected "" but got ",/x"
+FAIL x/, (Blob/File) assert_equals: Blob expected "" but got "x/,"
+FAIL x/, (Request/Response) assert_equals: expected "" but got "x/,"
+FAIL x/x;,=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got "x/x;,=x;bonus=x"
+FAIL x/x;,=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got "x/x;,=x;bonus=x"
+FAIL x/x;x=,;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\",\";bonus=x" but got "x/x;x=,;bonus=x"
+FAIL x/x;x=,;bonus=x (Request/Response) assert_equals: expected "x/x;x=\",\";bonus=x" but got "x/x;x=,;bonus=x"
+PASS x/x;x=",";bonus=x (Blob/File)
+PASS x/x;x=",";bonus=x (Request/Response)
+FAIL x/x;/=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got "x/x;/=x;bonus=x"
+FAIL x/x;/=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got "x/x;/=x;bonus=x"
+FAIL x/x;x=/;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"/\";bonus=x" but got "x/x;x=/;bonus=x"
+FAIL x/x;x=/;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"/\";bonus=x" but got "x/x;x=/;bonus=x"
+PASS x/x;x="/";bonus=x (Blob/File)
+PASS x/x;x="/";bonus=x (Request/Response)
+FAIL :/x (Blob/File) assert_equals: Blob expected "" but got ":/x"
+FAIL :/x (Request/Response) assert_equals: expected "" but got ":/x"
+FAIL x/: (Blob/File) assert_equals: Blob expected "" but got "x/:"
+FAIL x/: (Request/Response) assert_equals: expected "" but got "x/:"
+FAIL x/x;:=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got "x/x;:=x;bonus=x"
+FAIL x/x;:=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got "x/x;:=x;bonus=x"
+FAIL x/x;x=:;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\":\";bonus=x" but got "x/x;x=:;bonus=x"
+FAIL x/x;x=:;bonus=x (Request/Response) assert_equals: expected "x/x;x=\":\";bonus=x" but got "x/x;x=:;bonus=x"
+PASS x/x;x=":";bonus=x (Blob/File)
+PASS x/x;x=":";bonus=x (Request/Response)
+FAIL ;/x (Blob/File) assert_equals: Blob expected "" but got ";/x"
+FAIL ;/x (Request/Response) assert_equals: expected "" but got ";/x"
+FAIL x/; (Blob/File) assert_equals: Blob expected "" but got "x/;"
+FAIL x/; (Request/Response) assert_equals: expected "" but got "x/;"
+FAIL </x (Blob/File) assert_equals: Blob expected "" but got "</x"
+FAIL </x (Request/Response) assert_equals: expected "" but got "</x"
+FAIL x/< (Blob/File) assert_equals: Blob expected "" but got "x/<"
+FAIL x/< (Request/Response) assert_equals: expected "" but got "x/<"
+FAIL x/x;<=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got "x/x;<=x;bonus=x"
+FAIL x/x;<=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got "x/x;<=x;bonus=x"
+FAIL x/x;x=<;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"<\";bonus=x" but got "x/x;x=<;bonus=x"
+FAIL x/x;x=<;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"<\";bonus=x" but got "x/x;x=<;bonus=x"
+PASS x/x;x="<";bonus=x (Blob/File)
+PASS x/x;x="<";bonus=x (Request/Response)
+FAIL =/x (Blob/File) assert_equals: Blob expected "" but got "=/x"
+FAIL =/x (Request/Response) assert_equals: expected "" but got "=/x"
+FAIL x/= (Blob/File) assert_equals: Blob expected "" but got "x/="
+FAIL x/= (Request/Response) assert_equals: expected "" but got "x/="
+FAIL x/x;x==;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"=\";bonus=x" but got "x/x;x==;bonus=x"
+FAIL x/x;x==;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"=\";bonus=x" but got "x/x;x==;bonus=x"
+PASS x/x;x="=";bonus=x (Blob/File)
+PASS x/x;x="=";bonus=x (Request/Response)
+FAIL >/x (Blob/File) assert_equals: Blob expected "" but got ">/x"
+FAIL >/x (Request/Response) assert_equals: expected "" but got ">/x"
+FAIL x/> (Blob/File) assert_equals: Blob expected "" but got "x/>"
+FAIL x/> (Request/Response) assert_equals: expected "" but got "x/>"
+FAIL x/x;>=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got "x/x;>=x;bonus=x"
+FAIL x/x;>=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got "x/x;>=x;bonus=x"
+FAIL x/x;x=>;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\">\";bonus=x" but got "x/x;x=>;bonus=x"
+FAIL x/x;x=>;bonus=x (Request/Response) assert_equals: expected "x/x;x=\">\";bonus=x" but got "x/x;x=>;bonus=x"
+PASS x/x;x=">";bonus=x (Blob/File)
+PASS x/x;x=">";bonus=x (Request/Response)
+FAIL ?/x (Blob/File) assert_equals: Blob expected "" but got "?/x"
+FAIL ?/x (Request/Response) assert_equals: expected "" but got "?/x"
+FAIL x/? (Blob/File) assert_equals: Blob expected "" but got "x/?"
+FAIL x/? (Request/Response) assert_equals: expected "" but got "x/?"
+FAIL x/x;?=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got "x/x;?=x;bonus=x"
+FAIL x/x;?=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got "x/x;?=x;bonus=x"
+FAIL x/x;x=?;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"?\";bonus=x" but got "x/x;x=?;bonus=x"
+FAIL x/x;x=?;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"?\";bonus=x" but got "x/x;x=?;bonus=x"
+PASS x/x;x="?";bonus=x (Blob/File)
+PASS x/x;x="?";bonus=x (Request/Response)
+FAIL @/x (Blob/File) assert_equals: Blob expected "" but got "@/x"
+FAIL @/x (Request/Response) assert_equals: expected "" but got "@/x"
+FAIL x/@ (Blob/File) assert_equals: Blob expected "" but got "x/@"
+FAIL x/@ (Request/Response) assert_equals: expected "" but got "x/@"
+FAIL x/x;@=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got "x/x;@=x;bonus=x"
+FAIL x/x;@=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got "x/x;@=x;bonus=x"
+FAIL x/x;x=@;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"@\";bonus=x" but got "x/x;x=@;bonus=x"
+FAIL x/x;x=@;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"@\";bonus=x" but got "x/x;x=@;bonus=x"
+PASS x/x;x="@";bonus=x (Blob/File)
+PASS x/x;x="@";bonus=x (Request/Response)
+FAIL [/x (Blob/File) assert_equals: Blob expected "" but got "[/x"
+FAIL [/x (Request/Response) assert_equals: expected "" but got "[/x"
+FAIL x/[ (Blob/File) assert_equals: Blob expected "" but got "x/["
+FAIL x/[ (Request/Response) assert_equals: expected "" but got "x/["
+FAIL x/x;[=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got "x/x;[=x;bonus=x"
+FAIL x/x;[=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got "x/x;[=x;bonus=x"
+FAIL x/x;x=[;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"[\";bonus=x" but got "x/x;x=[;bonus=x"
+FAIL x/x;x=[;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"[\";bonus=x" but got "x/x;x=[;bonus=x"
+PASS x/x;x="[";bonus=x (Blob/File)
+PASS x/x;x="[";bonus=x (Request/Response)
+FAIL \/x (Blob/File) assert_equals: Blob expected "" but got "\\/x"
+FAIL \/x (Request/Response) assert_equals: expected "" but got "\\/x"
+FAIL x/\ (Blob/File) assert_equals: Blob expected "" but got "x/\\"
+FAIL x/\ (Request/Response) assert_equals: expected "" but got "x/\\"
+FAIL x/x;\=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got "x/x;\\=x;bonus=x"
+FAIL x/x;\=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got "x/x;\\=x;bonus=x"
+FAIL ]/x (Blob/File) assert_equals: Blob expected "" but got "]/x"
+FAIL ]/x (Request/Response) assert_equals: expected "" but got "]/x"
+FAIL x/] (Blob/File) assert_equals: Blob expected "" but got "x/]"
+FAIL x/] (Request/Response) assert_equals: expected "" but got "x/]"
+FAIL x/x;]=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got "x/x;]=x;bonus=x"
+FAIL x/x;]=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got "x/x;]=x;bonus=x"
+FAIL x/x;x=];bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"]\";bonus=x" but got "x/x;x=];bonus=x"
+FAIL x/x;x=];bonus=x (Request/Response) assert_equals: expected "x/x;x=\"]\";bonus=x" but got "x/x;x=];bonus=x"
+PASS x/x;x="]";bonus=x (Blob/File)
+PASS x/x;x="]";bonus=x (Request/Response)
+FAIL {/x (Blob/File) assert_equals: Blob expected "" but got "{/x"
+FAIL {/x (Request/Response) assert_equals: expected "" but got "{/x"
+FAIL x/{ (Blob/File) assert_equals: Blob expected "" but got "x/{"
+FAIL x/{ (Request/Response) assert_equals: expected "" but got "x/{"
+FAIL x/x;{=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got "x/x;{=x;bonus=x"
+FAIL x/x;{=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got "x/x;{=x;bonus=x"
+FAIL x/x;x={;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"{\";bonus=x" but got "x/x;x={;bonus=x"
+FAIL x/x;x={;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"{\";bonus=x" but got "x/x;x={;bonus=x"
+PASS x/x;x="{";bonus=x (Blob/File)
+PASS x/x;x="{";bonus=x (Request/Response)
+FAIL }/x (Blob/File) assert_equals: Blob expected "" but got "}/x"
+FAIL }/x (Request/Response) assert_equals: expected "" but got "}/x"
+FAIL x/} (Blob/File) assert_equals: Blob expected "" but got "x/}"
+FAIL x/} (Request/Response) assert_equals: expected "" but got "x/}"
+FAIL x/x;}=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got "x/x;}=x;bonus=x"
+FAIL x/x;}=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got "x/x;}=x;bonus=x"
+FAIL x/x;x=};bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"}\";bonus=x" but got "x/x;x=};bonus=x"
+FAIL x/x;x=};bonus=x (Request/Response) assert_equals: expected "x/x;x=\"}\";bonus=x" but got "x/x;x=};bonus=x"
+PASS x/x;x="}";bonus=x (Blob/File)
+PASS x/x;x="}";bonus=x (Request/Response)
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS €/x (Blob/File)
+PASS €/x (Request/Response)
+PASS x/€ (Blob/File)
+PASS x/€ (Request/Response)
+FAIL x/x;€=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;€=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=€;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"€\";bonus=x" but got ""
+FAIL x/x;x=€;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"€\";bonus=x" but got ""
+FAIL x/x;x="€";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"€\";bonus=x" but got ""
+FAIL x/x;x="€";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"€\";bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"\";bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"\";bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"\";bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"\";bonus=x" but got ""
+PASS ‚/x (Blob/File)
+PASS ‚/x (Request/Response)
+PASS x/‚ (Blob/File)
+PASS x/‚ (Request/Response)
+FAIL x/x;‚=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;‚=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=‚;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"‚\";bonus=x" but got ""
+FAIL x/x;x=‚;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"‚\";bonus=x" but got ""
+FAIL x/x;x="‚";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"‚\";bonus=x" but got ""
+FAIL x/x;x="‚";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"‚\";bonus=x" but got ""
+PASS ƒ/x (Blob/File)
+PASS ƒ/x (Request/Response)
+PASS x/ƒ (Blob/File)
+PASS x/ƒ (Request/Response)
+FAIL x/x;ƒ=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;ƒ=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=ƒ;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ƒ\";bonus=x" but got ""
+FAIL x/x;x=ƒ;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ƒ\";bonus=x" but got ""
+FAIL x/x;x="ƒ";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ƒ\";bonus=x" but got ""
+FAIL x/x;x="ƒ";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ƒ\";bonus=x" but got ""
+PASS „/x (Blob/File)
+PASS „/x (Request/Response)
+PASS x/„ (Blob/File)
+PASS x/„ (Request/Response)
+FAIL x/x;„=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;„=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=„;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"„\";bonus=x" but got ""
+FAIL x/x;x=„;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"„\";bonus=x" but got ""
+FAIL x/x;x="„";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"„\";bonus=x" but got ""
+FAIL x/x;x="„";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"„\";bonus=x" but got ""
+PASS …/x (Blob/File)
+PASS …/x (Request/Response)
+PASS x/… (Blob/File)
+PASS x/… (Request/Response)
+FAIL x/x;…=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;…=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=…;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"…\";bonus=x" but got ""
+FAIL x/x;x=…;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"…\";bonus=x" but got ""
+FAIL x/x;x="…";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"…\";bonus=x" but got ""
+FAIL x/x;x="…";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"…\";bonus=x" but got ""
+PASS †/x (Blob/File)
+PASS †/x (Request/Response)
+PASS x/† (Blob/File)
+PASS x/† (Request/Response)
+FAIL x/x;†=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;†=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=†;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"†\";bonus=x" but got ""
+FAIL x/x;x=†;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"†\";bonus=x" but got ""
+FAIL x/x;x="†";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"†\";bonus=x" but got ""
+FAIL x/x;x="†";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"†\";bonus=x" but got ""
+PASS ‡/x (Blob/File)
+PASS ‡/x (Request/Response)
+PASS x/‡ (Blob/File)
+PASS x/‡ (Request/Response)
+FAIL x/x;‡=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;‡=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=‡;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"‡\";bonus=x" but got ""
+FAIL x/x;x=‡;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"‡\";bonus=x" but got ""
+FAIL x/x;x="‡";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"‡\";bonus=x" but got ""
+FAIL x/x;x="‡";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"‡\";bonus=x" but got ""
+PASS ˆ/x (Blob/File)
+PASS ˆ/x (Request/Response)
+PASS x/ˆ (Blob/File)
+PASS x/ˆ (Request/Response)
+FAIL x/x;ˆ=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;ˆ=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=ˆ;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ˆ\";bonus=x" but got ""
+FAIL x/x;x=ˆ;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ˆ\";bonus=x" but got ""
+FAIL x/x;x="ˆ";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ˆ\";bonus=x" but got ""
+FAIL x/x;x="ˆ";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ˆ\";bonus=x" but got ""
+PASS ‰/x (Blob/File)
+PASS ‰/x (Request/Response)
+PASS x/‰ (Blob/File)
+PASS x/‰ (Request/Response)
+FAIL x/x;‰=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;‰=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=‰;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"‰\";bonus=x" but got ""
+FAIL x/x;x=‰;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"‰\";bonus=x" but got ""
+FAIL x/x;x="‰";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"‰\";bonus=x" but got ""
+FAIL x/x;x="‰";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"‰\";bonus=x" but got ""
+PASS Š/x (Blob/File)
+PASS Š/x (Request/Response)
+PASS x/Š (Blob/File)
+PASS x/Š (Request/Response)
+FAIL x/x;Š=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Š=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Š;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Š\";bonus=x" but got ""
+FAIL x/x;x=Š;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Š\";bonus=x" but got ""
+FAIL x/x;x="Š";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Š\";bonus=x" but got ""
+FAIL x/x;x="Š";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Š\";bonus=x" but got ""
+PASS ‹/x (Blob/File)
+PASS ‹/x (Request/Response)
+PASS x/‹ (Blob/File)
+PASS x/‹ (Request/Response)
+FAIL x/x;‹=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;‹=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=‹;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"‹\";bonus=x" but got ""
+FAIL x/x;x=‹;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"‹\";bonus=x" but got ""
+FAIL x/x;x="‹";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"‹\";bonus=x" but got ""
+FAIL x/x;x="‹";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"‹\";bonus=x" but got ""
+PASS Œ/x (Blob/File)
+PASS Œ/x (Request/Response)
+PASS x/Œ (Blob/File)
+PASS x/Œ (Request/Response)
+FAIL x/x;Œ=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Œ=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Œ;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Œ\";bonus=x" but got ""
+FAIL x/x;x=Œ;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Œ\";bonus=x" but got ""
+FAIL x/x;x="Œ";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Œ\";bonus=x" but got ""
+FAIL x/x;x="Œ";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Œ\";bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"\";bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"\";bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"\";bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"\";bonus=x" but got ""
+PASS Ž/x (Blob/File)
+PASS Ž/x (Request/Response)
+PASS x/Ž (Blob/File)
+PASS x/Ž (Request/Response)
+FAIL x/x;Ž=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Ž=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Ž;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ž\";bonus=x" but got ""
+FAIL x/x;x=Ž;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ž\";bonus=x" but got ""
+FAIL x/x;x="Ž";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ž\";bonus=x" but got ""
+FAIL x/x;x="Ž";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ž\";bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"\";bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"\";bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"\";bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"\";bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"\";bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"\";bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"\";bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"\";bonus=x" but got ""
+PASS ‘/x (Blob/File)
+PASS ‘/x (Request/Response)
+PASS x/‘ (Blob/File)
+PASS x/‘ (Request/Response)
+FAIL x/x;‘=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;‘=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=‘;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"‘\";bonus=x" but got ""
+FAIL x/x;x=‘;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"‘\";bonus=x" but got ""
+FAIL x/x;x="‘";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"‘\";bonus=x" but got ""
+FAIL x/x;x="‘";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"‘\";bonus=x" but got ""
+PASS ’/x (Blob/File)
+PASS ’/x (Request/Response)
+PASS x/’ (Blob/File)
+PASS x/’ (Request/Response)
+FAIL x/x;’=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;’=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=’;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"’\";bonus=x" but got ""
+FAIL x/x;x=’;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"’\";bonus=x" but got ""
+FAIL x/x;x="’";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"’\";bonus=x" but got ""
+FAIL x/x;x="’";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"’\";bonus=x" but got ""
+PASS “/x (Blob/File)
+PASS “/x (Request/Response)
+PASS x/“ (Blob/File)
+PASS x/“ (Request/Response)
+FAIL x/x;“=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;“=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=“;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"“\";bonus=x" but got ""
+FAIL x/x;x=“;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"“\";bonus=x" but got ""
+FAIL x/x;x="“";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"“\";bonus=x" but got ""
+FAIL x/x;x="“";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"“\";bonus=x" but got ""
+PASS ”/x (Blob/File)
+PASS ”/x (Request/Response)
+PASS x/” (Blob/File)
+PASS x/” (Request/Response)
+FAIL x/x;”=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;”=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=”;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"”\";bonus=x" but got ""
+FAIL x/x;x=”;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"”\";bonus=x" but got ""
+FAIL x/x;x="”";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"”\";bonus=x" but got ""
+FAIL x/x;x="”";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"”\";bonus=x" but got ""
+PASS •/x (Blob/File)
+PASS •/x (Request/Response)
+PASS x/• (Blob/File)
+PASS x/• (Request/Response)
+FAIL x/x;•=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;•=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=•;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"•\";bonus=x" but got ""
+FAIL x/x;x=•;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"•\";bonus=x" but got ""
+FAIL x/x;x="•";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"•\";bonus=x" but got ""
+FAIL x/x;x="•";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"•\";bonus=x" but got ""
+PASS –/x (Blob/File)
+PASS –/x (Request/Response)
+PASS x/– (Blob/File)
+PASS x/– (Request/Response)
+FAIL x/x;–=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;–=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=–;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"–\";bonus=x" but got ""
+FAIL x/x;x=–;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"–\";bonus=x" but got ""
+FAIL x/x;x="–";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"–\";bonus=x" but got ""
+FAIL x/x;x="–";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"–\";bonus=x" but got ""
+PASS —/x (Blob/File)
+PASS —/x (Request/Response)
+PASS x/— (Blob/File)
+PASS x/— (Request/Response)
+FAIL x/x;—=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;—=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=—;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"—\";bonus=x" but got ""
+FAIL x/x;x=—;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"—\";bonus=x" but got ""
+FAIL x/x;x="—";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"—\";bonus=x" but got ""
+FAIL x/x;x="—";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"—\";bonus=x" but got ""
+PASS ˜/x (Blob/File)
+PASS ˜/x (Request/Response)
+PASS x/˜ (Blob/File)
+PASS x/˜ (Request/Response)
+FAIL x/x;˜=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;˜=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=˜;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"˜\";bonus=x" but got ""
+FAIL x/x;x=˜;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"˜\";bonus=x" but got ""
+FAIL x/x;x="˜";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"˜\";bonus=x" but got ""
+FAIL x/x;x="˜";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"˜\";bonus=x" but got ""
+PASS ™/x (Blob/File)
+PASS ™/x (Request/Response)
+PASS x/™ (Blob/File)
+PASS x/™ (Request/Response)
+FAIL x/x;™=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;™=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=™;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"™\";bonus=x" but got ""
+FAIL x/x;x=™;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"™\";bonus=x" but got ""
+FAIL x/x;x="™";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"™\";bonus=x" but got ""
+FAIL x/x;x="™";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"™\";bonus=x" but got ""
+PASS š/x (Blob/File)
+PASS š/x (Request/Response)
+PASS x/š (Blob/File)
+PASS x/š (Request/Response)
+FAIL x/x;š=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;š=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=š;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"š\";bonus=x" but got ""
+FAIL x/x;x=š;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"š\";bonus=x" but got ""
+FAIL x/x;x="š";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"š\";bonus=x" but got ""
+FAIL x/x;x="š";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"š\";bonus=x" but got ""
+PASS ›/x (Blob/File)
+PASS ›/x (Request/Response)
+PASS x/› (Blob/File)
+PASS x/› (Request/Response)
+FAIL x/x;›=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;›=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=›;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"›\";bonus=x" but got ""
+FAIL x/x;x=›;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"›\";bonus=x" but got ""
+FAIL x/x;x="›";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"›\";bonus=x" but got ""
+FAIL x/x;x="›";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"›\";bonus=x" but got ""
+PASS œ/x (Blob/File)
+PASS œ/x (Request/Response)
+PASS x/œ (Blob/File)
+PASS x/œ (Request/Response)
+FAIL x/x;œ=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;œ=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=œ;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"œ\";bonus=x" but got ""
+FAIL x/x;x=œ;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"œ\";bonus=x" but got ""
+FAIL x/x;x="œ";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"œ\";bonus=x" but got ""
+FAIL x/x;x="œ";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"œ\";bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"\";bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"\";bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"\";bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"\";bonus=x" but got ""
+PASS ž/x (Blob/File)
+PASS ž/x (Request/Response)
+PASS x/ž (Blob/File)
+PASS x/ž (Request/Response)
+FAIL x/x;ž=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;ž=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=ž;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ž\";bonus=x" but got ""
+FAIL x/x;x=ž;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ž\";bonus=x" but got ""
+FAIL x/x;x="ž";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ž\";bonus=x" but got ""
+FAIL x/x;x="ž";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ž\";bonus=x" but got ""
+PASS Ÿ/x (Blob/File)
+PASS Ÿ/x (Request/Response)
+PASS x/Ÿ (Blob/File)
+PASS x/Ÿ (Request/Response)
+FAIL x/x;Ÿ=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Ÿ=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Ÿ;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ÿ\";bonus=x" but got ""
+FAIL x/x;x=Ÿ;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ÿ\";bonus=x" but got ""
+FAIL x/x;x="Ÿ";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ÿ\";bonus=x" but got ""
+FAIL x/x;x="Ÿ";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ÿ\";bonus=x" but got ""
+PASS  /x (Blob/File)
+PASS  /x (Request/Response)
+PASS x/  (Blob/File)
+PASS x/  (Request/Response)
+FAIL x/x; =x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x; =x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x= ;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\" \";bonus=x" but got ""
+FAIL x/x;x= ;bonus=x (Request/Response) assert_equals: expected "x/x;x=\" \";bonus=x" but got ""
+FAIL x/x;x=" ";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\" \";bonus=x" but got ""
+FAIL x/x;x=" ";bonus=x (Request/Response) assert_equals: expected "x/x;x=\" \";bonus=x" but got ""
+PASS ¡/x (Blob/File)
+PASS ¡/x (Request/Response)
+PASS x/¡ (Blob/File)
+PASS x/¡ (Request/Response)
+FAIL x/x;¡=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;¡=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=¡;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¡\";bonus=x" but got ""
+FAIL x/x;x=¡;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¡\";bonus=x" but got ""
+FAIL x/x;x="¡";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¡\";bonus=x" but got ""
+FAIL x/x;x="¡";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¡\";bonus=x" but got ""
+PASS ¢/x (Blob/File)
+PASS ¢/x (Request/Response)
+PASS x/¢ (Blob/File)
+PASS x/¢ (Request/Response)
+FAIL x/x;¢=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;¢=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=¢;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¢\";bonus=x" but got ""
+FAIL x/x;x=¢;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¢\";bonus=x" but got ""
+FAIL x/x;x="¢";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¢\";bonus=x" but got ""
+FAIL x/x;x="¢";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¢\";bonus=x" but got ""
+PASS £/x (Blob/File)
+PASS £/x (Request/Response)
+PASS x/£ (Blob/File)
+PASS x/£ (Request/Response)
+FAIL x/x;£=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;£=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=£;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"£\";bonus=x" but got ""
+FAIL x/x;x=£;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"£\";bonus=x" but got ""
+FAIL x/x;x="£";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"£\";bonus=x" but got ""
+FAIL x/x;x="£";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"£\";bonus=x" but got ""
+PASS ¤/x (Blob/File)
+PASS ¤/x (Request/Response)
+PASS x/¤ (Blob/File)
+PASS x/¤ (Request/Response)
+FAIL x/x;¤=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;¤=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=¤;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¤\";bonus=x" but got ""
+FAIL x/x;x=¤;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¤\";bonus=x" but got ""
+FAIL x/x;x="¤";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¤\";bonus=x" but got ""
+FAIL x/x;x="¤";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¤\";bonus=x" but got ""
+PASS ¥/x (Blob/File)
+PASS ¥/x (Request/Response)
+PASS x/¥ (Blob/File)
+PASS x/¥ (Request/Response)
+FAIL x/x;¥=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;¥=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=¥;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¥\";bonus=x" but got ""
+FAIL x/x;x=¥;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¥\";bonus=x" but got ""
+FAIL x/x;x="¥";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¥\";bonus=x" but got ""
+FAIL x/x;x="¥";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¥\";bonus=x" but got ""
+PASS ¦/x (Blob/File)
+PASS ¦/x (Request/Response)
+PASS x/¦ (Blob/File)
+PASS x/¦ (Request/Response)
+FAIL x/x;¦=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;¦=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=¦;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¦\";bonus=x" but got ""
+FAIL x/x;x=¦;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¦\";bonus=x" but got ""
+FAIL x/x;x="¦";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¦\";bonus=x" but got ""
+FAIL x/x;x="¦";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¦\";bonus=x" but got ""
+PASS §/x (Blob/File)
+PASS §/x (Request/Response)
+PASS x/§ (Blob/File)
+PASS x/§ (Request/Response)
+FAIL x/x;§=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;§=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=§;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"§\";bonus=x" but got ""
+FAIL x/x;x=§;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"§\";bonus=x" but got ""
+FAIL x/x;x="§";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"§\";bonus=x" but got ""
+FAIL x/x;x="§";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"§\";bonus=x" but got ""
+PASS ¨/x (Blob/File)
+PASS ¨/x (Request/Response)
+PASS x/¨ (Blob/File)
+PASS x/¨ (Request/Response)
+FAIL x/x;¨=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;¨=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=¨;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¨\";bonus=x" but got ""
+FAIL x/x;x=¨;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¨\";bonus=x" but got ""
+FAIL x/x;x="¨";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¨\";bonus=x" but got ""
+FAIL x/x;x="¨";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¨\";bonus=x" but got ""
+PASS ©/x (Blob/File)
+PASS ©/x (Request/Response)
+PASS x/© (Blob/File)
+PASS x/© (Request/Response)
+FAIL x/x;©=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;©=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=©;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"©\";bonus=x" but got ""
+FAIL x/x;x=©;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"©\";bonus=x" but got ""
+FAIL x/x;x="©";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"©\";bonus=x" but got ""
+FAIL x/x;x="©";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"©\";bonus=x" but got ""
+PASS ª/x (Blob/File)
+PASS ª/x (Request/Response)
+PASS x/ª (Blob/File)
+PASS x/ª (Request/Response)
+FAIL x/x;ª=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;ª=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=ª;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ª\";bonus=x" but got ""
+FAIL x/x;x=ª;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ª\";bonus=x" but got ""
+FAIL x/x;x="ª";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ª\";bonus=x" but got ""
+FAIL x/x;x="ª";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ª\";bonus=x" but got ""
+PASS «/x (Blob/File)
+PASS «/x (Request/Response)
+PASS x/« (Blob/File)
+PASS x/« (Request/Response)
+FAIL x/x;«=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;«=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=«;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"«\";bonus=x" but got ""
+FAIL x/x;x=«;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"«\";bonus=x" but got ""
+FAIL x/x;x="«";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"«\";bonus=x" but got ""
+FAIL x/x;x="«";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"«\";bonus=x" but got ""
+PASS ¬/x (Blob/File)
+PASS ¬/x (Request/Response)
+PASS x/¬ (Blob/File)
+PASS x/¬ (Request/Response)
+FAIL x/x;¬=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;¬=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=¬;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¬\";bonus=x" but got ""
+FAIL x/x;x=¬;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¬\";bonus=x" but got ""
+FAIL x/x;x="¬";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¬\";bonus=x" but got ""
+FAIL x/x;x="¬";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¬\";bonus=x" but got ""
+PASS ­/x (Blob/File)
+PASS ­/x (Request/Response)
+PASS x/­ (Blob/File)
+PASS x/­ (Request/Response)
+FAIL x/x;­=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;­=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=­;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"­\";bonus=x" but got ""
+FAIL x/x;x=­;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"­\";bonus=x" but got ""
+FAIL x/x;x="­";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"­\";bonus=x" but got ""
+FAIL x/x;x="­";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"­\";bonus=x" but got ""
+PASS ®/x (Blob/File)
+PASS ®/x (Request/Response)
+PASS x/® (Blob/File)
+PASS x/® (Request/Response)
+FAIL x/x;®=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;®=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=®;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"®\";bonus=x" but got ""
+FAIL x/x;x=®;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"®\";bonus=x" but got ""
+FAIL x/x;x="®";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"®\";bonus=x" but got ""
+FAIL x/x;x="®";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"®\";bonus=x" but got ""
+PASS ¯/x (Blob/File)
+PASS ¯/x (Request/Response)
+PASS x/¯ (Blob/File)
+PASS x/¯ (Request/Response)
+FAIL x/x;¯=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;¯=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=¯;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¯\";bonus=x" but got ""
+FAIL x/x;x=¯;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¯\";bonus=x" but got ""
+FAIL x/x;x="¯";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¯\";bonus=x" but got ""
+FAIL x/x;x="¯";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¯\";bonus=x" but got ""
+PASS °/x (Blob/File)
+PASS °/x (Request/Response)
+PASS x/° (Blob/File)
+PASS x/° (Request/Response)
+FAIL x/x;°=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;°=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=°;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"°\";bonus=x" but got ""
+FAIL x/x;x=°;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"°\";bonus=x" but got ""
+FAIL x/x;x="°";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"°\";bonus=x" but got ""
+FAIL x/x;x="°";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"°\";bonus=x" but got ""
+PASS ±/x (Blob/File)
+PASS ±/x (Request/Response)
+PASS x/± (Blob/File)
+PASS x/± (Request/Response)
+FAIL x/x;±=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;±=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=±;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"±\";bonus=x" but got ""
+FAIL x/x;x=±;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"±\";bonus=x" but got ""
+FAIL x/x;x="±";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"±\";bonus=x" but got ""
+FAIL x/x;x="±";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"±\";bonus=x" but got ""
+PASS ²/x (Blob/File)
+PASS ²/x (Request/Response)
+PASS x/² (Blob/File)
+PASS x/² (Request/Response)
+FAIL x/x;²=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;²=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=²;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"²\";bonus=x" but got ""
+FAIL x/x;x=²;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"²\";bonus=x" but got ""
+FAIL x/x;x="²";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"²\";bonus=x" but got ""
+FAIL x/x;x="²";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"²\";bonus=x" but got ""
+PASS ³/x (Blob/File)
+PASS ³/x (Request/Response)
+PASS x/³ (Blob/File)
+PASS x/³ (Request/Response)
+FAIL x/x;³=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;³=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=³;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"³\";bonus=x" but got ""
+FAIL x/x;x=³;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"³\";bonus=x" but got ""
+FAIL x/x;x="³";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"³\";bonus=x" but got ""
+FAIL x/x;x="³";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"³\";bonus=x" but got ""
+PASS ´/x (Blob/File)
+PASS ´/x (Request/Response)
+PASS x/´ (Blob/File)
+PASS x/´ (Request/Response)
+FAIL x/x;´=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;´=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=´;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"´\";bonus=x" but got ""
+FAIL x/x;x=´;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"´\";bonus=x" but got ""
+FAIL x/x;x="´";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"´\";bonus=x" but got ""
+FAIL x/x;x="´";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"´\";bonus=x" but got ""
+PASS µ/x (Blob/File)
+PASS µ/x (Request/Response)
+PASS x/µ (Blob/File)
+PASS x/µ (Request/Response)
+FAIL x/x;µ=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;µ=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=µ;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"µ\";bonus=x" but got ""
+FAIL x/x;x=µ;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"µ\";bonus=x" but got ""
+FAIL x/x;x="µ";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"µ\";bonus=x" but got ""
+FAIL x/x;x="µ";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"µ\";bonus=x" but got ""
+PASS ¶/x (Blob/File)
+PASS ¶/x (Request/Response)
+PASS x/¶ (Blob/File)
+PASS x/¶ (Request/Response)
+FAIL x/x;¶=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;¶=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=¶;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¶\";bonus=x" but got ""
+FAIL x/x;x=¶;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¶\";bonus=x" but got ""
+FAIL x/x;x="¶";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¶\";bonus=x" but got ""
+FAIL x/x;x="¶";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¶\";bonus=x" but got ""
+PASS ·/x (Blob/File)
+PASS ·/x (Request/Response)
+PASS x/· (Blob/File)
+PASS x/· (Request/Response)
+FAIL x/x;·=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;·=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=·;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"·\";bonus=x" but got ""
+FAIL x/x;x=·;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"·\";bonus=x" but got ""
+FAIL x/x;x="·";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"·\";bonus=x" but got ""
+FAIL x/x;x="·";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"·\";bonus=x" but got ""
+PASS ¸/x (Blob/File)
+PASS ¸/x (Request/Response)
+PASS x/¸ (Blob/File)
+PASS x/¸ (Request/Response)
+FAIL x/x;¸=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;¸=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=¸;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¸\";bonus=x" but got ""
+FAIL x/x;x=¸;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¸\";bonus=x" but got ""
+FAIL x/x;x="¸";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¸\";bonus=x" but got ""
+FAIL x/x;x="¸";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¸\";bonus=x" but got ""
+PASS ¹/x (Blob/File)
+PASS ¹/x (Request/Response)
+PASS x/¹ (Blob/File)
+PASS x/¹ (Request/Response)
+FAIL x/x;¹=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;¹=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=¹;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¹\";bonus=x" but got ""
+FAIL x/x;x=¹;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¹\";bonus=x" but got ""
+FAIL x/x;x="¹";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¹\";bonus=x" but got ""
+FAIL x/x;x="¹";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¹\";bonus=x" but got ""
+PASS º/x (Blob/File)
+PASS º/x (Request/Response)
+PASS x/º (Blob/File)
+PASS x/º (Request/Response)
+FAIL x/x;º=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;º=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=º;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"º\";bonus=x" but got ""
+FAIL x/x;x=º;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"º\";bonus=x" but got ""
+FAIL x/x;x="º";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"º\";bonus=x" but got ""
+FAIL x/x;x="º";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"º\";bonus=x" but got ""
+PASS »/x (Blob/File)
+PASS »/x (Request/Response)
+PASS x/» (Blob/File)
+PASS x/» (Request/Response)
+FAIL x/x;»=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;»=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=»;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"»\";bonus=x" but got ""
+FAIL x/x;x=»;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"»\";bonus=x" but got ""
+FAIL x/x;x="»";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"»\";bonus=x" but got ""
+FAIL x/x;x="»";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"»\";bonus=x" but got ""
+PASS ¼/x (Blob/File)
+PASS ¼/x (Request/Response)
+PASS x/¼ (Blob/File)
+PASS x/¼ (Request/Response)
+FAIL x/x;¼=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;¼=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=¼;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¼\";bonus=x" but got ""
+FAIL x/x;x=¼;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¼\";bonus=x" but got ""
+FAIL x/x;x="¼";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¼\";bonus=x" but got ""
+FAIL x/x;x="¼";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¼\";bonus=x" but got ""
+PASS ½/x (Blob/File)
+PASS ½/x (Request/Response)
+PASS x/½ (Blob/File)
+PASS x/½ (Request/Response)
+FAIL x/x;½=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;½=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=½;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"½\";bonus=x" but got ""
+FAIL x/x;x=½;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"½\";bonus=x" but got ""
+FAIL x/x;x="½";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"½\";bonus=x" but got ""
+FAIL x/x;x="½";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"½\";bonus=x" but got ""
+PASS ¾/x (Blob/File)
+PASS ¾/x (Request/Response)
+PASS x/¾ (Blob/File)
+PASS x/¾ (Request/Response)
+FAIL x/x;¾=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;¾=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=¾;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¾\";bonus=x" but got ""
+FAIL x/x;x=¾;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¾\";bonus=x" but got ""
+FAIL x/x;x="¾";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¾\";bonus=x" but got ""
+FAIL x/x;x="¾";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¾\";bonus=x" but got ""
+PASS ¿/x (Blob/File)
+PASS ¿/x (Request/Response)
+PASS x/¿ (Blob/File)
+PASS x/¿ (Request/Response)
+FAIL x/x;¿=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;¿=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=¿;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¿\";bonus=x" but got ""
+FAIL x/x;x=¿;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¿\";bonus=x" but got ""
+FAIL x/x;x="¿";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¿\";bonus=x" but got ""
+FAIL x/x;x="¿";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¿\";bonus=x" but got ""
+PASS À/x (Blob/File)
+PASS À/x (Request/Response)
+PASS x/À (Blob/File)
+PASS x/À (Request/Response)
+FAIL x/x;À=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;À=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=À;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"À\";bonus=x" but got ""
+FAIL x/x;x=À;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"À\";bonus=x" but got ""
+FAIL x/x;x="À";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"À\";bonus=x" but got ""
+FAIL x/x;x="À";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"À\";bonus=x" but got ""
+PASS Á/x (Blob/File)
+PASS Á/x (Request/Response)
+PASS x/Á (Blob/File)
+PASS x/Á (Request/Response)
+FAIL x/x;Á=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Á=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Á;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Á\";bonus=x" but got ""
+FAIL x/x;x=Á;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Á\";bonus=x" but got ""
+FAIL x/x;x="Á";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Á\";bonus=x" but got ""
+FAIL x/x;x="Á";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Á\";bonus=x" but got ""
+PASS Â/x (Blob/File)
+PASS Â/x (Request/Response)
+PASS x/Â (Blob/File)
+PASS x/Â (Request/Response)
+FAIL x/x;Â=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Â=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Â;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Â\";bonus=x" but got ""
+FAIL x/x;x=Â;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Â\";bonus=x" but got ""
+FAIL x/x;x="Â";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Â\";bonus=x" but got ""
+FAIL x/x;x="Â";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Â\";bonus=x" but got ""
+PASS Ã/x (Blob/File)
+PASS Ã/x (Request/Response)
+PASS x/Ã (Blob/File)
+PASS x/Ã (Request/Response)
+FAIL x/x;Ã=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Ã=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Ã;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ã\";bonus=x" but got ""
+FAIL x/x;x=Ã;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ã\";bonus=x" but got ""
+FAIL x/x;x="Ã";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ã\";bonus=x" but got ""
+FAIL x/x;x="Ã";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ã\";bonus=x" but got ""
+PASS Ä/x (Blob/File)
+PASS Ä/x (Request/Response)
+PASS x/Ä (Blob/File)
+PASS x/Ä (Request/Response)
+FAIL x/x;Ä=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Ä=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Ä;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ä\";bonus=x" but got ""
+FAIL x/x;x=Ä;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ä\";bonus=x" but got ""
+FAIL x/x;x="Ä";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ä\";bonus=x" but got ""
+FAIL x/x;x="Ä";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ä\";bonus=x" but got ""
+PASS Å/x (Blob/File)
+PASS Å/x (Request/Response)
+PASS x/Å (Blob/File)
+PASS x/Å (Request/Response)
+FAIL x/x;Å=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Å=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Å;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Å\";bonus=x" but got ""
+FAIL x/x;x=Å;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Å\";bonus=x" but got ""
+FAIL x/x;x="Å";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Å\";bonus=x" but got ""
+FAIL x/x;x="Å";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Å\";bonus=x" but got ""
+PASS Æ/x (Blob/File)
+PASS Æ/x (Request/Response)
+PASS x/Æ (Blob/File)
+PASS x/Æ (Request/Response)
+FAIL x/x;Æ=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Æ=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Æ;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Æ\";bonus=x" but got ""
+FAIL x/x;x=Æ;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Æ\";bonus=x" but got ""
+FAIL x/x;x="Æ";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Æ\";bonus=x" but got ""
+FAIL x/x;x="Æ";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Æ\";bonus=x" but got ""
+PASS Ç/x (Blob/File)
+PASS Ç/x (Request/Response)
+PASS x/Ç (Blob/File)
+PASS x/Ç (Request/Response)
+FAIL x/x;Ç=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Ç=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Ç;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ç\";bonus=x" but got ""
+FAIL x/x;x=Ç;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ç\";bonus=x" but got ""
+FAIL x/x;x="Ç";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ç\";bonus=x" but got ""
+FAIL x/x;x="Ç";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ç\";bonus=x" but got ""
+PASS È/x (Blob/File)
+PASS È/x (Request/Response)
+PASS x/È (Blob/File)
+PASS x/È (Request/Response)
+FAIL x/x;È=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;È=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=È;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"È\";bonus=x" but got ""
+FAIL x/x;x=È;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"È\";bonus=x" but got ""
+FAIL x/x;x="È";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"È\";bonus=x" but got ""
+FAIL x/x;x="È";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"È\";bonus=x" but got ""
+PASS É/x (Blob/File)
+PASS É/x (Request/Response)
+PASS x/É (Blob/File)
+PASS x/É (Request/Response)
+FAIL x/x;É=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;É=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=É;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"É\";bonus=x" but got ""
+FAIL x/x;x=É;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"É\";bonus=x" but got ""
+FAIL x/x;x="É";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"É\";bonus=x" but got ""
+FAIL x/x;x="É";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"É\";bonus=x" but got ""
+PASS Ê/x (Blob/File)
+PASS Ê/x (Request/Response)
+PASS x/Ê (Blob/File)
+PASS x/Ê (Request/Response)
+FAIL x/x;Ê=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Ê=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Ê;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ê\";bonus=x" but got ""
+FAIL x/x;x=Ê;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ê\";bonus=x" but got ""
+FAIL x/x;x="Ê";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ê\";bonus=x" but got ""
+FAIL x/x;x="Ê";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ê\";bonus=x" but got ""
+PASS Ë/x (Blob/File)
+PASS Ë/x (Request/Response)
+PASS x/Ë (Blob/File)
+PASS x/Ë (Request/Response)
+FAIL x/x;Ë=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Ë=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Ë;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ë\";bonus=x" but got ""
+FAIL x/x;x=Ë;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ë\";bonus=x" but got ""
+FAIL x/x;x="Ë";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ë\";bonus=x" but got ""
+FAIL x/x;x="Ë";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ë\";bonus=x" but got ""
+PASS Ì/x (Blob/File)
+PASS Ì/x (Request/Response)
+PASS x/Ì (Blob/File)
+PASS x/Ì (Request/Response)
+FAIL x/x;Ì=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Ì=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Ì;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ì\";bonus=x" but got ""
+FAIL x/x;x=Ì;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ì\";bonus=x" but got ""
+FAIL x/x;x="Ì";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ì\";bonus=x" but got ""
+FAIL x/x;x="Ì";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ì\";bonus=x" but got ""
+PASS Í/x (Blob/File)
+PASS Í/x (Request/Response)
+PASS x/Í (Blob/File)
+PASS x/Í (Request/Response)
+FAIL x/x;Í=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Í=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Í;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Í\";bonus=x" but got ""
+FAIL x/x;x=Í;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Í\";bonus=x" but got ""
+FAIL x/x;x="Í";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Í\";bonus=x" but got ""
+FAIL x/x;x="Í";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Í\";bonus=x" but got ""
+PASS Î/x (Blob/File)
+PASS Î/x (Request/Response)
+PASS x/Î (Blob/File)
+PASS x/Î (Request/Response)
+FAIL x/x;Î=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Î=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Î;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Î\";bonus=x" but got ""
+FAIL x/x;x=Î;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Î\";bonus=x" but got ""
+FAIL x/x;x="Î";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Î\";bonus=x" but got ""
+FAIL x/x;x="Î";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Î\";bonus=x" but got ""
+PASS Ï/x (Blob/File)
+PASS Ï/x (Request/Response)
+PASS x/Ï (Blob/File)
+PASS x/Ï (Request/Response)
+FAIL x/x;Ï=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Ï=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Ï;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ï\";bonus=x" but got ""
+FAIL x/x;x=Ï;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ï\";bonus=x" but got ""
+FAIL x/x;x="Ï";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ï\";bonus=x" but got ""
+FAIL x/x;x="Ï";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ï\";bonus=x" but got ""
+PASS Ð/x (Blob/File)
+PASS Ð/x (Request/Response)
+PASS x/Ð (Blob/File)
+PASS x/Ð (Request/Response)
+FAIL x/x;Ð=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Ð=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Ð;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ð\";bonus=x" but got ""
+FAIL x/x;x=Ð;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ð\";bonus=x" but got ""
+FAIL x/x;x="Ð";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ð\";bonus=x" but got ""
+FAIL x/x;x="Ð";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ð\";bonus=x" but got ""
+PASS Ñ/x (Blob/File)
+PASS Ñ/x (Request/Response)
+PASS x/Ñ (Blob/File)
+PASS x/Ñ (Request/Response)
+FAIL x/x;Ñ=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Ñ=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Ñ;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ñ\";bonus=x" but got ""
+FAIL x/x;x=Ñ;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ñ\";bonus=x" but got ""
+FAIL x/x;x="Ñ";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ñ\";bonus=x" but got ""
+FAIL x/x;x="Ñ";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ñ\";bonus=x" but got ""
+PASS Ò/x (Blob/File)
+PASS Ò/x (Request/Response)
+PASS x/Ò (Blob/File)
+PASS x/Ò (Request/Response)
+FAIL x/x;Ò=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Ò=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Ò;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ò\";bonus=x" but got ""
+FAIL x/x;x=Ò;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ò\";bonus=x" but got ""
+FAIL x/x;x="Ò";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ò\";bonus=x" but got ""
+FAIL x/x;x="Ò";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ò\";bonus=x" but got ""
+PASS Ó/x (Blob/File)
+PASS Ó/x (Request/Response)
+PASS x/Ó (Blob/File)
+PASS x/Ó (Request/Response)
+FAIL x/x;Ó=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Ó=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Ó;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ó\";bonus=x" but got ""
+FAIL x/x;x=Ó;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ó\";bonus=x" but got ""
+FAIL x/x;x="Ó";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ó\";bonus=x" but got ""
+FAIL x/x;x="Ó";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ó\";bonus=x" but got ""
+PASS Ô/x (Blob/File)
+PASS Ô/x (Request/Response)
+PASS x/Ô (Blob/File)
+PASS x/Ô (Request/Response)
+FAIL x/x;Ô=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Ô=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Ô;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ô\";bonus=x" but got ""
+FAIL x/x;x=Ô;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ô\";bonus=x" but got ""
+FAIL x/x;x="Ô";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ô\";bonus=x" but got ""
+FAIL x/x;x="Ô";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ô\";bonus=x" but got ""
+PASS Õ/x (Blob/File)
+PASS Õ/x (Request/Response)
+PASS x/Õ (Blob/File)
+PASS x/Õ (Request/Response)
+FAIL x/x;Õ=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Õ=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Õ;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Õ\";bonus=x" but got ""
+FAIL x/x;x=Õ;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Õ\";bonus=x" but got ""
+FAIL x/x;x="Õ";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Õ\";bonus=x" but got ""
+FAIL x/x;x="Õ";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Õ\";bonus=x" but got ""
+PASS Ö/x (Blob/File)
+PASS Ö/x (Request/Response)
+PASS x/Ö (Blob/File)
+PASS x/Ö (Request/Response)
+FAIL x/x;Ö=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Ö=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Ö;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ö\";bonus=x" but got ""
+FAIL x/x;x=Ö;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ö\";bonus=x" but got ""
+FAIL x/x;x="Ö";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ö\";bonus=x" but got ""
+FAIL x/x;x="Ö";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ö\";bonus=x" but got ""
+PASS ×/x (Blob/File)
+PASS ×/x (Request/Response)
+PASS x/× (Blob/File)
+PASS x/× (Request/Response)
+FAIL x/x;×=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;×=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=×;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"×\";bonus=x" but got ""
+FAIL x/x;x=×;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"×\";bonus=x" but got ""
+FAIL x/x;x="×";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"×\";bonus=x" but got ""
+FAIL x/x;x="×";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"×\";bonus=x" but got ""
+PASS Ø/x (Blob/File)
+PASS Ø/x (Request/Response)
+PASS x/Ø (Blob/File)
+PASS x/Ø (Request/Response)
+FAIL x/x;Ø=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Ø=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Ø;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ø\";bonus=x" but got ""
+FAIL x/x;x=Ø;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ø\";bonus=x" but got ""
+FAIL x/x;x="Ø";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ø\";bonus=x" but got ""
+FAIL x/x;x="Ø";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ø\";bonus=x" but got ""
+PASS Ù/x (Blob/File)
+PASS Ù/x (Request/Response)
+PASS x/Ù (Blob/File)
+PASS x/Ù (Request/Response)
+FAIL x/x;Ù=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Ù=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Ù;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ù\";bonus=x" but got ""
+FAIL x/x;x=Ù;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ù\";bonus=x" but got ""
+FAIL x/x;x="Ù";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ù\";bonus=x" but got ""
+FAIL x/x;x="Ù";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ù\";bonus=x" but got ""
+PASS Ú/x (Blob/File)
+PASS Ú/x (Request/Response)
+PASS x/Ú (Blob/File)
+PASS x/Ú (Request/Response)
+FAIL x/x;Ú=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Ú=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Ú;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ú\";bonus=x" but got ""
+FAIL x/x;x=Ú;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ú\";bonus=x" but got ""
+FAIL x/x;x="Ú";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ú\";bonus=x" but got ""
+FAIL x/x;x="Ú";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ú\";bonus=x" but got ""
+PASS Û/x (Blob/File)
+PASS Û/x (Request/Response)
+PASS x/Û (Blob/File)
+PASS x/Û (Request/Response)
+FAIL x/x;Û=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Û=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Û;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Û\";bonus=x" but got ""
+FAIL x/x;x=Û;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Û\";bonus=x" but got ""
+FAIL x/x;x="Û";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Û\";bonus=x" but got ""
+FAIL x/x;x="Û";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Û\";bonus=x" but got ""
+PASS Ü/x (Blob/File)
+PASS Ü/x (Request/Response)
+PASS x/Ü (Blob/File)
+PASS x/Ü (Request/Response)
+FAIL x/x;Ü=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Ü=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Ü;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ü\";bonus=x" but got ""
+FAIL x/x;x=Ü;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ü\";bonus=x" but got ""
+FAIL x/x;x="Ü";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ü\";bonus=x" but got ""
+FAIL x/x;x="Ü";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ü\";bonus=x" but got ""
+PASS Ý/x (Blob/File)
+PASS Ý/x (Request/Response)
+PASS x/Ý (Blob/File)
+PASS x/Ý (Request/Response)
+FAIL x/x;Ý=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Ý=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Ý;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ý\";bonus=x" but got ""
+FAIL x/x;x=Ý;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ý\";bonus=x" but got ""
+FAIL x/x;x="Ý";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ý\";bonus=x" but got ""
+FAIL x/x;x="Ý";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ý\";bonus=x" but got ""
+PASS Þ/x (Blob/File)
+PASS Þ/x (Request/Response)
+PASS x/Þ (Blob/File)
+PASS x/Þ (Request/Response)
+FAIL x/x;Þ=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Þ=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Þ;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Þ\";bonus=x" but got ""
+FAIL x/x;x=Þ;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Þ\";bonus=x" but got ""
+FAIL x/x;x="Þ";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Þ\";bonus=x" but got ""
+FAIL x/x;x="Þ";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Þ\";bonus=x" but got ""
+PASS ß/x (Blob/File)
+PASS ß/x (Request/Response)
+PASS x/ß (Blob/File)
+PASS x/ß (Request/Response)
+FAIL x/x;ß=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;ß=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=ß;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ß\";bonus=x" but got ""
+FAIL x/x;x=ß;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ß\";bonus=x" but got ""
+FAIL x/x;x="ß";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ß\";bonus=x" but got ""
+FAIL x/x;x="ß";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ß\";bonus=x" but got ""
+PASS à/x (Blob/File)
+PASS à/x (Request/Response)
+PASS x/à (Blob/File)
+PASS x/à (Request/Response)
+FAIL x/x;à=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;à=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=à;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"à\";bonus=x" but got ""
+FAIL x/x;x=à;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"à\";bonus=x" but got ""
+FAIL x/x;x="à";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"à\";bonus=x" but got ""
+FAIL x/x;x="à";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"à\";bonus=x" but got ""
+PASS á/x (Blob/File)
+PASS á/x (Request/Response)
+PASS x/á (Blob/File)
+PASS x/á (Request/Response)
+FAIL x/x;á=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;á=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=á;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"á\";bonus=x" but got ""
+FAIL x/x;x=á;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"á\";bonus=x" but got ""
+FAIL x/x;x="á";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"á\";bonus=x" but got ""
+FAIL x/x;x="á";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"á\";bonus=x" but got ""
+PASS â/x (Blob/File)
+PASS â/x (Request/Response)
+PASS x/â (Blob/File)
+PASS x/â (Request/Response)
+FAIL x/x;â=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;â=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=â;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"â\";bonus=x" but got ""
+FAIL x/x;x=â;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"â\";bonus=x" but got ""
+FAIL x/x;x="â";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"â\";bonus=x" but got ""
+FAIL x/x;x="â";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"â\";bonus=x" but got ""
+PASS ã/x (Blob/File)
+PASS ã/x (Request/Response)
+PASS x/ã (Blob/File)
+PASS x/ã (Request/Response)
+FAIL x/x;ã=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;ã=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=ã;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ã\";bonus=x" but got ""
+FAIL x/x;x=ã;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ã\";bonus=x" but got ""
+FAIL x/x;x="ã";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ã\";bonus=x" but got ""
+FAIL x/x;x="ã";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ã\";bonus=x" but got ""
+PASS ä/x (Blob/File)
+PASS ä/x (Request/Response)
+PASS x/ä (Blob/File)
+PASS x/ä (Request/Response)
+FAIL x/x;ä=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;ä=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=ä;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ä\";bonus=x" but got ""
+FAIL x/x;x=ä;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ä\";bonus=x" but got ""
+FAIL x/x;x="ä";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ä\";bonus=x" but got ""
+FAIL x/x;x="ä";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ä\";bonus=x" but got ""
+PASS å/x (Blob/File)
+PASS å/x (Request/Response)
+PASS x/å (Blob/File)
+PASS x/å (Request/Response)
+FAIL x/x;å=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;å=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=å;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"å\";bonus=x" but got ""
+FAIL x/x;x=å;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"å\";bonus=x" but got ""
+FAIL x/x;x="å";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"å\";bonus=x" but got ""
+FAIL x/x;x="å";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"å\";bonus=x" but got ""
+PASS æ/x (Blob/File)
+PASS æ/x (Request/Response)
+PASS x/æ (Blob/File)
+PASS x/æ (Request/Response)
+FAIL x/x;æ=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;æ=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=æ;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"æ\";bonus=x" but got ""
+FAIL x/x;x=æ;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"æ\";bonus=x" but got ""
+FAIL x/x;x="æ";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"æ\";bonus=x" but got ""
+FAIL x/x;x="æ";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"æ\";bonus=x" but got ""
+PASS ç/x (Blob/File)
+PASS ç/x (Request/Response)
+PASS x/ç (Blob/File)
+PASS x/ç (Request/Response)
+FAIL x/x;ç=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;ç=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=ç;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ç\";bonus=x" but got ""
+FAIL x/x;x=ç;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ç\";bonus=x" but got ""
+FAIL x/x;x="ç";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ç\";bonus=x" but got ""
+FAIL x/x;x="ç";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ç\";bonus=x" but got ""
+PASS è/x (Blob/File)
+PASS è/x (Request/Response)
+PASS x/è (Blob/File)
+PASS x/è (Request/Response)
+FAIL x/x;è=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;è=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=è;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"è\";bonus=x" but got ""
+FAIL x/x;x=è;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"è\";bonus=x" but got ""
+FAIL x/x;x="è";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"è\";bonus=x" but got ""
+FAIL x/x;x="è";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"è\";bonus=x" but got ""
+PASS é/x (Blob/File)
+PASS é/x (Request/Response)
+PASS x/é (Blob/File)
+PASS x/é (Request/Response)
+FAIL x/x;é=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;é=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=é;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"é\";bonus=x" but got ""
+FAIL x/x;x=é;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"é\";bonus=x" but got ""
+FAIL x/x;x="é";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"é\";bonus=x" but got ""
+FAIL x/x;x="é";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"é\";bonus=x" but got ""
+PASS ê/x (Blob/File)
+PASS ê/x (Request/Response)
+PASS x/ê (Blob/File)
+PASS x/ê (Request/Response)
+FAIL x/x;ê=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;ê=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=ê;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ê\";bonus=x" but got ""
+FAIL x/x;x=ê;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ê\";bonus=x" but got ""
+FAIL x/x;x="ê";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ê\";bonus=x" but got ""
+FAIL x/x;x="ê";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ê\";bonus=x" but got ""
+PASS ë/x (Blob/File)
+PASS ë/x (Request/Response)
+PASS x/ë (Blob/File)
+PASS x/ë (Request/Response)
+FAIL x/x;ë=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;ë=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=ë;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ë\";bonus=x" but got ""
+FAIL x/x;x=ë;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ë\";bonus=x" but got ""
+FAIL x/x;x="ë";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ë\";bonus=x" but got ""
+FAIL x/x;x="ë";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ë\";bonus=x" but got ""
+PASS ì/x (Blob/File)
+PASS ì/x (Request/Response)
+PASS x/ì (Blob/File)
+PASS x/ì (Request/Response)
+FAIL x/x;ì=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;ì=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=ì;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ì\";bonus=x" but got ""
+FAIL x/x;x=ì;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ì\";bonus=x" but got ""
+FAIL x/x;x="ì";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ì\";bonus=x" but got ""
+FAIL x/x;x="ì";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ì\";bonus=x" but got ""
+PASS í/x (Blob/File)
+PASS í/x (Request/Response)
+PASS x/í (Blob/File)
+PASS x/í (Request/Response)
+FAIL x/x;í=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;í=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=í;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"í\";bonus=x" but got ""
+FAIL x/x;x=í;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"í\";bonus=x" but got ""
+FAIL x/x;x="í";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"í\";bonus=x" but got ""
+FAIL x/x;x="í";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"í\";bonus=x" but got ""
+PASS î/x (Blob/File)
+PASS î/x (Request/Response)
+PASS x/î (Blob/File)
+PASS x/î (Request/Response)
+FAIL x/x;î=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;î=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=î;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"î\";bonus=x" but got ""
+FAIL x/x;x=î;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"î\";bonus=x" but got ""
+FAIL x/x;x="î";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"î\";bonus=x" but got ""
+FAIL x/x;x="î";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"î\";bonus=x" but got ""
+PASS ï/x (Blob/File)
+PASS ï/x (Request/Response)
+PASS x/ï (Blob/File)
+PASS x/ï (Request/Response)
+FAIL x/x;ï=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;ï=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=ï;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ï\";bonus=x" but got ""
+FAIL x/x;x=ï;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ï\";bonus=x" but got ""
+FAIL x/x;x="ï";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ï\";bonus=x" but got ""
+FAIL x/x;x="ï";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ï\";bonus=x" but got ""
+PASS ð/x (Blob/File)
+PASS ð/x (Request/Response)
+PASS x/ð (Blob/File)
+PASS x/ð (Request/Response)
+FAIL x/x;ð=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;ð=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=ð;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ð\";bonus=x" but got ""
+FAIL x/x;x=ð;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ð\";bonus=x" but got ""
+FAIL x/x;x="ð";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ð\";bonus=x" but got ""
+FAIL x/x;x="ð";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ð\";bonus=x" but got ""
+PASS ñ/x (Blob/File)
+PASS ñ/x (Request/Response)
+PASS x/ñ (Blob/File)
+PASS x/ñ (Request/Response)
+FAIL x/x;ñ=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;ñ=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=ñ;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ñ\";bonus=x" but got ""
+FAIL x/x;x=ñ;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ñ\";bonus=x" but got ""
+FAIL x/x;x="ñ";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ñ\";bonus=x" but got ""
+FAIL x/x;x="ñ";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ñ\";bonus=x" but got ""
+PASS ò/x (Blob/File)
+PASS ò/x (Request/Response)
+PASS x/ò (Blob/File)
+PASS x/ò (Request/Response)
+FAIL x/x;ò=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;ò=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=ò;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ò\";bonus=x" but got ""
+FAIL x/x;x=ò;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ò\";bonus=x" but got ""
+FAIL x/x;x="ò";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ò\";bonus=x" but got ""
+FAIL x/x;x="ò";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ò\";bonus=x" but got ""
+PASS ó/x (Blob/File)
+PASS ó/x (Request/Response)
+PASS x/ó (Blob/File)
+PASS x/ó (Request/Response)
+FAIL x/x;ó=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;ó=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=ó;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ó\";bonus=x" but got ""
+FAIL x/x;x=ó;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ó\";bonus=x" but got ""
+FAIL x/x;x="ó";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ó\";bonus=x" but got ""
+FAIL x/x;x="ó";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ó\";bonus=x" but got ""
+PASS ô/x (Blob/File)
+PASS ô/x (Request/Response)
+PASS x/ô (Blob/File)
+PASS x/ô (Request/Response)
+FAIL x/x;ô=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;ô=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=ô;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ô\";bonus=x" but got ""
+FAIL x/x;x=ô;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ô\";bonus=x" but got ""
+FAIL x/x;x="ô";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ô\";bonus=x" but got ""
+FAIL x/x;x="ô";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ô\";bonus=x" but got ""
+PASS õ/x (Blob/File)
+PASS õ/x (Request/Response)
+PASS x/õ (Blob/File)
+PASS x/õ (Request/Response)
+FAIL x/x;õ=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;õ=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=õ;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"õ\";bonus=x" but got ""
+FAIL x/x;x=õ;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"õ\";bonus=x" but got ""
+FAIL x/x;x="õ";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"õ\";bonus=x" but got ""
+FAIL x/x;x="õ";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"õ\";bonus=x" but got ""
+PASS ö/x (Blob/File)
+PASS ö/x (Request/Response)
+PASS x/ö (Blob/File)
+PASS x/ö (Request/Response)
+FAIL x/x;ö=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;ö=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=ö;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ö\";bonus=x" but got ""
+FAIL x/x;x=ö;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ö\";bonus=x" but got ""
+FAIL x/x;x="ö";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ö\";bonus=x" but got ""
+FAIL x/x;x="ö";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ö\";bonus=x" but got ""
+PASS ÷/x (Blob/File)
+PASS ÷/x (Request/Response)
+PASS x/÷ (Blob/File)
+PASS x/÷ (Request/Response)
+FAIL x/x;÷=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;÷=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=÷;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"÷\";bonus=x" but got ""
+FAIL x/x;x=÷;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"÷\";bonus=x" but got ""
+FAIL x/x;x="÷";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"÷\";bonus=x" but got ""
+FAIL x/x;x="÷";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"÷\";bonus=x" but got ""
+PASS ø/x (Blob/File)
+PASS ø/x (Request/Response)
+PASS x/ø (Blob/File)
+PASS x/ø (Request/Response)
+FAIL x/x;ø=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;ø=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=ø;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ø\";bonus=x" but got ""
+FAIL x/x;x=ø;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ø\";bonus=x" but got ""
+FAIL x/x;x="ø";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ø\";bonus=x" but got ""
+FAIL x/x;x="ø";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ø\";bonus=x" but got ""
+PASS ù/x (Blob/File)
+PASS ù/x (Request/Response)
+PASS x/ù (Blob/File)
+PASS x/ù (Request/Response)
+FAIL x/x;ù=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;ù=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=ù;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ù\";bonus=x" but got ""
+FAIL x/x;x=ù;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ù\";bonus=x" but got ""
+FAIL x/x;x="ù";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ù\";bonus=x" but got ""
+FAIL x/x;x="ù";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ù\";bonus=x" but got ""
+PASS ú/x (Blob/File)
+PASS ú/x (Request/Response)
+PASS x/ú (Blob/File)
+PASS x/ú (Request/Response)
+FAIL x/x;ú=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;ú=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=ú;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ú\";bonus=x" but got ""
+FAIL x/x;x=ú;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ú\";bonus=x" but got ""
+FAIL x/x;x="ú";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ú\";bonus=x" but got ""
+FAIL x/x;x="ú";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ú\";bonus=x" but got ""
+PASS û/x (Blob/File)
+PASS û/x (Request/Response)
+PASS x/û (Blob/File)
+PASS x/û (Request/Response)
+FAIL x/x;û=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;û=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=û;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"û\";bonus=x" but got ""
+FAIL x/x;x=û;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"û\";bonus=x" but got ""
+FAIL x/x;x="û";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"û\";bonus=x" but got ""
+FAIL x/x;x="û";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"û\";bonus=x" but got ""
+PASS ü/x (Blob/File)
+PASS ü/x (Request/Response)
+PASS x/ü (Blob/File)
+PASS x/ü (Request/Response)
+FAIL x/x;ü=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;ü=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=ü;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ü\";bonus=x" but got ""
+FAIL x/x;x=ü;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ü\";bonus=x" but got ""
+FAIL x/x;x="ü";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ü\";bonus=x" but got ""
+FAIL x/x;x="ü";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ü\";bonus=x" but got ""
+PASS ý/x (Blob/File)
+PASS ý/x (Request/Response)
+PASS x/ý (Blob/File)
+PASS x/ý (Request/Response)
+FAIL x/x;ý=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;ý=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=ý;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ý\";bonus=x" but got ""
+FAIL x/x;x=ý;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ý\";bonus=x" but got ""
+FAIL x/x;x="ý";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ý\";bonus=x" but got ""
+FAIL x/x;x="ý";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ý\";bonus=x" but got ""
+PASS þ/x (Blob/File)
+PASS þ/x (Request/Response)
+PASS x/þ (Blob/File)
+PASS x/þ (Request/Response)
+FAIL x/x;þ=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;þ=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=þ;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"þ\";bonus=x" but got ""
+FAIL x/x;x=þ;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"þ\";bonus=x" but got ""
+FAIL x/x;x="þ";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"þ\";bonus=x" but got ""
+FAIL x/x;x="þ";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"þ\";bonus=x" but got ""
+PASS ÿ/x (Blob/File)
+PASS ÿ/x (Request/Response)
+PASS x/ÿ (Blob/File)
+PASS x/ÿ (Request/Response)
+FAIL x/x;ÿ=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;ÿ=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=ÿ;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ÿ\";bonus=x" but got ""
+FAIL x/x;x=ÿ;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ÿ\";bonus=x" but got ""
+FAIL x/x;x="ÿ";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ÿ\";bonus=x" but got ""
+FAIL x/x;x="ÿ";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ÿ\";bonus=x" but got ""
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mimesniff/mime-types/parsing.any.js b/third_party/WebKit/LayoutTests/external/wpt/mimesniff/mime-types/parsing.any.js
new file mode 100644
index 0000000..bd9a62e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/mimesniff/mime-types/parsing.any.js
@@ -0,0 +1,51 @@
+// META: timeout=long
+
+promise_test(() => {
+  return Promise.all([
+    fetch("resources/mime-types.json"),
+    fetch("resources/generated-mime-types.json")
+  ]).then(([res, res2]) => res.json().then(runTests).then(() => res2.json().then(runTests)));
+}, "Loading data…");
+
+function isByteCompatible(str) {
+  for(let i = 0; i < str.length; i++) {
+    const charCode = str.charCodeAt(i);
+    // See https://github.com/w3c/web-platform-tests/issues/8372 for 0x0B and 0x0C
+    // See https://fetch.spec.whatwg.org/#concept-header-value for the remainder
+    if(charCode > 0xFF) {
+      return "incompatible";
+    } else if(charCode === 0x00 || charCode === 0x0A || charCode === 0x0D) {
+      return "header-value-incompatible";
+    } else if(charCode === 0x0B || charCode === 0x0C) {
+      return "wptserve-incompatible";
+    }
+  }
+  return "compatible";
+}
+
+function runTests(tests) {
+  tests.forEach(val => {
+    if(typeof val === "string") {
+      return;
+    }
+    const output = val.output === null ? "" : val.output
+    test(() => {
+      assert_equals(new Blob([], { type: val.input}).type, output, "Blob");
+      assert_equals(new File([], "noname", { type: val.input}).type, output, "File");
+    }, val.input + " (Blob/File)");
+
+    promise_test(() => {
+      const compatibleNess = isByteCompatible(val.input);
+      if(compatibleNess === "incompatible" || compatibleNess === "header-value-incompatible") {
+        assert_throws(new TypeError(), () => new Request("about:blank", { headers: [["Content-Type", val.input]] }));
+        assert_throws(new TypeError(), () => new Response(null, { headers: [["Content-Type", val.input]] }));
+        return Promise.resolve();
+      } else {
+        return Promise.all([
+          new Request("about:blank", { headers: [["Content-Type", val.input]] }).blob().then(blob => assert_equals(blob.type, output)),
+          new Response(null, { headers: [["Content-Type", val.input]] }).blob().then(blob => assert_equals(blob.type, output))
+        ]);
+      }
+    }, val.input + " (Request/Response)");
+  });
+}
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mimesniff/mime-types/parsing.any.worker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/mimesniff/mime-types/parsing.any.worker-expected.txt
new file mode 100644
index 0000000..77f8830
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/mimesniff/mime-types/parsing.any.worker-expected.txt
@@ -0,0 +1,1871 @@
+This is a testharness.js-based test.
+Found 1857 tests; 697 PASS, 1160 FAIL, 0 TIMEOUT, 0 NOTRUN.
+PASS Loading data…
+PASS text/html;charset=gbk (Blob/File)
+PASS text/html;charset=gbk (Request/Response)
+FAIL TEXT/HTML;CHARSET=GBK (Blob/File) assert_equals: Blob expected "text/html;charset=GBK" but got "text/html;charset=gbk"
+FAIL TEXT/HTML;CHARSET=GBK (Request/Response) assert_equals: expected "text/html;charset=GBK" but got "text/html;charset=gbk"
+FAIL text/html;charset=gbk( (Blob/File) assert_equals: Blob expected "text/html;charset=\"gbk(\"" but got "text/html;charset=gbk("
+FAIL text/html;charset=gbk( (Request/Response) assert_equals: expected "text/html;charset=\"gbk(\"" but got "text/html;charset=gbk("
+FAIL text/html;x=(;charset=gbk (Blob/File) assert_equals: Blob expected "text/html;x=\"(\";charset=gbk" but got "text/html;x=(;charset=gbk"
+FAIL text/html;x=(;charset=gbk (Request/Response) assert_equals: expected "text/html;x=\"(\";charset=gbk" but got "text/html;x=(;charset=gbk"
+FAIL text/html;charset=gbk;charset=windows-1255 (Blob/File) assert_equals: Blob expected "text/html;charset=gbk" but got "text/html;charset=gbk;charset=windows-1255"
+FAIL text/html;charset=gbk;charset=windows-1255 (Request/Response) assert_equals: expected "text/html;charset=gbk" but got "text/html;charset=gbk;charset=windows-1255"
+FAIL text/html;charset =gbk (Blob/File) assert_equals: Blob expected "text/html" but got "text/html;charset =gbk"
+FAIL text/html;charset =gbk (Request/Response) assert_equals: expected "text/html" but got "text/html;charset =gbk"
+FAIL text/html ;charset=gbk (Blob/File) assert_equals: Blob expected "text/html;charset=gbk" but got "text/html ;charset=gbk"
+FAIL text/html ;charset=gbk (Request/Response) assert_equals: expected "text/html;charset=gbk" but got "text/html ;charset=gbk"
+FAIL text/html; charset=gbk (Blob/File) assert_equals: Blob expected "text/html;charset=gbk" but got "text/html; charset=gbk"
+FAIL text/html; charset=gbk (Request/Response) assert_equals: expected "text/html;charset=gbk" but got "text/html; charset=gbk"
+FAIL text/html;charset= gbk (Blob/File) assert_equals: Blob expected "text/html;charset=\" gbk\"" but got "text/html;charset= gbk"
+FAIL text/html;charset= gbk (Request/Response) assert_equals: expected "text/html;charset=\" gbk\"" but got "text/html;charset= gbk"
+PASS text/html;charset='gbk' (Blob/File)
+PASS text/html;charset='gbk' (Request/Response)
+PASS text/html;charset='gbk (Blob/File)
+PASS text/html;charset='gbk (Request/Response)
+PASS text/html;charset=gbk' (Blob/File)
+PASS text/html;charset=gbk' (Request/Response)
+FAIL text/html;test;charset=gbk (Blob/File) assert_equals: Blob expected "text/html;charset=gbk" but got "text/html;test;charset=gbk"
+FAIL text/html;test;charset=gbk (Request/Response) assert_equals: expected "text/html;charset=gbk" but got "text/html;test;charset=gbk"
+FAIL text/html;test=;charset=gbk (Blob/File) assert_equals: Blob expected "text/html;charset=gbk" but got "text/html;test=;charset=gbk"
+FAIL text/html;test=;charset=gbk (Request/Response) assert_equals: expected "text/html;charset=gbk" but got "text/html;test=;charset=gbk"
+FAIL text/html;';charset=gbk (Blob/File) assert_equals: Blob expected "text/html;charset=gbk" but got "text/html;';charset=gbk"
+FAIL text/html;';charset=gbk (Request/Response) assert_equals: expected "text/html;charset=gbk" but got "text/html;';charset=gbk"
+FAIL text/html;";charset=gbk (Blob/File) assert_equals: Blob expected "text/html;charset=gbk" but got "text/html;\";charset=gbk"
+FAIL text/html;";charset=gbk (Request/Response) assert_equals: expected "text/html;charset=gbk" but got "text/html;\";charset=gbk"
+FAIL text/html ; ; charset=gbk (Blob/File) assert_equals: Blob expected "text/html;charset=gbk" but got "text/html ; ; charset=gbk"
+FAIL text/html ; ; charset=gbk (Request/Response) assert_equals: expected "text/html;charset=gbk" but got "text/html ; ; charset=gbk"
+FAIL text/html;;;;charset=gbk (Blob/File) assert_equals: Blob expected "text/html;charset=gbk" but got "text/html;;;;charset=gbk"
+FAIL text/html;;;;charset=gbk (Request/Response) assert_equals: expected "text/html;charset=gbk" but got "text/html;;;;charset=gbk"
+FAIL text/html;charset="gbk" (Blob/File) assert_equals: Blob expected "text/html;charset=gbk" but got "text/html;charset=\"gbk\""
+FAIL text/html;charset="gbk" (Request/Response) assert_equals: expected "text/html;charset=gbk" but got "text/html;charset=\"gbk\""
+FAIL text/html;charset="gbk (Blob/File) assert_equals: Blob expected "text/html;charset=gbk" but got "text/html;charset=\"gbk"
+FAIL text/html;charset="gbk (Request/Response) assert_equals: expected "text/html;charset=gbk" but got "text/html;charset=\"gbk"
+FAIL text/html;charset=gbk" (Blob/File) assert_equals: Blob expected "text/html;charset=\"gbk\\\"\"" but got "text/html;charset=gbk\""
+FAIL text/html;charset=gbk" (Request/Response) assert_equals: expected "text/html;charset=\"gbk\\\"\"" but got "text/html;charset=gbk\""
+PASS text/html;charset=" gbk" (Blob/File)
+PASS text/html;charset=" gbk" (Request/Response)
+FAIL text/html;charset="\ gbk" (Blob/File) assert_equals: Blob expected "text/html;charset=\" gbk\"" but got "text/html;charset=\"\\ gbk\""
+FAIL text/html;charset="\ gbk" (Request/Response) assert_equals: expected "text/html;charset=\" gbk\"" but got "text/html;charset=\"\\ gbk\""
+FAIL text/html;charset="\g\b\k" (Blob/File) assert_equals: Blob expected "text/html;charset=gbk" but got "text/html;charset=\"\\g\b\k\""
+FAIL text/html;charset="\g\b\k" (Request/Response) assert_equals: expected "text/html;charset=gbk" but got "text/html;charset=\"\\g\b\k\""
+FAIL text/html;charset="gbk"x (Blob/File) assert_equals: Blob expected "text/html;charset=gbk" but got "text/html;charset=\"gbk\"x"
+FAIL text/html;charset="gbk"x (Request/Response) assert_equals: expected "text/html;charset=gbk" but got "text/html;charset=\"gbk\"x"
+FAIL text/html;charset={gbk} (Blob/File) assert_equals: Blob expected "text/html;charset=\"{gbk}\"" but got "text/html;charset={gbk}"
+FAIL text/html;charset={gbk} (Request/Response) assert_equals: expected "text/html;charset=\"{gbk}\"" but got "text/html;charset={gbk}"
+PASS text/html;0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789=x;charset=gbk (Blob/File)
+PASS text/html;0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789=x;charset=gbk (Request/Response)
+PASS 0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789/0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 (Blob/File)
+PASS 0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789/0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 (Request/Response)
+FAIL !#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz;!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz=!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz (Blob/File) assert_equals: Blob expected "!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz/!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz;!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz=!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" but got "!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz/!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz;!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz=!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
+FAIL !#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz;!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz=!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz (Request/Response) assert_equals: expected "!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz/!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz;!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz=!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" but got "!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz/!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz;!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz=!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
+FAIL x/x;x="	 !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ" (Blob/File) assert_equals: Blob expected "x/x;x=\"\t !\\\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ\"" but got ""
+FAIL x/x;x="	 !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ" (Request/Response) assert_equals: expected "x/x;x=\"\t !\\\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ\"" but got ""
+FAIL x/x;test (Blob/File) assert_equals: Blob expected "x/x" but got "x/x;test"
+FAIL x/x;test (Request/Response) assert_equals: expected "x/x" but got "x/x;test"
+FAIL x/x;test="\ (Blob/File) assert_equals: Blob expected "x/x;test=\"\\\\"" but got "x/x;test=\"\\"
+FAIL x/x;test="\ (Request/Response) assert_equals: expected "x/x;test=\"\\\\"" but got "x/x;test=\"\\"
+FAIL x/x;x=  (Blob/File) assert_equals: Blob expected "x/x" but got "x/x;x= "
+FAIL x/x;x=  (Request/Response) assert_equals: expected "x/x" but got "x/x;x="
+FAIL x/x;x=	 (Blob/File) assert_equals: Blob expected "x/x" but got ""
+FAIL x/x;x=	 (Request/Response) assert_equals: expected "x/x" but got "x/x;x="
+FAIL text/html;test=ÿ;charset=gbk (Blob/File) assert_equals: Blob expected "text/html;test=\"ÿ\";charset=gbk" but got ""
+FAIL text/html;test=ÿ;charset=gbk (Request/Response) assert_equals: expected "text/html;test=\"ÿ\";charset=gbk" but got ""
+FAIL x/x;test=�;x=x (Blob/File) assert_equals: Blob expected "x/x;x=x" but got ""
+PASS x/x;test=�;x=x (Request/Response)
+PASS  (Blob/File)
+PASS  (Request/Response)
+PASS 	 (Blob/File)
+PASS 	 (Request/Response)
+FAIL bogus (Blob/File) assert_equals: Blob expected "" but got "bogus"
+FAIL bogus (Request/Response) assert_equals: expected "" but got "bogus"
+FAIL bogus/ (Blob/File) assert_equals: Blob expected "" but got "bogus/"
+FAIL bogus/ (Request/Response) assert_equals: expected "" but got "bogus/"
+FAIL bogus/  (Blob/File) assert_equals: Blob expected "" but got "bogus/ "
+FAIL bogus/  (Request/Response) assert_equals: expected "" but got "bogus/"
+FAIL bogus/bogus/; (Blob/File) assert_equals: Blob expected "" but got "bogus/bogus/;"
+FAIL bogus/bogus/; (Request/Response) assert_equals: expected "" but got "bogus/bogus/;"
+FAIL </> (Blob/File) assert_equals: Blob expected "" but got "</>"
+FAIL </> (Request/Response) assert_equals: expected "" but got "</>"
+FAIL (/) (Blob/File) assert_equals: Blob expected "" but got "(/)"
+FAIL (/) (Request/Response) assert_equals: expected "" but got "(/)"
+FAIL text/html(;doesnot=matter (Blob/File) assert_equals: Blob expected "" but got "text/html(;doesnot=matter"
+FAIL text/html(;doesnot=matter (Request/Response) assert_equals: expected "" but got "text/html(;doesnot=matter"
+FAIL {/} (Blob/File) assert_equals: Blob expected "" but got "{/}"
+FAIL {/} (Request/Response) assert_equals: expected "" but got "{/}"
+PASS Ā/Ā (Blob/File)
+PASS Ā/Ā (Request/Response)
+PASS \0/x (Blob/File)
+PASS \0/x (Request/Response)
+PASS x/\0 (Blob/File)
+PASS x/\0 (Request/Response)
+FAIL x/x;\0=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+PASS x/x;\0=x;bonus=x (Request/Response)
+FAIL x/x;x=\0;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+PASS x/x;x=\0;bonus=x (Request/Response)
+FAIL x/x;x="\0";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+PASS x/x;x="\0";bonus=x (Request/Response)
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS 	/x (Blob/File)
+FAIL 	/x (Request/Response) assert_equals: expected "" but got "/x"
+PASS x/	 (Blob/File)
+FAIL x/	 (Request/Response) assert_equals: expected "" but got "x/"
+FAIL x/x;	=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;	=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS 
+/x (Blob/File)
+FAIL 
+/x (Request/Response) assert_throws: function "() => new Request("about:blank", { headers: [["Content-Type", val.input]] })" did not throw
+PASS x/
+ (Blob/File)
+FAIL x/
+ (Request/Response) assert_throws: function "() => new Request("about:blank", { headers: [["Content-Type", val.input]] })" did not throw
+FAIL x/x;
+=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+PASS x/x;
+=x;bonus=x (Request/Response)
+FAIL x/x;x=
+;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+PASS x/x;x=
+;bonus=x (Request/Response)
+FAIL x/x;x="
+";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+PASS x/x;x="
+";bonus=x (Request/Response)
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS \r/x (Blob/File)
+FAIL \r/x (Request/Response) assert_throws: function "() => new Request("about:blank", { headers: [["Content-Type", val.input]] })" did not throw
+PASS x/\r (Blob/File)
+FAIL x/\r (Request/Response) assert_throws: function "() => new Request("about:blank", { headers: [["Content-Type", val.input]] })" did not throw
+FAIL x/x;\r=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+PASS x/x;\r=x;bonus=x (Request/Response)
+FAIL x/x;x=\r;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+PASS x/x;x=\r;bonus=x (Request/Response)
+FAIL x/x;x="\r";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+PASS x/x;x="\r";bonus=x (Request/Response)
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL  /x (Blob/File) assert_equals: Blob expected "" but got " /x"
+FAIL  /x (Request/Response) assert_equals: expected "" but got "/x"
+FAIL x/  (Blob/File) assert_equals: Blob expected "" but got "x/ "
+FAIL x/  (Request/Response) assert_equals: expected "" but got "x/"
+FAIL x/x; =x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got "x/x; =x;bonus=x"
+FAIL x/x; =x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got "x/x; =x;bonus=x"
+FAIL "/x (Blob/File) assert_equals: Blob expected "" but got "\"/x"
+FAIL "/x (Request/Response) assert_equals: expected "" but got "\"/x"
+FAIL x/" (Blob/File) assert_equals: Blob expected "" but got "x/\""
+FAIL x/" (Request/Response) assert_equals: expected "" but got "x/\""
+FAIL x/x;"=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got "x/x;\"=x;bonus=x"
+FAIL x/x;"=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got "x/x;\"=x;bonus=x"
+FAIL (/x (Blob/File) assert_equals: Blob expected "" but got "(/x"
+FAIL (/x (Request/Response) assert_equals: expected "" but got "(/x"
+FAIL x/( (Blob/File) assert_equals: Blob expected "" but got "x/("
+FAIL x/( (Request/Response) assert_equals: expected "" but got "x/("
+FAIL x/x;(=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got "x/x;(=x;bonus=x"
+FAIL x/x;(=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got "x/x;(=x;bonus=x"
+FAIL x/x;x=(;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"(\";bonus=x" but got "x/x;x=(;bonus=x"
+FAIL x/x;x=(;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"(\";bonus=x" but got "x/x;x=(;bonus=x"
+PASS x/x;x="(";bonus=x (Blob/File)
+PASS x/x;x="(";bonus=x (Request/Response)
+FAIL )/x (Blob/File) assert_equals: Blob expected "" but got ")/x"
+FAIL )/x (Request/Response) assert_equals: expected "" but got ")/x"
+FAIL x/) (Blob/File) assert_equals: Blob expected "" but got "x/)"
+FAIL x/) (Request/Response) assert_equals: expected "" but got "x/)"
+FAIL x/x;)=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got "x/x;)=x;bonus=x"
+FAIL x/x;)=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got "x/x;)=x;bonus=x"
+FAIL x/x;x=);bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\")\";bonus=x" but got "x/x;x=);bonus=x"
+FAIL x/x;x=);bonus=x (Request/Response) assert_equals: expected "x/x;x=\")\";bonus=x" but got "x/x;x=);bonus=x"
+PASS x/x;x=")";bonus=x (Blob/File)
+PASS x/x;x=")";bonus=x (Request/Response)
+FAIL ,/x (Blob/File) assert_equals: Blob expected "" but got ",/x"
+FAIL ,/x (Request/Response) assert_equals: expected "" but got ",/x"
+FAIL x/, (Blob/File) assert_equals: Blob expected "" but got "x/,"
+FAIL x/, (Request/Response) assert_equals: expected "" but got "x/,"
+FAIL x/x;,=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got "x/x;,=x;bonus=x"
+FAIL x/x;,=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got "x/x;,=x;bonus=x"
+FAIL x/x;x=,;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\",\";bonus=x" but got "x/x;x=,;bonus=x"
+FAIL x/x;x=,;bonus=x (Request/Response) assert_equals: expected "x/x;x=\",\";bonus=x" but got "x/x;x=,;bonus=x"
+PASS x/x;x=",";bonus=x (Blob/File)
+PASS x/x;x=",";bonus=x (Request/Response)
+FAIL x/x;/=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got "x/x;/=x;bonus=x"
+FAIL x/x;/=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got "x/x;/=x;bonus=x"
+FAIL x/x;x=/;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"/\";bonus=x" but got "x/x;x=/;bonus=x"
+FAIL x/x;x=/;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"/\";bonus=x" but got "x/x;x=/;bonus=x"
+PASS x/x;x="/";bonus=x (Blob/File)
+PASS x/x;x="/";bonus=x (Request/Response)
+FAIL :/x (Blob/File) assert_equals: Blob expected "" but got ":/x"
+FAIL :/x (Request/Response) assert_equals: expected "" but got ":/x"
+FAIL x/: (Blob/File) assert_equals: Blob expected "" but got "x/:"
+FAIL x/: (Request/Response) assert_equals: expected "" but got "x/:"
+FAIL x/x;:=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got "x/x;:=x;bonus=x"
+FAIL x/x;:=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got "x/x;:=x;bonus=x"
+FAIL x/x;x=:;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\":\";bonus=x" but got "x/x;x=:;bonus=x"
+FAIL x/x;x=:;bonus=x (Request/Response) assert_equals: expected "x/x;x=\":\";bonus=x" but got "x/x;x=:;bonus=x"
+PASS x/x;x=":";bonus=x (Blob/File)
+PASS x/x;x=":";bonus=x (Request/Response)
+FAIL ;/x (Blob/File) assert_equals: Blob expected "" but got ";/x"
+FAIL ;/x (Request/Response) assert_equals: expected "" but got ";/x"
+FAIL x/; (Blob/File) assert_equals: Blob expected "" but got "x/;"
+FAIL x/; (Request/Response) assert_equals: expected "" but got "x/;"
+FAIL </x (Blob/File) assert_equals: Blob expected "" but got "</x"
+FAIL </x (Request/Response) assert_equals: expected "" but got "</x"
+FAIL x/< (Blob/File) assert_equals: Blob expected "" but got "x/<"
+FAIL x/< (Request/Response) assert_equals: expected "" but got "x/<"
+FAIL x/x;<=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got "x/x;<=x;bonus=x"
+FAIL x/x;<=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got "x/x;<=x;bonus=x"
+FAIL x/x;x=<;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"<\";bonus=x" but got "x/x;x=<;bonus=x"
+FAIL x/x;x=<;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"<\";bonus=x" but got "x/x;x=<;bonus=x"
+PASS x/x;x="<";bonus=x (Blob/File)
+PASS x/x;x="<";bonus=x (Request/Response)
+FAIL =/x (Blob/File) assert_equals: Blob expected "" but got "=/x"
+FAIL =/x (Request/Response) assert_equals: expected "" but got "=/x"
+FAIL x/= (Blob/File) assert_equals: Blob expected "" but got "x/="
+FAIL x/= (Request/Response) assert_equals: expected "" but got "x/="
+FAIL x/x;x==;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"=\";bonus=x" but got "x/x;x==;bonus=x"
+FAIL x/x;x==;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"=\";bonus=x" but got "x/x;x==;bonus=x"
+PASS x/x;x="=";bonus=x (Blob/File)
+PASS x/x;x="=";bonus=x (Request/Response)
+FAIL >/x (Blob/File) assert_equals: Blob expected "" but got ">/x"
+FAIL >/x (Request/Response) assert_equals: expected "" but got ">/x"
+FAIL x/> (Blob/File) assert_equals: Blob expected "" but got "x/>"
+FAIL x/> (Request/Response) assert_equals: expected "" but got "x/>"
+FAIL x/x;>=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got "x/x;>=x;bonus=x"
+FAIL x/x;>=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got "x/x;>=x;bonus=x"
+FAIL x/x;x=>;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\">\";bonus=x" but got "x/x;x=>;bonus=x"
+FAIL x/x;x=>;bonus=x (Request/Response) assert_equals: expected "x/x;x=\">\";bonus=x" but got "x/x;x=>;bonus=x"
+PASS x/x;x=">";bonus=x (Blob/File)
+PASS x/x;x=">";bonus=x (Request/Response)
+FAIL ?/x (Blob/File) assert_equals: Blob expected "" but got "?/x"
+FAIL ?/x (Request/Response) assert_equals: expected "" but got "?/x"
+FAIL x/? (Blob/File) assert_equals: Blob expected "" but got "x/?"
+FAIL x/? (Request/Response) assert_equals: expected "" but got "x/?"
+FAIL x/x;?=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got "x/x;?=x;bonus=x"
+FAIL x/x;?=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got "x/x;?=x;bonus=x"
+FAIL x/x;x=?;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"?\";bonus=x" but got "x/x;x=?;bonus=x"
+FAIL x/x;x=?;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"?\";bonus=x" but got "x/x;x=?;bonus=x"
+PASS x/x;x="?";bonus=x (Blob/File)
+PASS x/x;x="?";bonus=x (Request/Response)
+FAIL @/x (Blob/File) assert_equals: Blob expected "" but got "@/x"
+FAIL @/x (Request/Response) assert_equals: expected "" but got "@/x"
+FAIL x/@ (Blob/File) assert_equals: Blob expected "" but got "x/@"
+FAIL x/@ (Request/Response) assert_equals: expected "" but got "x/@"
+FAIL x/x;@=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got "x/x;@=x;bonus=x"
+FAIL x/x;@=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got "x/x;@=x;bonus=x"
+FAIL x/x;x=@;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"@\";bonus=x" but got "x/x;x=@;bonus=x"
+FAIL x/x;x=@;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"@\";bonus=x" but got "x/x;x=@;bonus=x"
+PASS x/x;x="@";bonus=x (Blob/File)
+PASS x/x;x="@";bonus=x (Request/Response)
+FAIL [/x (Blob/File) assert_equals: Blob expected "" but got "[/x"
+FAIL [/x (Request/Response) assert_equals: expected "" but got "[/x"
+FAIL x/[ (Blob/File) assert_equals: Blob expected "" but got "x/["
+FAIL x/[ (Request/Response) assert_equals: expected "" but got "x/["
+FAIL x/x;[=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got "x/x;[=x;bonus=x"
+FAIL x/x;[=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got "x/x;[=x;bonus=x"
+FAIL x/x;x=[;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"[\";bonus=x" but got "x/x;x=[;bonus=x"
+FAIL x/x;x=[;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"[\";bonus=x" but got "x/x;x=[;bonus=x"
+PASS x/x;x="[";bonus=x (Blob/File)
+PASS x/x;x="[";bonus=x (Request/Response)
+FAIL \/x (Blob/File) assert_equals: Blob expected "" but got "\\/x"
+FAIL \/x (Request/Response) assert_equals: expected "" but got "\\/x"
+FAIL x/\ (Blob/File) assert_equals: Blob expected "" but got "x/\\"
+FAIL x/\ (Request/Response) assert_equals: expected "" but got "x/\\"
+FAIL x/x;\=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got "x/x;\\=x;bonus=x"
+FAIL x/x;\=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got "x/x;\\=x;bonus=x"
+FAIL ]/x (Blob/File) assert_equals: Blob expected "" but got "]/x"
+FAIL ]/x (Request/Response) assert_equals: expected "" but got "]/x"
+FAIL x/] (Blob/File) assert_equals: Blob expected "" but got "x/]"
+FAIL x/] (Request/Response) assert_equals: expected "" but got "x/]"
+FAIL x/x;]=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got "x/x;]=x;bonus=x"
+FAIL x/x;]=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got "x/x;]=x;bonus=x"
+FAIL x/x;x=];bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"]\";bonus=x" but got "x/x;x=];bonus=x"
+FAIL x/x;x=];bonus=x (Request/Response) assert_equals: expected "x/x;x=\"]\";bonus=x" but got "x/x;x=];bonus=x"
+PASS x/x;x="]";bonus=x (Blob/File)
+PASS x/x;x="]";bonus=x (Request/Response)
+FAIL {/x (Blob/File) assert_equals: Blob expected "" but got "{/x"
+FAIL {/x (Request/Response) assert_equals: expected "" but got "{/x"
+FAIL x/{ (Blob/File) assert_equals: Blob expected "" but got "x/{"
+FAIL x/{ (Request/Response) assert_equals: expected "" but got "x/{"
+FAIL x/x;{=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got "x/x;{=x;bonus=x"
+FAIL x/x;{=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got "x/x;{=x;bonus=x"
+FAIL x/x;x={;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"{\";bonus=x" but got "x/x;x={;bonus=x"
+FAIL x/x;x={;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"{\";bonus=x" but got "x/x;x={;bonus=x"
+PASS x/x;x="{";bonus=x (Blob/File)
+PASS x/x;x="{";bonus=x (Request/Response)
+FAIL }/x (Blob/File) assert_equals: Blob expected "" but got "}/x"
+FAIL }/x (Request/Response) assert_equals: expected "" but got "}/x"
+FAIL x/} (Blob/File) assert_equals: Blob expected "" but got "x/}"
+FAIL x/} (Request/Response) assert_equals: expected "" but got "x/}"
+FAIL x/x;}=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got "x/x;}=x;bonus=x"
+FAIL x/x;}=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got "x/x;}=x;bonus=x"
+FAIL x/x;x=};bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"}\";bonus=x" but got "x/x;x=};bonus=x"
+FAIL x/x;x=};bonus=x (Request/Response) assert_equals: expected "x/x;x=\"}\";bonus=x" but got "x/x;x=};bonus=x"
+PASS x/x;x="}";bonus=x (Blob/File)
+PASS x/x;x="}";bonus=x (Request/Response)
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+PASS €/x (Blob/File)
+PASS €/x (Request/Response)
+PASS x/€ (Blob/File)
+PASS x/€ (Request/Response)
+FAIL x/x;€=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;€=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=€;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"€\";bonus=x" but got ""
+FAIL x/x;x=€;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"€\";bonus=x" but got ""
+FAIL x/x;x="€";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"€\";bonus=x" but got ""
+FAIL x/x;x="€";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"€\";bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"\";bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"\";bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"\";bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"\";bonus=x" but got ""
+PASS ‚/x (Blob/File)
+PASS ‚/x (Request/Response)
+PASS x/‚ (Blob/File)
+PASS x/‚ (Request/Response)
+FAIL x/x;‚=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;‚=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=‚;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"‚\";bonus=x" but got ""
+FAIL x/x;x=‚;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"‚\";bonus=x" but got ""
+FAIL x/x;x="‚";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"‚\";bonus=x" but got ""
+FAIL x/x;x="‚";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"‚\";bonus=x" but got ""
+PASS ƒ/x (Blob/File)
+PASS ƒ/x (Request/Response)
+PASS x/ƒ (Blob/File)
+PASS x/ƒ (Request/Response)
+FAIL x/x;ƒ=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;ƒ=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=ƒ;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ƒ\";bonus=x" but got ""
+FAIL x/x;x=ƒ;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ƒ\";bonus=x" but got ""
+FAIL x/x;x="ƒ";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ƒ\";bonus=x" but got ""
+FAIL x/x;x="ƒ";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ƒ\";bonus=x" but got ""
+PASS „/x (Blob/File)
+PASS „/x (Request/Response)
+PASS x/„ (Blob/File)
+PASS x/„ (Request/Response)
+FAIL x/x;„=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;„=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=„;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"„\";bonus=x" but got ""
+FAIL x/x;x=„;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"„\";bonus=x" but got ""
+FAIL x/x;x="„";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"„\";bonus=x" but got ""
+FAIL x/x;x="„";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"„\";bonus=x" but got ""
+PASS …/x (Blob/File)
+PASS …/x (Request/Response)
+PASS x/… (Blob/File)
+PASS x/… (Request/Response)
+FAIL x/x;…=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;…=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=…;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"…\";bonus=x" but got ""
+FAIL x/x;x=…;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"…\";bonus=x" but got ""
+FAIL x/x;x="…";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"…\";bonus=x" but got ""
+FAIL x/x;x="…";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"…\";bonus=x" but got ""
+PASS †/x (Blob/File)
+PASS †/x (Request/Response)
+PASS x/† (Blob/File)
+PASS x/† (Request/Response)
+FAIL x/x;†=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;†=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=†;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"†\";bonus=x" but got ""
+FAIL x/x;x=†;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"†\";bonus=x" but got ""
+FAIL x/x;x="†";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"†\";bonus=x" but got ""
+FAIL x/x;x="†";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"†\";bonus=x" but got ""
+PASS ‡/x (Blob/File)
+PASS ‡/x (Request/Response)
+PASS x/‡ (Blob/File)
+PASS x/‡ (Request/Response)
+FAIL x/x;‡=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;‡=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=‡;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"‡\";bonus=x" but got ""
+FAIL x/x;x=‡;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"‡\";bonus=x" but got ""
+FAIL x/x;x="‡";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"‡\";bonus=x" but got ""
+FAIL x/x;x="‡";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"‡\";bonus=x" but got ""
+PASS ˆ/x (Blob/File)
+PASS ˆ/x (Request/Response)
+PASS x/ˆ (Blob/File)
+PASS x/ˆ (Request/Response)
+FAIL x/x;ˆ=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;ˆ=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=ˆ;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ˆ\";bonus=x" but got ""
+FAIL x/x;x=ˆ;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ˆ\";bonus=x" but got ""
+FAIL x/x;x="ˆ";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ˆ\";bonus=x" but got ""
+FAIL x/x;x="ˆ";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ˆ\";bonus=x" but got ""
+PASS ‰/x (Blob/File)
+PASS ‰/x (Request/Response)
+PASS x/‰ (Blob/File)
+PASS x/‰ (Request/Response)
+FAIL x/x;‰=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;‰=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=‰;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"‰\";bonus=x" but got ""
+FAIL x/x;x=‰;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"‰\";bonus=x" but got ""
+FAIL x/x;x="‰";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"‰\";bonus=x" but got ""
+FAIL x/x;x="‰";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"‰\";bonus=x" but got ""
+PASS Š/x (Blob/File)
+PASS Š/x (Request/Response)
+PASS x/Š (Blob/File)
+PASS x/Š (Request/Response)
+FAIL x/x;Š=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Š=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Š;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Š\";bonus=x" but got ""
+FAIL x/x;x=Š;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Š\";bonus=x" but got ""
+FAIL x/x;x="Š";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Š\";bonus=x" but got ""
+FAIL x/x;x="Š";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Š\";bonus=x" but got ""
+PASS ‹/x (Blob/File)
+PASS ‹/x (Request/Response)
+PASS x/‹ (Blob/File)
+PASS x/‹ (Request/Response)
+FAIL x/x;‹=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;‹=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=‹;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"‹\";bonus=x" but got ""
+FAIL x/x;x=‹;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"‹\";bonus=x" but got ""
+FAIL x/x;x="‹";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"‹\";bonus=x" but got ""
+FAIL x/x;x="‹";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"‹\";bonus=x" but got ""
+PASS Œ/x (Blob/File)
+PASS Œ/x (Request/Response)
+PASS x/Œ (Blob/File)
+PASS x/Œ (Request/Response)
+FAIL x/x;Œ=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Œ=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Œ;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Œ\";bonus=x" but got ""
+FAIL x/x;x=Œ;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Œ\";bonus=x" but got ""
+FAIL x/x;x="Œ";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Œ\";bonus=x" but got ""
+FAIL x/x;x="Œ";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Œ\";bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"\";bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"\";bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"\";bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"\";bonus=x" but got ""
+PASS Ž/x (Blob/File)
+PASS Ž/x (Request/Response)
+PASS x/Ž (Blob/File)
+PASS x/Ž (Request/Response)
+FAIL x/x;Ž=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Ž=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Ž;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ž\";bonus=x" but got ""
+FAIL x/x;x=Ž;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ž\";bonus=x" but got ""
+FAIL x/x;x="Ž";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ž\";bonus=x" but got ""
+FAIL x/x;x="Ž";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ž\";bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"\";bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"\";bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"\";bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"\";bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"\";bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"\";bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"\";bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"\";bonus=x" but got ""
+PASS ‘/x (Blob/File)
+PASS ‘/x (Request/Response)
+PASS x/‘ (Blob/File)
+PASS x/‘ (Request/Response)
+FAIL x/x;‘=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;‘=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=‘;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"‘\";bonus=x" but got ""
+FAIL x/x;x=‘;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"‘\";bonus=x" but got ""
+FAIL x/x;x="‘";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"‘\";bonus=x" but got ""
+FAIL x/x;x="‘";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"‘\";bonus=x" but got ""
+PASS ’/x (Blob/File)
+PASS ’/x (Request/Response)
+PASS x/’ (Blob/File)
+PASS x/’ (Request/Response)
+FAIL x/x;’=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;’=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=’;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"’\";bonus=x" but got ""
+FAIL x/x;x=’;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"’\";bonus=x" but got ""
+FAIL x/x;x="’";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"’\";bonus=x" but got ""
+FAIL x/x;x="’";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"’\";bonus=x" but got ""
+PASS “/x (Blob/File)
+PASS “/x (Request/Response)
+PASS x/“ (Blob/File)
+PASS x/“ (Request/Response)
+FAIL x/x;“=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;“=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=“;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"“\";bonus=x" but got ""
+FAIL x/x;x=“;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"“\";bonus=x" but got ""
+FAIL x/x;x="“";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"“\";bonus=x" but got ""
+FAIL x/x;x="“";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"“\";bonus=x" but got ""
+PASS ”/x (Blob/File)
+PASS ”/x (Request/Response)
+PASS x/” (Blob/File)
+PASS x/” (Request/Response)
+FAIL x/x;”=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;”=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=”;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"”\";bonus=x" but got ""
+FAIL x/x;x=”;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"”\";bonus=x" but got ""
+FAIL x/x;x="”";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"”\";bonus=x" but got ""
+FAIL x/x;x="”";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"”\";bonus=x" but got ""
+PASS •/x (Blob/File)
+PASS •/x (Request/Response)
+PASS x/• (Blob/File)
+PASS x/• (Request/Response)
+FAIL x/x;•=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;•=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=•;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"•\";bonus=x" but got ""
+FAIL x/x;x=•;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"•\";bonus=x" but got ""
+FAIL x/x;x="•";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"•\";bonus=x" but got ""
+FAIL x/x;x="•";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"•\";bonus=x" but got ""
+PASS –/x (Blob/File)
+PASS –/x (Request/Response)
+PASS x/– (Blob/File)
+PASS x/– (Request/Response)
+FAIL x/x;–=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;–=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=–;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"–\";bonus=x" but got ""
+FAIL x/x;x=–;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"–\";bonus=x" but got ""
+FAIL x/x;x="–";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"–\";bonus=x" but got ""
+FAIL x/x;x="–";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"–\";bonus=x" but got ""
+PASS —/x (Blob/File)
+PASS —/x (Request/Response)
+PASS x/— (Blob/File)
+PASS x/— (Request/Response)
+FAIL x/x;—=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;—=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=—;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"—\";bonus=x" but got ""
+FAIL x/x;x=—;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"—\";bonus=x" but got ""
+FAIL x/x;x="—";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"—\";bonus=x" but got ""
+FAIL x/x;x="—";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"—\";bonus=x" but got ""
+PASS ˜/x (Blob/File)
+PASS ˜/x (Request/Response)
+PASS x/˜ (Blob/File)
+PASS x/˜ (Request/Response)
+FAIL x/x;˜=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;˜=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=˜;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"˜\";bonus=x" but got ""
+FAIL x/x;x=˜;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"˜\";bonus=x" but got ""
+FAIL x/x;x="˜";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"˜\";bonus=x" but got ""
+FAIL x/x;x="˜";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"˜\";bonus=x" but got ""
+PASS ™/x (Blob/File)
+PASS ™/x (Request/Response)
+PASS x/™ (Blob/File)
+PASS x/™ (Request/Response)
+FAIL x/x;™=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;™=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=™;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"™\";bonus=x" but got ""
+FAIL x/x;x=™;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"™\";bonus=x" but got ""
+FAIL x/x;x="™";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"™\";bonus=x" but got ""
+FAIL x/x;x="™";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"™\";bonus=x" but got ""
+PASS š/x (Blob/File)
+PASS š/x (Request/Response)
+PASS x/š (Blob/File)
+PASS x/š (Request/Response)
+FAIL x/x;š=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;š=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=š;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"š\";bonus=x" but got ""
+FAIL x/x;x=š;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"š\";bonus=x" but got ""
+FAIL x/x;x="š";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"š\";bonus=x" but got ""
+FAIL x/x;x="š";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"š\";bonus=x" but got ""
+PASS ›/x (Blob/File)
+PASS ›/x (Request/Response)
+PASS x/› (Blob/File)
+PASS x/› (Request/Response)
+FAIL x/x;›=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;›=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=›;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"›\";bonus=x" but got ""
+FAIL x/x;x=›;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"›\";bonus=x" but got ""
+FAIL x/x;x="›";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"›\";bonus=x" but got ""
+FAIL x/x;x="›";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"›\";bonus=x" but got ""
+PASS œ/x (Blob/File)
+PASS œ/x (Request/Response)
+PASS x/œ (Blob/File)
+PASS x/œ (Request/Response)
+FAIL x/x;œ=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;œ=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=œ;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"œ\";bonus=x" but got ""
+FAIL x/x;x=œ;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"œ\";bonus=x" but got ""
+FAIL x/x;x="œ";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"œ\";bonus=x" but got ""
+FAIL x/x;x="œ";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"œ\";bonus=x" but got ""
+PASS /x (Blob/File)
+PASS /x (Request/Response)
+PASS x/ (Blob/File)
+PASS x/ (Request/Response)
+FAIL x/x;=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"\";bonus=x" but got ""
+FAIL x/x;x=;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"\";bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"\";bonus=x" but got ""
+FAIL x/x;x="";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"\";bonus=x" but got ""
+PASS ž/x (Blob/File)
+PASS ž/x (Request/Response)
+PASS x/ž (Blob/File)
+PASS x/ž (Request/Response)
+FAIL x/x;ž=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;ž=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=ž;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ž\";bonus=x" but got ""
+FAIL x/x;x=ž;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ž\";bonus=x" but got ""
+FAIL x/x;x="ž";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ž\";bonus=x" but got ""
+FAIL x/x;x="ž";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ž\";bonus=x" but got ""
+PASS Ÿ/x (Blob/File)
+PASS Ÿ/x (Request/Response)
+PASS x/Ÿ (Blob/File)
+PASS x/Ÿ (Request/Response)
+FAIL x/x;Ÿ=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Ÿ=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Ÿ;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ÿ\";bonus=x" but got ""
+FAIL x/x;x=Ÿ;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ÿ\";bonus=x" but got ""
+FAIL x/x;x="Ÿ";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ÿ\";bonus=x" but got ""
+FAIL x/x;x="Ÿ";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ÿ\";bonus=x" but got ""
+PASS  /x (Blob/File)
+PASS  /x (Request/Response)
+PASS x/  (Blob/File)
+PASS x/  (Request/Response)
+FAIL x/x; =x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x; =x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x= ;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\" \";bonus=x" but got ""
+FAIL x/x;x= ;bonus=x (Request/Response) assert_equals: expected "x/x;x=\" \";bonus=x" but got ""
+FAIL x/x;x=" ";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\" \";bonus=x" but got ""
+FAIL x/x;x=" ";bonus=x (Request/Response) assert_equals: expected "x/x;x=\" \";bonus=x" but got ""
+PASS ¡/x (Blob/File)
+PASS ¡/x (Request/Response)
+PASS x/¡ (Blob/File)
+PASS x/¡ (Request/Response)
+FAIL x/x;¡=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;¡=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=¡;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¡\";bonus=x" but got ""
+FAIL x/x;x=¡;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¡\";bonus=x" but got ""
+FAIL x/x;x="¡";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¡\";bonus=x" but got ""
+FAIL x/x;x="¡";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¡\";bonus=x" but got ""
+PASS ¢/x (Blob/File)
+PASS ¢/x (Request/Response)
+PASS x/¢ (Blob/File)
+PASS x/¢ (Request/Response)
+FAIL x/x;¢=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;¢=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=¢;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¢\";bonus=x" but got ""
+FAIL x/x;x=¢;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¢\";bonus=x" but got ""
+FAIL x/x;x="¢";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¢\";bonus=x" but got ""
+FAIL x/x;x="¢";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¢\";bonus=x" but got ""
+PASS £/x (Blob/File)
+PASS £/x (Request/Response)
+PASS x/£ (Blob/File)
+PASS x/£ (Request/Response)
+FAIL x/x;£=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;£=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=£;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"£\";bonus=x" but got ""
+FAIL x/x;x=£;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"£\";bonus=x" but got ""
+FAIL x/x;x="£";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"£\";bonus=x" but got ""
+FAIL x/x;x="£";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"£\";bonus=x" but got ""
+PASS ¤/x (Blob/File)
+PASS ¤/x (Request/Response)
+PASS x/¤ (Blob/File)
+PASS x/¤ (Request/Response)
+FAIL x/x;¤=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;¤=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=¤;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¤\";bonus=x" but got ""
+FAIL x/x;x=¤;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¤\";bonus=x" but got ""
+FAIL x/x;x="¤";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¤\";bonus=x" but got ""
+FAIL x/x;x="¤";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¤\";bonus=x" but got ""
+PASS ¥/x (Blob/File)
+PASS ¥/x (Request/Response)
+PASS x/¥ (Blob/File)
+PASS x/¥ (Request/Response)
+FAIL x/x;¥=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;¥=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=¥;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¥\";bonus=x" but got ""
+FAIL x/x;x=¥;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¥\";bonus=x" but got ""
+FAIL x/x;x="¥";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¥\";bonus=x" but got ""
+FAIL x/x;x="¥";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¥\";bonus=x" but got ""
+PASS ¦/x (Blob/File)
+PASS ¦/x (Request/Response)
+PASS x/¦ (Blob/File)
+PASS x/¦ (Request/Response)
+FAIL x/x;¦=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;¦=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=¦;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¦\";bonus=x" but got ""
+FAIL x/x;x=¦;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¦\";bonus=x" but got ""
+FAIL x/x;x="¦";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¦\";bonus=x" but got ""
+FAIL x/x;x="¦";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¦\";bonus=x" but got ""
+PASS §/x (Blob/File)
+PASS §/x (Request/Response)
+PASS x/§ (Blob/File)
+PASS x/§ (Request/Response)
+FAIL x/x;§=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;§=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=§;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"§\";bonus=x" but got ""
+FAIL x/x;x=§;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"§\";bonus=x" but got ""
+FAIL x/x;x="§";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"§\";bonus=x" but got ""
+FAIL x/x;x="§";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"§\";bonus=x" but got ""
+PASS ¨/x (Blob/File)
+PASS ¨/x (Request/Response)
+PASS x/¨ (Blob/File)
+PASS x/¨ (Request/Response)
+FAIL x/x;¨=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;¨=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=¨;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¨\";bonus=x" but got ""
+FAIL x/x;x=¨;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¨\";bonus=x" but got ""
+FAIL x/x;x="¨";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¨\";bonus=x" but got ""
+FAIL x/x;x="¨";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¨\";bonus=x" but got ""
+PASS ©/x (Blob/File)
+PASS ©/x (Request/Response)
+PASS x/© (Blob/File)
+PASS x/© (Request/Response)
+FAIL x/x;©=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;©=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=©;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"©\";bonus=x" but got ""
+FAIL x/x;x=©;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"©\";bonus=x" but got ""
+FAIL x/x;x="©";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"©\";bonus=x" but got ""
+FAIL x/x;x="©";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"©\";bonus=x" but got ""
+PASS ª/x (Blob/File)
+PASS ª/x (Request/Response)
+PASS x/ª (Blob/File)
+PASS x/ª (Request/Response)
+FAIL x/x;ª=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;ª=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=ª;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ª\";bonus=x" but got ""
+FAIL x/x;x=ª;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ª\";bonus=x" but got ""
+FAIL x/x;x="ª";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ª\";bonus=x" but got ""
+FAIL x/x;x="ª";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ª\";bonus=x" but got ""
+PASS «/x (Blob/File)
+PASS «/x (Request/Response)
+PASS x/« (Blob/File)
+PASS x/« (Request/Response)
+FAIL x/x;«=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;«=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=«;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"«\";bonus=x" but got ""
+FAIL x/x;x=«;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"«\";bonus=x" but got ""
+FAIL x/x;x="«";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"«\";bonus=x" but got ""
+FAIL x/x;x="«";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"«\";bonus=x" but got ""
+PASS ¬/x (Blob/File)
+PASS ¬/x (Request/Response)
+PASS x/¬ (Blob/File)
+PASS x/¬ (Request/Response)
+FAIL x/x;¬=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;¬=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=¬;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¬\";bonus=x" but got ""
+FAIL x/x;x=¬;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¬\";bonus=x" but got ""
+FAIL x/x;x="¬";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¬\";bonus=x" but got ""
+FAIL x/x;x="¬";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¬\";bonus=x" but got ""
+PASS ­/x (Blob/File)
+PASS ­/x (Request/Response)
+PASS x/­ (Blob/File)
+PASS x/­ (Request/Response)
+FAIL x/x;­=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;­=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=­;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"­\";bonus=x" but got ""
+FAIL x/x;x=­;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"­\";bonus=x" but got ""
+FAIL x/x;x="­";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"­\";bonus=x" but got ""
+FAIL x/x;x="­";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"­\";bonus=x" but got ""
+PASS ®/x (Blob/File)
+PASS ®/x (Request/Response)
+PASS x/® (Blob/File)
+PASS x/® (Request/Response)
+FAIL x/x;®=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;®=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=®;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"®\";bonus=x" but got ""
+FAIL x/x;x=®;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"®\";bonus=x" but got ""
+FAIL x/x;x="®";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"®\";bonus=x" but got ""
+FAIL x/x;x="®";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"®\";bonus=x" but got ""
+PASS ¯/x (Blob/File)
+PASS ¯/x (Request/Response)
+PASS x/¯ (Blob/File)
+PASS x/¯ (Request/Response)
+FAIL x/x;¯=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;¯=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=¯;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¯\";bonus=x" but got ""
+FAIL x/x;x=¯;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¯\";bonus=x" but got ""
+FAIL x/x;x="¯";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¯\";bonus=x" but got ""
+FAIL x/x;x="¯";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¯\";bonus=x" but got ""
+PASS °/x (Blob/File)
+PASS °/x (Request/Response)
+PASS x/° (Blob/File)
+PASS x/° (Request/Response)
+FAIL x/x;°=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;°=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=°;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"°\";bonus=x" but got ""
+FAIL x/x;x=°;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"°\";bonus=x" but got ""
+FAIL x/x;x="°";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"°\";bonus=x" but got ""
+FAIL x/x;x="°";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"°\";bonus=x" but got ""
+PASS ±/x (Blob/File)
+PASS ±/x (Request/Response)
+PASS x/± (Blob/File)
+PASS x/± (Request/Response)
+FAIL x/x;±=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;±=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=±;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"±\";bonus=x" but got ""
+FAIL x/x;x=±;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"±\";bonus=x" but got ""
+FAIL x/x;x="±";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"±\";bonus=x" but got ""
+FAIL x/x;x="±";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"±\";bonus=x" but got ""
+PASS ²/x (Blob/File)
+PASS ²/x (Request/Response)
+PASS x/² (Blob/File)
+PASS x/² (Request/Response)
+FAIL x/x;²=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;²=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=²;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"²\";bonus=x" but got ""
+FAIL x/x;x=²;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"²\";bonus=x" but got ""
+FAIL x/x;x="²";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"²\";bonus=x" but got ""
+FAIL x/x;x="²";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"²\";bonus=x" but got ""
+PASS ³/x (Blob/File)
+PASS ³/x (Request/Response)
+PASS x/³ (Blob/File)
+PASS x/³ (Request/Response)
+FAIL x/x;³=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;³=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=³;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"³\";bonus=x" but got ""
+FAIL x/x;x=³;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"³\";bonus=x" but got ""
+FAIL x/x;x="³";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"³\";bonus=x" but got ""
+FAIL x/x;x="³";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"³\";bonus=x" but got ""
+PASS ´/x (Blob/File)
+PASS ´/x (Request/Response)
+PASS x/´ (Blob/File)
+PASS x/´ (Request/Response)
+FAIL x/x;´=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;´=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=´;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"´\";bonus=x" but got ""
+FAIL x/x;x=´;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"´\";bonus=x" but got ""
+FAIL x/x;x="´";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"´\";bonus=x" but got ""
+FAIL x/x;x="´";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"´\";bonus=x" but got ""
+PASS µ/x (Blob/File)
+PASS µ/x (Request/Response)
+PASS x/µ (Blob/File)
+PASS x/µ (Request/Response)
+FAIL x/x;µ=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;µ=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=µ;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"µ\";bonus=x" but got ""
+FAIL x/x;x=µ;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"µ\";bonus=x" but got ""
+FAIL x/x;x="µ";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"µ\";bonus=x" but got ""
+FAIL x/x;x="µ";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"µ\";bonus=x" but got ""
+PASS ¶/x (Blob/File)
+PASS ¶/x (Request/Response)
+PASS x/¶ (Blob/File)
+PASS x/¶ (Request/Response)
+FAIL x/x;¶=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;¶=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=¶;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¶\";bonus=x" but got ""
+FAIL x/x;x=¶;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¶\";bonus=x" but got ""
+FAIL x/x;x="¶";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¶\";bonus=x" but got ""
+FAIL x/x;x="¶";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¶\";bonus=x" but got ""
+PASS ·/x (Blob/File)
+PASS ·/x (Request/Response)
+PASS x/· (Blob/File)
+PASS x/· (Request/Response)
+FAIL x/x;·=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;·=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=·;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"·\";bonus=x" but got ""
+FAIL x/x;x=·;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"·\";bonus=x" but got ""
+FAIL x/x;x="·";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"·\";bonus=x" but got ""
+FAIL x/x;x="·";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"·\";bonus=x" but got ""
+PASS ¸/x (Blob/File)
+PASS ¸/x (Request/Response)
+PASS x/¸ (Blob/File)
+PASS x/¸ (Request/Response)
+FAIL x/x;¸=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;¸=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=¸;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¸\";bonus=x" but got ""
+FAIL x/x;x=¸;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¸\";bonus=x" but got ""
+FAIL x/x;x="¸";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¸\";bonus=x" but got ""
+FAIL x/x;x="¸";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¸\";bonus=x" but got ""
+PASS ¹/x (Blob/File)
+PASS ¹/x (Request/Response)
+PASS x/¹ (Blob/File)
+PASS x/¹ (Request/Response)
+FAIL x/x;¹=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;¹=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=¹;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¹\";bonus=x" but got ""
+FAIL x/x;x=¹;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¹\";bonus=x" but got ""
+FAIL x/x;x="¹";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¹\";bonus=x" but got ""
+FAIL x/x;x="¹";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¹\";bonus=x" but got ""
+PASS º/x (Blob/File)
+PASS º/x (Request/Response)
+PASS x/º (Blob/File)
+PASS x/º (Request/Response)
+FAIL x/x;º=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;º=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=º;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"º\";bonus=x" but got ""
+FAIL x/x;x=º;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"º\";bonus=x" but got ""
+FAIL x/x;x="º";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"º\";bonus=x" but got ""
+FAIL x/x;x="º";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"º\";bonus=x" but got ""
+PASS »/x (Blob/File)
+PASS »/x (Request/Response)
+PASS x/» (Blob/File)
+PASS x/» (Request/Response)
+FAIL x/x;»=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;»=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=»;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"»\";bonus=x" but got ""
+FAIL x/x;x=»;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"»\";bonus=x" but got ""
+FAIL x/x;x="»";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"»\";bonus=x" but got ""
+FAIL x/x;x="»";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"»\";bonus=x" but got ""
+PASS ¼/x (Blob/File)
+PASS ¼/x (Request/Response)
+PASS x/¼ (Blob/File)
+PASS x/¼ (Request/Response)
+FAIL x/x;¼=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;¼=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=¼;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¼\";bonus=x" but got ""
+FAIL x/x;x=¼;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¼\";bonus=x" but got ""
+FAIL x/x;x="¼";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¼\";bonus=x" but got ""
+FAIL x/x;x="¼";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¼\";bonus=x" but got ""
+PASS ½/x (Blob/File)
+PASS ½/x (Request/Response)
+PASS x/½ (Blob/File)
+PASS x/½ (Request/Response)
+FAIL x/x;½=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;½=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=½;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"½\";bonus=x" but got ""
+FAIL x/x;x=½;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"½\";bonus=x" but got ""
+FAIL x/x;x="½";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"½\";bonus=x" but got ""
+FAIL x/x;x="½";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"½\";bonus=x" but got ""
+PASS ¾/x (Blob/File)
+PASS ¾/x (Request/Response)
+PASS x/¾ (Blob/File)
+PASS x/¾ (Request/Response)
+FAIL x/x;¾=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;¾=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=¾;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¾\";bonus=x" but got ""
+FAIL x/x;x=¾;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¾\";bonus=x" but got ""
+FAIL x/x;x="¾";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¾\";bonus=x" but got ""
+FAIL x/x;x="¾";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¾\";bonus=x" but got ""
+PASS ¿/x (Blob/File)
+PASS ¿/x (Request/Response)
+PASS x/¿ (Blob/File)
+PASS x/¿ (Request/Response)
+FAIL x/x;¿=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;¿=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=¿;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¿\";bonus=x" but got ""
+FAIL x/x;x=¿;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¿\";bonus=x" but got ""
+FAIL x/x;x="¿";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"¿\";bonus=x" but got ""
+FAIL x/x;x="¿";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"¿\";bonus=x" but got ""
+PASS À/x (Blob/File)
+PASS À/x (Request/Response)
+PASS x/À (Blob/File)
+PASS x/À (Request/Response)
+FAIL x/x;À=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;À=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=À;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"À\";bonus=x" but got ""
+FAIL x/x;x=À;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"À\";bonus=x" but got ""
+FAIL x/x;x="À";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"À\";bonus=x" but got ""
+FAIL x/x;x="À";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"À\";bonus=x" but got ""
+PASS Á/x (Blob/File)
+PASS Á/x (Request/Response)
+PASS x/Á (Blob/File)
+PASS x/Á (Request/Response)
+FAIL x/x;Á=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Á=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Á;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Á\";bonus=x" but got ""
+FAIL x/x;x=Á;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Á\";bonus=x" but got ""
+FAIL x/x;x="Á";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Á\";bonus=x" but got ""
+FAIL x/x;x="Á";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Á\";bonus=x" but got ""
+PASS Â/x (Blob/File)
+PASS Â/x (Request/Response)
+PASS x/Â (Blob/File)
+PASS x/Â (Request/Response)
+FAIL x/x;Â=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Â=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Â;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Â\";bonus=x" but got ""
+FAIL x/x;x=Â;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Â\";bonus=x" but got ""
+FAIL x/x;x="Â";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Â\";bonus=x" but got ""
+FAIL x/x;x="Â";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Â\";bonus=x" but got ""
+PASS Ã/x (Blob/File)
+PASS Ã/x (Request/Response)
+PASS x/Ã (Blob/File)
+PASS x/Ã (Request/Response)
+FAIL x/x;Ã=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Ã=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Ã;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ã\";bonus=x" but got ""
+FAIL x/x;x=Ã;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ã\";bonus=x" but got ""
+FAIL x/x;x="Ã";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ã\";bonus=x" but got ""
+FAIL x/x;x="Ã";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ã\";bonus=x" but got ""
+PASS Ä/x (Blob/File)
+PASS Ä/x (Request/Response)
+PASS x/Ä (Blob/File)
+PASS x/Ä (Request/Response)
+FAIL x/x;Ä=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Ä=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Ä;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ä\";bonus=x" but got ""
+FAIL x/x;x=Ä;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ä\";bonus=x" but got ""
+FAIL x/x;x="Ä";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ä\";bonus=x" but got ""
+FAIL x/x;x="Ä";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ä\";bonus=x" but got ""
+PASS Å/x (Blob/File)
+PASS Å/x (Request/Response)
+PASS x/Å (Blob/File)
+PASS x/Å (Request/Response)
+FAIL x/x;Å=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Å=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Å;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Å\";bonus=x" but got ""
+FAIL x/x;x=Å;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Å\";bonus=x" but got ""
+FAIL x/x;x="Å";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Å\";bonus=x" but got ""
+FAIL x/x;x="Å";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Å\";bonus=x" but got ""
+PASS Æ/x (Blob/File)
+PASS Æ/x (Request/Response)
+PASS x/Æ (Blob/File)
+PASS x/Æ (Request/Response)
+FAIL x/x;Æ=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Æ=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Æ;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Æ\";bonus=x" but got ""
+FAIL x/x;x=Æ;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Æ\";bonus=x" but got ""
+FAIL x/x;x="Æ";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Æ\";bonus=x" but got ""
+FAIL x/x;x="Æ";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Æ\";bonus=x" but got ""
+PASS Ç/x (Blob/File)
+PASS Ç/x (Request/Response)
+PASS x/Ç (Blob/File)
+PASS x/Ç (Request/Response)
+FAIL x/x;Ç=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Ç=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Ç;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ç\";bonus=x" but got ""
+FAIL x/x;x=Ç;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ç\";bonus=x" but got ""
+FAIL x/x;x="Ç";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ç\";bonus=x" but got ""
+FAIL x/x;x="Ç";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ç\";bonus=x" but got ""
+PASS È/x (Blob/File)
+PASS È/x (Request/Response)
+PASS x/È (Blob/File)
+PASS x/È (Request/Response)
+FAIL x/x;È=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;È=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=È;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"È\";bonus=x" but got ""
+FAIL x/x;x=È;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"È\";bonus=x" but got ""
+FAIL x/x;x="È";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"È\";bonus=x" but got ""
+FAIL x/x;x="È";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"È\";bonus=x" but got ""
+PASS É/x (Blob/File)
+PASS É/x (Request/Response)
+PASS x/É (Blob/File)
+PASS x/É (Request/Response)
+FAIL x/x;É=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;É=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=É;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"É\";bonus=x" but got ""
+FAIL x/x;x=É;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"É\";bonus=x" but got ""
+FAIL x/x;x="É";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"É\";bonus=x" but got ""
+FAIL x/x;x="É";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"É\";bonus=x" but got ""
+PASS Ê/x (Blob/File)
+PASS Ê/x (Request/Response)
+PASS x/Ê (Blob/File)
+PASS x/Ê (Request/Response)
+FAIL x/x;Ê=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Ê=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Ê;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ê\";bonus=x" but got ""
+FAIL x/x;x=Ê;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ê\";bonus=x" but got ""
+FAIL x/x;x="Ê";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ê\";bonus=x" but got ""
+FAIL x/x;x="Ê";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ê\";bonus=x" but got ""
+PASS Ë/x (Blob/File)
+PASS Ë/x (Request/Response)
+PASS x/Ë (Blob/File)
+PASS x/Ë (Request/Response)
+FAIL x/x;Ë=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Ë=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Ë;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ë\";bonus=x" but got ""
+FAIL x/x;x=Ë;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ë\";bonus=x" but got ""
+FAIL x/x;x="Ë";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ë\";bonus=x" but got ""
+FAIL x/x;x="Ë";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ë\";bonus=x" but got ""
+PASS Ì/x (Blob/File)
+PASS Ì/x (Request/Response)
+PASS x/Ì (Blob/File)
+PASS x/Ì (Request/Response)
+FAIL x/x;Ì=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Ì=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Ì;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ì\";bonus=x" but got ""
+FAIL x/x;x=Ì;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ì\";bonus=x" but got ""
+FAIL x/x;x="Ì";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ì\";bonus=x" but got ""
+FAIL x/x;x="Ì";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ì\";bonus=x" but got ""
+PASS Í/x (Blob/File)
+PASS Í/x (Request/Response)
+PASS x/Í (Blob/File)
+PASS x/Í (Request/Response)
+FAIL x/x;Í=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Í=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Í;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Í\";bonus=x" but got ""
+FAIL x/x;x=Í;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Í\";bonus=x" but got ""
+FAIL x/x;x="Í";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Í\";bonus=x" but got ""
+FAIL x/x;x="Í";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Í\";bonus=x" but got ""
+PASS Î/x (Blob/File)
+PASS Î/x (Request/Response)
+PASS x/Î (Blob/File)
+PASS x/Î (Request/Response)
+FAIL x/x;Î=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Î=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Î;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Î\";bonus=x" but got ""
+FAIL x/x;x=Î;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Î\";bonus=x" but got ""
+FAIL x/x;x="Î";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Î\";bonus=x" but got ""
+FAIL x/x;x="Î";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Î\";bonus=x" but got ""
+PASS Ï/x (Blob/File)
+PASS Ï/x (Request/Response)
+PASS x/Ï (Blob/File)
+PASS x/Ï (Request/Response)
+FAIL x/x;Ï=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Ï=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Ï;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ï\";bonus=x" but got ""
+FAIL x/x;x=Ï;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ï\";bonus=x" but got ""
+FAIL x/x;x="Ï";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ï\";bonus=x" but got ""
+FAIL x/x;x="Ï";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ï\";bonus=x" but got ""
+PASS Ð/x (Blob/File)
+PASS Ð/x (Request/Response)
+PASS x/Ð (Blob/File)
+PASS x/Ð (Request/Response)
+FAIL x/x;Ð=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Ð=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Ð;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ð\";bonus=x" but got ""
+FAIL x/x;x=Ð;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ð\";bonus=x" but got ""
+FAIL x/x;x="Ð";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ð\";bonus=x" but got ""
+FAIL x/x;x="Ð";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ð\";bonus=x" but got ""
+PASS Ñ/x (Blob/File)
+PASS Ñ/x (Request/Response)
+PASS x/Ñ (Blob/File)
+PASS x/Ñ (Request/Response)
+FAIL x/x;Ñ=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Ñ=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Ñ;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ñ\";bonus=x" but got ""
+FAIL x/x;x=Ñ;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ñ\";bonus=x" but got ""
+FAIL x/x;x="Ñ";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ñ\";bonus=x" but got ""
+FAIL x/x;x="Ñ";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ñ\";bonus=x" but got ""
+PASS Ò/x (Blob/File)
+PASS Ò/x (Request/Response)
+PASS x/Ò (Blob/File)
+PASS x/Ò (Request/Response)
+FAIL x/x;Ò=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Ò=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Ò;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ò\";bonus=x" but got ""
+FAIL x/x;x=Ò;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ò\";bonus=x" but got ""
+FAIL x/x;x="Ò";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ò\";bonus=x" but got ""
+FAIL x/x;x="Ò";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ò\";bonus=x" but got ""
+PASS Ó/x (Blob/File)
+PASS Ó/x (Request/Response)
+PASS x/Ó (Blob/File)
+PASS x/Ó (Request/Response)
+FAIL x/x;Ó=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Ó=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Ó;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ó\";bonus=x" but got ""
+FAIL x/x;x=Ó;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ó\";bonus=x" but got ""
+FAIL x/x;x="Ó";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ó\";bonus=x" but got ""
+FAIL x/x;x="Ó";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ó\";bonus=x" but got ""
+PASS Ô/x (Blob/File)
+PASS Ô/x (Request/Response)
+PASS x/Ô (Blob/File)
+PASS x/Ô (Request/Response)
+FAIL x/x;Ô=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Ô=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Ô;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ô\";bonus=x" but got ""
+FAIL x/x;x=Ô;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ô\";bonus=x" but got ""
+FAIL x/x;x="Ô";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ô\";bonus=x" but got ""
+FAIL x/x;x="Ô";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ô\";bonus=x" but got ""
+PASS Õ/x (Blob/File)
+PASS Õ/x (Request/Response)
+PASS x/Õ (Blob/File)
+PASS x/Õ (Request/Response)
+FAIL x/x;Õ=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Õ=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Õ;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Õ\";bonus=x" but got ""
+FAIL x/x;x=Õ;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Õ\";bonus=x" but got ""
+FAIL x/x;x="Õ";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Õ\";bonus=x" but got ""
+FAIL x/x;x="Õ";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Õ\";bonus=x" but got ""
+PASS Ö/x (Blob/File)
+PASS Ö/x (Request/Response)
+PASS x/Ö (Blob/File)
+PASS x/Ö (Request/Response)
+FAIL x/x;Ö=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Ö=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Ö;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ö\";bonus=x" but got ""
+FAIL x/x;x=Ö;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ö\";bonus=x" but got ""
+FAIL x/x;x="Ö";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ö\";bonus=x" but got ""
+FAIL x/x;x="Ö";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ö\";bonus=x" but got ""
+PASS ×/x (Blob/File)
+PASS ×/x (Request/Response)
+PASS x/× (Blob/File)
+PASS x/× (Request/Response)
+FAIL x/x;×=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;×=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=×;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"×\";bonus=x" but got ""
+FAIL x/x;x=×;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"×\";bonus=x" but got ""
+FAIL x/x;x="×";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"×\";bonus=x" but got ""
+FAIL x/x;x="×";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"×\";bonus=x" but got ""
+PASS Ø/x (Blob/File)
+PASS Ø/x (Request/Response)
+PASS x/Ø (Blob/File)
+PASS x/Ø (Request/Response)
+FAIL x/x;Ø=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Ø=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Ø;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ø\";bonus=x" but got ""
+FAIL x/x;x=Ø;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ø\";bonus=x" but got ""
+FAIL x/x;x="Ø";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ø\";bonus=x" but got ""
+FAIL x/x;x="Ø";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ø\";bonus=x" but got ""
+PASS Ù/x (Blob/File)
+PASS Ù/x (Request/Response)
+PASS x/Ù (Blob/File)
+PASS x/Ù (Request/Response)
+FAIL x/x;Ù=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Ù=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Ù;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ù\";bonus=x" but got ""
+FAIL x/x;x=Ù;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ù\";bonus=x" but got ""
+FAIL x/x;x="Ù";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ù\";bonus=x" but got ""
+FAIL x/x;x="Ù";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ù\";bonus=x" but got ""
+PASS Ú/x (Blob/File)
+PASS Ú/x (Request/Response)
+PASS x/Ú (Blob/File)
+PASS x/Ú (Request/Response)
+FAIL x/x;Ú=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Ú=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Ú;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ú\";bonus=x" but got ""
+FAIL x/x;x=Ú;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ú\";bonus=x" but got ""
+FAIL x/x;x="Ú";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ú\";bonus=x" but got ""
+FAIL x/x;x="Ú";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ú\";bonus=x" but got ""
+PASS Û/x (Blob/File)
+PASS Û/x (Request/Response)
+PASS x/Û (Blob/File)
+PASS x/Û (Request/Response)
+FAIL x/x;Û=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Û=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Û;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Û\";bonus=x" but got ""
+FAIL x/x;x=Û;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Û\";bonus=x" but got ""
+FAIL x/x;x="Û";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Û\";bonus=x" but got ""
+FAIL x/x;x="Û";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Û\";bonus=x" but got ""
+PASS Ü/x (Blob/File)
+PASS Ü/x (Request/Response)
+PASS x/Ü (Blob/File)
+PASS x/Ü (Request/Response)
+FAIL x/x;Ü=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Ü=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Ü;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ü\";bonus=x" but got ""
+FAIL x/x;x=Ü;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ü\";bonus=x" but got ""
+FAIL x/x;x="Ü";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ü\";bonus=x" but got ""
+FAIL x/x;x="Ü";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ü\";bonus=x" but got ""
+PASS Ý/x (Blob/File)
+PASS Ý/x (Request/Response)
+PASS x/Ý (Blob/File)
+PASS x/Ý (Request/Response)
+FAIL x/x;Ý=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Ý=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Ý;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ý\";bonus=x" but got ""
+FAIL x/x;x=Ý;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ý\";bonus=x" but got ""
+FAIL x/x;x="Ý";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Ý\";bonus=x" but got ""
+FAIL x/x;x="Ý";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Ý\";bonus=x" but got ""
+PASS Þ/x (Blob/File)
+PASS Þ/x (Request/Response)
+PASS x/Þ (Blob/File)
+PASS x/Þ (Request/Response)
+FAIL x/x;Þ=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;Þ=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=Þ;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Þ\";bonus=x" but got ""
+FAIL x/x;x=Þ;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Þ\";bonus=x" but got ""
+FAIL x/x;x="Þ";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"Þ\";bonus=x" but got ""
+FAIL x/x;x="Þ";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"Þ\";bonus=x" but got ""
+PASS ß/x (Blob/File)
+PASS ß/x (Request/Response)
+PASS x/ß (Blob/File)
+PASS x/ß (Request/Response)
+FAIL x/x;ß=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;ß=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=ß;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ß\";bonus=x" but got ""
+FAIL x/x;x=ß;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ß\";bonus=x" but got ""
+FAIL x/x;x="ß";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ß\";bonus=x" but got ""
+FAIL x/x;x="ß";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ß\";bonus=x" but got ""
+PASS à/x (Blob/File)
+PASS à/x (Request/Response)
+PASS x/à (Blob/File)
+PASS x/à (Request/Response)
+FAIL x/x;à=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;à=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=à;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"à\";bonus=x" but got ""
+FAIL x/x;x=à;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"à\";bonus=x" but got ""
+FAIL x/x;x="à";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"à\";bonus=x" but got ""
+FAIL x/x;x="à";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"à\";bonus=x" but got ""
+PASS á/x (Blob/File)
+PASS á/x (Request/Response)
+PASS x/á (Blob/File)
+PASS x/á (Request/Response)
+FAIL x/x;á=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;á=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=á;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"á\";bonus=x" but got ""
+FAIL x/x;x=á;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"á\";bonus=x" but got ""
+FAIL x/x;x="á";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"á\";bonus=x" but got ""
+FAIL x/x;x="á";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"á\";bonus=x" but got ""
+PASS â/x (Blob/File)
+PASS â/x (Request/Response)
+PASS x/â (Blob/File)
+PASS x/â (Request/Response)
+FAIL x/x;â=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;â=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=â;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"â\";bonus=x" but got ""
+FAIL x/x;x=â;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"â\";bonus=x" but got ""
+FAIL x/x;x="â";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"â\";bonus=x" but got ""
+FAIL x/x;x="â";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"â\";bonus=x" but got ""
+PASS ã/x (Blob/File)
+PASS ã/x (Request/Response)
+PASS x/ã (Blob/File)
+PASS x/ã (Request/Response)
+FAIL x/x;ã=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;ã=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=ã;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ã\";bonus=x" but got ""
+FAIL x/x;x=ã;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ã\";bonus=x" but got ""
+FAIL x/x;x="ã";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ã\";bonus=x" but got ""
+FAIL x/x;x="ã";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ã\";bonus=x" but got ""
+PASS ä/x (Blob/File)
+PASS ä/x (Request/Response)
+PASS x/ä (Blob/File)
+PASS x/ä (Request/Response)
+FAIL x/x;ä=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;ä=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=ä;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ä\";bonus=x" but got ""
+FAIL x/x;x=ä;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ä\";bonus=x" but got ""
+FAIL x/x;x="ä";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ä\";bonus=x" but got ""
+FAIL x/x;x="ä";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ä\";bonus=x" but got ""
+PASS å/x (Blob/File)
+PASS å/x (Request/Response)
+PASS x/å (Blob/File)
+PASS x/å (Request/Response)
+FAIL x/x;å=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;å=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=å;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"å\";bonus=x" but got ""
+FAIL x/x;x=å;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"å\";bonus=x" but got ""
+FAIL x/x;x="å";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"å\";bonus=x" but got ""
+FAIL x/x;x="å";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"å\";bonus=x" but got ""
+PASS æ/x (Blob/File)
+PASS æ/x (Request/Response)
+PASS x/æ (Blob/File)
+PASS x/æ (Request/Response)
+FAIL x/x;æ=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;æ=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=æ;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"æ\";bonus=x" but got ""
+FAIL x/x;x=æ;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"æ\";bonus=x" but got ""
+FAIL x/x;x="æ";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"æ\";bonus=x" but got ""
+FAIL x/x;x="æ";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"æ\";bonus=x" but got ""
+PASS ç/x (Blob/File)
+PASS ç/x (Request/Response)
+PASS x/ç (Blob/File)
+PASS x/ç (Request/Response)
+FAIL x/x;ç=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;ç=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=ç;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ç\";bonus=x" but got ""
+FAIL x/x;x=ç;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ç\";bonus=x" but got ""
+FAIL x/x;x="ç";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ç\";bonus=x" but got ""
+FAIL x/x;x="ç";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ç\";bonus=x" but got ""
+PASS è/x (Blob/File)
+PASS è/x (Request/Response)
+PASS x/è (Blob/File)
+PASS x/è (Request/Response)
+FAIL x/x;è=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;è=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=è;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"è\";bonus=x" but got ""
+FAIL x/x;x=è;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"è\";bonus=x" but got ""
+FAIL x/x;x="è";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"è\";bonus=x" but got ""
+FAIL x/x;x="è";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"è\";bonus=x" but got ""
+PASS é/x (Blob/File)
+PASS é/x (Request/Response)
+PASS x/é (Blob/File)
+PASS x/é (Request/Response)
+FAIL x/x;é=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;é=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=é;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"é\";bonus=x" but got ""
+FAIL x/x;x=é;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"é\";bonus=x" but got ""
+FAIL x/x;x="é";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"é\";bonus=x" but got ""
+FAIL x/x;x="é";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"é\";bonus=x" but got ""
+PASS ê/x (Blob/File)
+PASS ê/x (Request/Response)
+PASS x/ê (Blob/File)
+PASS x/ê (Request/Response)
+FAIL x/x;ê=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;ê=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=ê;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ê\";bonus=x" but got ""
+FAIL x/x;x=ê;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ê\";bonus=x" but got ""
+FAIL x/x;x="ê";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ê\";bonus=x" but got ""
+FAIL x/x;x="ê";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ê\";bonus=x" but got ""
+PASS ë/x (Blob/File)
+PASS ë/x (Request/Response)
+PASS x/ë (Blob/File)
+PASS x/ë (Request/Response)
+FAIL x/x;ë=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;ë=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=ë;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ë\";bonus=x" but got ""
+FAIL x/x;x=ë;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ë\";bonus=x" but got ""
+FAIL x/x;x="ë";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ë\";bonus=x" but got ""
+FAIL x/x;x="ë";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ë\";bonus=x" but got ""
+PASS ì/x (Blob/File)
+PASS ì/x (Request/Response)
+PASS x/ì (Blob/File)
+PASS x/ì (Request/Response)
+FAIL x/x;ì=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;ì=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=ì;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ì\";bonus=x" but got ""
+FAIL x/x;x=ì;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ì\";bonus=x" but got ""
+FAIL x/x;x="ì";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ì\";bonus=x" but got ""
+FAIL x/x;x="ì";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ì\";bonus=x" but got ""
+PASS í/x (Blob/File)
+PASS í/x (Request/Response)
+PASS x/í (Blob/File)
+PASS x/í (Request/Response)
+FAIL x/x;í=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;í=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=í;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"í\";bonus=x" but got ""
+FAIL x/x;x=í;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"í\";bonus=x" but got ""
+FAIL x/x;x="í";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"í\";bonus=x" but got ""
+FAIL x/x;x="í";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"í\";bonus=x" but got ""
+PASS î/x (Blob/File)
+PASS î/x (Request/Response)
+PASS x/î (Blob/File)
+PASS x/î (Request/Response)
+FAIL x/x;î=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;î=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=î;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"î\";bonus=x" but got ""
+FAIL x/x;x=î;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"î\";bonus=x" but got ""
+FAIL x/x;x="î";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"î\";bonus=x" but got ""
+FAIL x/x;x="î";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"î\";bonus=x" but got ""
+PASS ï/x (Blob/File)
+PASS ï/x (Request/Response)
+PASS x/ï (Blob/File)
+PASS x/ï (Request/Response)
+FAIL x/x;ï=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;ï=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=ï;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ï\";bonus=x" but got ""
+FAIL x/x;x=ï;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ï\";bonus=x" but got ""
+FAIL x/x;x="ï";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ï\";bonus=x" but got ""
+FAIL x/x;x="ï";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ï\";bonus=x" but got ""
+PASS ð/x (Blob/File)
+PASS ð/x (Request/Response)
+PASS x/ð (Blob/File)
+PASS x/ð (Request/Response)
+FAIL x/x;ð=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;ð=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=ð;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ð\";bonus=x" but got ""
+FAIL x/x;x=ð;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ð\";bonus=x" but got ""
+FAIL x/x;x="ð";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ð\";bonus=x" but got ""
+FAIL x/x;x="ð";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ð\";bonus=x" but got ""
+PASS ñ/x (Blob/File)
+PASS ñ/x (Request/Response)
+PASS x/ñ (Blob/File)
+PASS x/ñ (Request/Response)
+FAIL x/x;ñ=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;ñ=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=ñ;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ñ\";bonus=x" but got ""
+FAIL x/x;x=ñ;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ñ\";bonus=x" but got ""
+FAIL x/x;x="ñ";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ñ\";bonus=x" but got ""
+FAIL x/x;x="ñ";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ñ\";bonus=x" but got ""
+PASS ò/x (Blob/File)
+PASS ò/x (Request/Response)
+PASS x/ò (Blob/File)
+PASS x/ò (Request/Response)
+FAIL x/x;ò=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;ò=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=ò;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ò\";bonus=x" but got ""
+FAIL x/x;x=ò;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ò\";bonus=x" but got ""
+FAIL x/x;x="ò";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ò\";bonus=x" but got ""
+FAIL x/x;x="ò";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ò\";bonus=x" but got ""
+PASS ó/x (Blob/File)
+PASS ó/x (Request/Response)
+PASS x/ó (Blob/File)
+PASS x/ó (Request/Response)
+FAIL x/x;ó=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;ó=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=ó;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ó\";bonus=x" but got ""
+FAIL x/x;x=ó;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ó\";bonus=x" but got ""
+FAIL x/x;x="ó";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ó\";bonus=x" but got ""
+FAIL x/x;x="ó";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ó\";bonus=x" but got ""
+PASS ô/x (Blob/File)
+PASS ô/x (Request/Response)
+PASS x/ô (Blob/File)
+PASS x/ô (Request/Response)
+FAIL x/x;ô=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;ô=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=ô;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ô\";bonus=x" but got ""
+FAIL x/x;x=ô;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ô\";bonus=x" but got ""
+FAIL x/x;x="ô";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ô\";bonus=x" but got ""
+FAIL x/x;x="ô";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ô\";bonus=x" but got ""
+PASS õ/x (Blob/File)
+PASS õ/x (Request/Response)
+PASS x/õ (Blob/File)
+PASS x/õ (Request/Response)
+FAIL x/x;õ=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;õ=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=õ;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"õ\";bonus=x" but got ""
+FAIL x/x;x=õ;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"õ\";bonus=x" but got ""
+FAIL x/x;x="õ";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"õ\";bonus=x" but got ""
+FAIL x/x;x="õ";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"õ\";bonus=x" but got ""
+PASS ö/x (Blob/File)
+PASS ö/x (Request/Response)
+PASS x/ö (Blob/File)
+PASS x/ö (Request/Response)
+FAIL x/x;ö=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;ö=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=ö;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ö\";bonus=x" but got ""
+FAIL x/x;x=ö;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ö\";bonus=x" but got ""
+FAIL x/x;x="ö";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ö\";bonus=x" but got ""
+FAIL x/x;x="ö";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ö\";bonus=x" but got ""
+PASS ÷/x (Blob/File)
+PASS ÷/x (Request/Response)
+PASS x/÷ (Blob/File)
+PASS x/÷ (Request/Response)
+FAIL x/x;÷=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;÷=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=÷;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"÷\";bonus=x" but got ""
+FAIL x/x;x=÷;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"÷\";bonus=x" but got ""
+FAIL x/x;x="÷";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"÷\";bonus=x" but got ""
+FAIL x/x;x="÷";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"÷\";bonus=x" but got ""
+PASS ø/x (Blob/File)
+PASS ø/x (Request/Response)
+PASS x/ø (Blob/File)
+PASS x/ø (Request/Response)
+FAIL x/x;ø=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;ø=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=ø;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ø\";bonus=x" but got ""
+FAIL x/x;x=ø;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ø\";bonus=x" but got ""
+FAIL x/x;x="ø";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ø\";bonus=x" but got ""
+FAIL x/x;x="ø";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ø\";bonus=x" but got ""
+PASS ù/x (Blob/File)
+PASS ù/x (Request/Response)
+PASS x/ù (Blob/File)
+PASS x/ù (Request/Response)
+FAIL x/x;ù=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;ù=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=ù;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ù\";bonus=x" but got ""
+FAIL x/x;x=ù;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ù\";bonus=x" but got ""
+FAIL x/x;x="ù";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ù\";bonus=x" but got ""
+FAIL x/x;x="ù";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ù\";bonus=x" but got ""
+PASS ú/x (Blob/File)
+PASS ú/x (Request/Response)
+PASS x/ú (Blob/File)
+PASS x/ú (Request/Response)
+FAIL x/x;ú=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;ú=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=ú;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ú\";bonus=x" but got ""
+FAIL x/x;x=ú;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ú\";bonus=x" but got ""
+FAIL x/x;x="ú";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ú\";bonus=x" but got ""
+FAIL x/x;x="ú";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ú\";bonus=x" but got ""
+PASS û/x (Blob/File)
+PASS û/x (Request/Response)
+PASS x/û (Blob/File)
+PASS x/û (Request/Response)
+FAIL x/x;û=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;û=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=û;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"û\";bonus=x" but got ""
+FAIL x/x;x=û;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"û\";bonus=x" but got ""
+FAIL x/x;x="û";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"û\";bonus=x" but got ""
+FAIL x/x;x="û";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"û\";bonus=x" but got ""
+PASS ü/x (Blob/File)
+PASS ü/x (Request/Response)
+PASS x/ü (Blob/File)
+PASS x/ü (Request/Response)
+FAIL x/x;ü=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;ü=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=ü;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ü\";bonus=x" but got ""
+FAIL x/x;x=ü;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ü\";bonus=x" but got ""
+FAIL x/x;x="ü";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ü\";bonus=x" but got ""
+FAIL x/x;x="ü";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ü\";bonus=x" but got ""
+PASS ý/x (Blob/File)
+PASS ý/x (Request/Response)
+PASS x/ý (Blob/File)
+PASS x/ý (Request/Response)
+FAIL x/x;ý=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;ý=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=ý;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ý\";bonus=x" but got ""
+FAIL x/x;x=ý;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ý\";bonus=x" but got ""
+FAIL x/x;x="ý";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ý\";bonus=x" but got ""
+FAIL x/x;x="ý";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ý\";bonus=x" but got ""
+PASS þ/x (Blob/File)
+PASS þ/x (Request/Response)
+PASS x/þ (Blob/File)
+PASS x/þ (Request/Response)
+FAIL x/x;þ=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;þ=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=þ;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"þ\";bonus=x" but got ""
+FAIL x/x;x=þ;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"þ\";bonus=x" but got ""
+FAIL x/x;x="þ";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"þ\";bonus=x" but got ""
+FAIL x/x;x="þ";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"þ\";bonus=x" but got ""
+PASS ÿ/x (Blob/File)
+PASS ÿ/x (Request/Response)
+PASS x/ÿ (Blob/File)
+PASS x/ÿ (Request/Response)
+FAIL x/x;ÿ=x;bonus=x (Blob/File) assert_equals: Blob expected "x/x;bonus=x" but got ""
+FAIL x/x;ÿ=x;bonus=x (Request/Response) assert_equals: expected "x/x;bonus=x" but got ""
+FAIL x/x;x=ÿ;bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ÿ\";bonus=x" but got ""
+FAIL x/x;x=ÿ;bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ÿ\";bonus=x" but got ""
+FAIL x/x;x="ÿ";bonus=x (Blob/File) assert_equals: Blob expected "x/x;x=\"ÿ\";bonus=x" but got ""
+FAIL x/x;x="ÿ";bonus=x (Request/Response) assert_equals: expected "x/x;x=\"ÿ\";bonus=x" but got ""
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/fast/harness/results.html b/third_party/WebKit/LayoutTests/fast/harness/results.html
index 71188ab..cddc970 100644
--- a/third_party/WebKit/LayoutTests/fast/harness/results.html
+++ b/third_party/WebKit/LayoutTests/fast/harness/results.html
@@ -527,7 +527,7 @@
     }
     let html = `
       <div class='expect' tabindex='0' data-id='${test.expectId}'><div class='details'></div>${Report.printFlag(test)}${bug}
-        ${pathParser.dir}/<a target='test' tabindex='-1' href='${pathParser.testHref}'>${pathParser.file}</a>
+        ${pathParser.dir}<a target='test' tabindex='-1' href='${pathParser.testHref}'>${pathParser.file}</a>
         [ ${status} ]
     </div>
     `;
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptController.cpp b/third_party/WebKit/Source/bindings/core/v8/ScriptController.cpp
index de29490d..36a7fb0 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptController.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptController.cpp
@@ -113,8 +113,7 @@
                                          source.StartPosition()));
   v8::Local<v8::Value> result;
   {
-    CachedMetadataHandler* cache_handler =
-        source.GetResource() ? source.GetResource()->CacheHandler() : nullptr;
+    CachedMetadataHandler* cache_handler = source.CacheHandler();
 
     V8CacheOptions v8_cache_options =
         CacheOptions(cache_handler, GetFrame()->GetSettings());
@@ -133,8 +132,8 @@
     v8::Local<v8::Script> script;
 
     if (!V8ScriptRunner::CompileScript(ScriptState::From(context), source,
-                                       cache_handler, access_control_status,
-                                       v8_cache_options, referrer_info)
+                                       access_control_status, v8_cache_options,
+                                       referrer_info)
              .ToLocal(&script))
       return result;
 
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptSourceCode.cpp b/third_party/WebKit/Source/bindings/core/v8/ScriptSourceCode.cpp
index 573ba67..54d2f07 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptSourceCode.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptSourceCode.cpp
@@ -4,6 +4,8 @@
 
 #include "bindings/core/v8/ScriptSourceCode.h"
 
+#include "core/loader/resource/ScriptResource.h"
+
 namespace blink {
 
 namespace {
@@ -49,9 +51,11 @@
 ScriptSourceCode::ScriptSourceCode(
     const String& source,
     ScriptSourceLocationType source_location_type,
+    CachedMetadataHandler* cache_handler,
     const KURL& url,
     const TextPosition& start_position)
     : source_(TreatNullSourceAsEmpty(source)),
+      cache_handler_(cache_handler),
       url_(StripFragmentIdentifier(url)),
       start_position_(start_position),
       source_location_type_(source_location_type) {
@@ -62,7 +66,7 @@
 ScriptSourceCode::ScriptSourceCode(ScriptStreamer* streamer,
                                    ScriptResource* resource)
     : source_(TreatNullSourceAsEmpty(resource->SourceText())),
-      resource_(resource),
+      cache_handler_(resource->CacheHandler()),
       streamer_(streamer),
       url_(StripFragmentIdentifier(resource->GetResponse().Url())),
       source_map_url_(SourceMapUrlFromResponse(resource->GetResponse())),
@@ -72,7 +76,7 @@
 ScriptSourceCode::~ScriptSourceCode() {}
 
 void ScriptSourceCode::Trace(blink::Visitor* visitor) {
-  visitor->Trace(resource_);
+  visitor->Trace(cache_handler_);
   visitor->Trace(streamer_);
 }
 
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptSourceCode.h b/third_party/WebKit/Source/bindings/core/v8/ScriptSourceCode.h
index 30e8775..36b301b 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptSourceCode.h
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptSourceCode.h
@@ -34,7 +34,6 @@
 #include "bindings/core/v8/ScriptSourceLocationType.h"
 #include "bindings/core/v8/ScriptStreamer.h"
 #include "core/CoreExport.h"
-#include "core/loader/resource/ScriptResource.h"
 #include "platform/heap/Handle.h"
 #include "platform/weborigin/KURL.h"
 #include "platform/wtf/text/TextPosition.h"
@@ -42,6 +41,9 @@
 
 namespace blink {
 
+class ScriptResource;
+class CachedMetadataHandler;
+
 class CORE_EXPORT ScriptSourceCode final {
   DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
 
@@ -50,6 +52,7 @@
   ScriptSourceCode(
       const String& source,
       ScriptSourceLocationType = ScriptSourceLocationType::kUnknown,
+      CachedMetadataHandler* cache_handler = nullptr,
       const KURL& = KURL(),
       const TextPosition& start_position = TextPosition::MinimumPosition());
 
@@ -67,7 +70,7 @@
   bool IsNull() const { return source_.IsNull(); }
 
   const String& Source() const { return source_; }
-  ScriptResource* GetResource() const { return resource_; }
+  CachedMetadataHandler* CacheHandler() const { return cache_handler_; }
   KURL Url() const;
   int StartLine() const { return start_position_.line_.OneBasedInt(); }
   const TextPosition& StartPosition() const { return start_position_; }
@@ -80,7 +83,7 @@
 
  private:
   const String source_;
-  Member<ScriptResource> resource_;
+  Member<CachedMetadataHandler> cache_handler_;
   Member<ScriptStreamer> streamer_;
   const KURL url_;
   const String source_map_url_;
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptStreamerTest.cpp b/third_party/WebKit/Source/bindings/core/v8/ScriptStreamerTest.cpp
index f80bc36..f7287908 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptStreamerTest.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptStreamerTest.cpp
@@ -153,10 +153,8 @@
   v8::TryCatch try_catch(scope.GetIsolate());
   v8::Local<v8::Script> script;
   EXPECT_TRUE(V8ScriptRunner::CompileScript(
-                  scope.GetScriptState(), source_code,
-                  source_code.GetResource()->CacheHandler(),
-                  kSharableCrossOrigin, kV8CacheOptionsDefault,
-                  ReferrerScriptInfo())
+                  scope.GetScriptState(), source_code, kSharableCrossOrigin,
+                  kV8CacheOptionsDefault, ReferrerScriptInfo())
                   .ToLocal(&script));
   EXPECT_FALSE(try_catch.HasCaught());
 }
@@ -195,10 +193,8 @@
   v8::TryCatch try_catch(scope.GetIsolate());
   v8::Local<v8::Script> script;
   EXPECT_FALSE(V8ScriptRunner::CompileScript(
-                   scope.GetScriptState(), source_code,
-                   source_code.GetResource()->CacheHandler(),
-                   kSharableCrossOrigin, kV8CacheOptionsDefault,
-                   ReferrerScriptInfo())
+                   scope.GetScriptState(), source_code, kSharableCrossOrigin,
+                   kV8CacheOptionsDefault, ReferrerScriptInfo())
                    .ToLocal(&script));
   EXPECT_TRUE(try_catch.HasCaught());
 }
@@ -350,10 +346,8 @@
   v8::TryCatch try_catch(scope.GetIsolate());
   v8::Local<v8::Script> script;
   EXPECT_TRUE(V8ScriptRunner::CompileScript(
-                  scope.GetScriptState(), source_code,
-                  source_code.GetResource()->CacheHandler(),
-                  kSharableCrossOrigin, kV8CacheOptionsDefault,
-                  ReferrerScriptInfo())
+                  scope.GetScriptState(), source_code, kSharableCrossOrigin,
+                  kV8CacheOptionsDefault, ReferrerScriptInfo())
                   .ToLocal(&script));
   EXPECT_FALSE(try_catch.HasCaught());
 }
@@ -389,10 +383,8 @@
   v8::TryCatch try_catch(scope.GetIsolate());
   v8::Local<v8::Script> script;
   EXPECT_TRUE(V8ScriptRunner::CompileScript(
-                  scope.GetScriptState(), source_code,
-                  source_code.GetResource()->CacheHandler(),
-                  kSharableCrossOrigin, kV8CacheOptionsDefault,
-                  ReferrerScriptInfo())
+                  scope.GetScriptState(), source_code, kSharableCrossOrigin,
+                  kV8CacheOptionsDefault, ReferrerScriptInfo())
                   .ToLocal(&script));
   EXPECT_FALSE(try_catch.HasCaught());
 }
@@ -429,10 +421,8 @@
   v8::TryCatch try_catch(scope.GetIsolate());
   v8::Local<v8::Script> script;
   EXPECT_TRUE(V8ScriptRunner::CompileScript(
-                  scope.GetScriptState(), source_code,
-                  source_code.GetResource()->CacheHandler(),
-                  kSharableCrossOrigin, kV8CacheOptionsDefault,
-                  ReferrerScriptInfo())
+                  scope.GetScriptState(), source_code, kSharableCrossOrigin,
+                  kV8CacheOptionsDefault, ReferrerScriptInfo())
                   .ToLocal(&script));
   EXPECT_FALSE(try_catch.HasCaught());
 }
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8ScriptRunner.cpp b/third_party/WebKit/Source/bindings/core/v8/V8ScriptRunner.cpp
index 8c51a14e..e7dfef8 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V8ScriptRunner.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/V8ScriptRunner.cpp
@@ -389,7 +389,6 @@
 v8::MaybeLocal<v8::Script> V8ScriptRunner::CompileScript(
     ScriptState* script_state,
     const ScriptSourceCode& source,
-    CachedMetadataHandler* cache_metadata_handler,
     AccessControlStatus access_control_status,
     V8CacheOptions v8_cache_options,
     const ReferrerScriptInfo& referrer_info) {
@@ -402,7 +401,7 @@
   return CompileScript(script_state, V8String(isolate, source.Source()),
                        source.Url(), source.SourceMapUrl(),
                        source.StartPosition(), source.SourceLocationType(),
-                       source.Streamer(), cache_metadata_handler,
+                       source.Streamer(), source.CacheHandler(),
                        access_control_status, v8_cache_options, referrer_info);
 }
 
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8ScriptRunner.h b/third_party/WebKit/Source/bindings/core/v8/V8ScriptRunner.h
index 99755a2..cd0db2f 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V8ScriptRunner.h
+++ b/third_party/WebKit/Source/bindings/core/v8/V8ScriptRunner.h
@@ -67,7 +67,6 @@
   // CachedMetadataHandler is set when metadata caching is supported.
   static v8::MaybeLocal<v8::Script> CompileScript(ScriptState*,
                                                   const ScriptSourceCode&,
-                                                  CachedMetadataHandler*,
                                                   AccessControlStatus,
                                                   V8CacheOptions,
                                                   const ReferrerScriptInfo&);
diff --git a/third_party/WebKit/Source/bindings/core/v8/WorkerOrWorkletScriptController.cpp b/third_party/WebKit/Source/bindings/core/v8/WorkerOrWorkletScriptController.cpp
index 8c9c887..e851064b 100644
--- a/third_party/WebKit/Source/bindings/core/v8/WorkerOrWorkletScriptController.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/WorkerOrWorkletScriptController.cpp
@@ -254,7 +254,6 @@
 
 ScriptValue WorkerOrWorkletScriptController::EvaluateInternal(
     const ScriptSourceCode& source_code,
-    CachedMetadataHandler* cache_handler,
     V8CacheOptions v8_cache_options) {
   TRACE_EVENT1("devtools.timeline", "EvaluateScript", "data",
                InspectorEvaluateScriptEvent::Data(nullptr, source_code.Url(),
@@ -273,8 +272,8 @@
   // - a work{er,let} script is always "not parser inserted".
   ReferrerScriptInfo referrer_info;
   if (V8ScriptRunner::CompileScript(script_state_.get(), source_code,
-                                    cache_handler, kSharableCrossOrigin,
-                                    v8_cache_options, referrer_info)
+                                    kSharableCrossOrigin, v8_cache_options,
+                                    referrer_info)
           .ToLocal(&compiled_script))
     maybe_result = V8ScriptRunner::RunCompiledScript(isolate_, compiled_script,
                                                      global_scope_);
@@ -307,13 +306,12 @@
 bool WorkerOrWorkletScriptController::Evaluate(
     const ScriptSourceCode& source_code,
     ErrorEvent** error_event,
-    CachedMetadataHandler* cache_handler,
     V8CacheOptions v8_cache_options) {
   if (IsExecutionForbidden())
     return false;
 
   ExecutionState state(this);
-  EvaluateInternal(source_code, cache_handler, v8_cache_options);
+  EvaluateInternal(source_code, v8_cache_options);
   if (IsExecutionForbidden())
     return false;
 
@@ -357,7 +355,7 @@
 ScriptValue WorkerOrWorkletScriptController::EvaluateAndReturnValueForTest(
     const ScriptSourceCode& source_code) {
   ExecutionState state(this);
-  return EvaluateInternal(source_code, nullptr, kV8CacheOptionsDefault);
+  return EvaluateInternal(source_code, kV8CacheOptionsDefault);
 }
 
 void WorkerOrWorkletScriptController::ForbidExecution() {
diff --git a/third_party/WebKit/Source/bindings/core/v8/WorkerOrWorkletScriptController.h b/third_party/WebKit/Source/bindings/core/v8/WorkerOrWorkletScriptController.h
index 6585654..13f7950 100644
--- a/third_party/WebKit/Source/bindings/core/v8/WorkerOrWorkletScriptController.h
+++ b/third_party/WebKit/Source/bindings/core/v8/WorkerOrWorkletScriptController.h
@@ -42,7 +42,6 @@
 
 namespace blink {
 
-class CachedMetadataHandler;
 class ErrorEvent;
 class ExceptionState;
 class ScriptSourceCode;
@@ -63,7 +62,6 @@
   // Returns true if the evaluation completed with no uncaught exception.
   bool Evaluate(const ScriptSourceCode&,
                 ErrorEvent** = nullptr,
-                CachedMetadataHandler* = nullptr,
                 V8CacheOptions = kV8CacheOptionsDefault);
 
   // Prevents future JavaScript execution.
@@ -104,7 +102,6 @@
 
   // Evaluate a script file in the current execution environment.
   ScriptValue EvaluateInternal(const ScriptSourceCode&,
-                               CachedMetadataHandler*,
                                V8CacheOptions);
   void DisposeContextIfNeeded();
 
diff --git a/third_party/WebKit/Source/core/dom/ClassicPendingScript.cpp b/third_party/WebKit/Source/core/dom/ClassicPendingScript.cpp
index 4021e5a..493d049 100644
--- a/third_party/WebKit/Source/core/dom/ClassicPendingScript.cpp
+++ b/third_party/WebKit/Source/core/dom/ClassicPendingScript.cpp
@@ -246,9 +246,9 @@
 
   error_occurred = ErrorOccurred();
   if (!is_external_) {
-    ScriptSourceCode source_code(GetElement()->TextFromChildren(),
-                                 source_location_type_, document_url,
-                                 StartingPosition());
+    ScriptSourceCode source_code(
+        GetElement()->TextFromChildren(), source_location_type_,
+        nullptr /* cache_handler */, document_url, StartingPosition());
     return ClassicScript::Create(source_code, options_, kSharableCrossOrigin);
   }
 
diff --git a/third_party/WebKit/Source/core/dom/ScriptLoader.cpp b/third_party/WebKit/Source/core/dom/ScriptLoader.cpp
index 52df9b84..5abc376 100644
--- a/third_party/WebKit/Source/core/dom/ScriptLoader.cpp
+++ b/third_party/WebKit/Source/core/dom/ScriptLoader.cpp
@@ -682,11 +682,10 @@
 }
 
 // https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-classic-script
-bool ScriptLoader::FetchClassicScript(
-    const KURL& url,
-    Document& element_document,
-    const ScriptFetchOptions& options,
-    const WTF::TextEncoding& encoding) {
+bool ScriptLoader::FetchClassicScript(const KURL& url,
+                                      Document& element_document,
+                                      const ScriptFetchOptions& options,
+                                      const WTF::TextEncoding& encoding) {
   FetchParameters::DeferOption defer = FetchParameters::kNoDefer;
   if (!parser_inserted_ || element_->AsyncAttributeValue() ||
       element_->DeferAttributeValue())
diff --git a/third_party/WebKit/Source/core/dom/ScriptRunner.cpp b/third_party/WebKit/Source/core/dom/ScriptRunner.cpp
index 5c02721..0707e08a 100644
--- a/third_party/WebKit/Source/core/dom/ScriptRunner.cpp
+++ b/third_party/WebKit/Source/core/dom/ScriptRunner.cpp
@@ -177,9 +177,10 @@
     DCHECK(!old_document.GetFrame());
     old_context_document = &old_document;
   }
-  if (old_context_document != new_context_document)
+  if (old_context_document != new_context_document) {
     old_context_document->GetScriptRunner()->MovePendingScript(
         new_context_document->GetScriptRunner(), script_loader);
+  }
 }
 
 void ScriptRunner::MovePendingScript(ScriptRunner* new_runner,
diff --git a/third_party/WebKit/Source/core/dom/ScriptRunnerTest.cpp b/third_party/WebKit/Source/core/dom/ScriptRunnerTest.cpp
index e2fff36..853f7da4 100644
--- a/third_party/WebKit/Source/core/dom/ScriptRunnerTest.cpp
+++ b/third_party/WebKit/Source/core/dom/ScriptRunnerTest.cpp
@@ -371,9 +371,10 @@
 
   EXPECT_CALL(*script_loaders[0], Execute())
       .WillOnce(Invoke([&script_loaders, this] {
-        for (int i = 2; i < 20; i++)
+        for (int i = 2; i < 20; i++) {
           script_runner_->NotifyScriptReady(script_loaders[i],
                                             ScriptRunner::kAsync);
+        }
         order_.push_back(0);
       }));
 
diff --git a/third_party/WebKit/Source/core/exported/WebScriptSource.cpp b/third_party/WebKit/Source/core/exported/WebScriptSource.cpp
index ddc320a..92e8546 100644
--- a/third_party/WebKit/Source/core/exported/WebScriptSource.cpp
+++ b/third_party/WebKit/Source/core/exported/WebScriptSource.cpp
@@ -12,8 +12,8 @@
 WebScriptSource::operator ScriptSourceCode() const {
   TextPosition position(OrdinalNumber::FromOneBasedInt(start_line),
                         OrdinalNumber::First());
-  return ScriptSourceCode(code, ScriptSourceLocationType::kUnknown, url,
-                          position);
+  return ScriptSourceCode(code, ScriptSourceLocationType::kUnknown,
+                          nullptr /* cache_handler */, url, position);
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/loader/resource/CSSStyleSheetResource.cpp b/third_party/WebKit/Source/core/loader/resource/CSSStyleSheetResource.cpp
index 87dce93..073a767c 100644
--- a/third_party/WebKit/Source/core/loader/resource/CSSStyleSheetResource.cpp
+++ b/third_party/WebKit/Source/core/loader/resource/CSSStyleSheetResource.cpp
@@ -48,9 +48,6 @@
   params.SetRequestContext(WebURLRequest::kRequestContextStyle);
   CSSStyleSheetResource* resource = ToCSSStyleSheetResource(
       fetcher->RequestResource(params, CSSStyleSheetResourceFactory()));
-  // TODO(kouhei): Dedupe this logic w/ ScriptResource::fetch
-  if (resource && !params.IntegrityMetadata().IsEmpty())
-    resource->SetIntegrityMetadata(params.IntegrityMetadata());
   return resource;
 }
 
diff --git a/third_party/WebKit/Source/core/loader/resource/ScriptResource.cpp b/third_party/WebKit/Source/core/loader/resource/ScriptResource.cpp
index dd83831..5c97ea5 100644
--- a/third_party/WebKit/Source/core/loader/resource/ScriptResource.cpp
+++ b/third_party/WebKit/Source/core/loader/resource/ScriptResource.cpp
@@ -46,11 +46,8 @@
   DCHECK_EQ(params.GetResourceRequest().GetFrameType(),
             WebURLRequest::kFrameTypeNone);
   params.SetRequestContext(WebURLRequest::kRequestContextScript);
-  ScriptResource* resource = ToScriptResource(
+  return ToScriptResource(
       fetcher->RequestResource(params, ScriptResourceFactory()));
-  if (resource && !params.IntegrityMetadata().IsEmpty())
-    resource->SetIntegrityMetadata(params.IntegrityMetadata());
-  return resource;
 }
 
 ScriptResource::ScriptResource(
diff --git a/third_party/WebKit/Source/core/mojo/tests/JsToCppTest.cpp b/third_party/WebKit/Source/core/mojo/tests/JsToCppTest.cpp
index 31dd0d4..77a98bc3 100644
--- a/third_party/WebKit/Source/core/mojo/tests/JsToCppTest.cpp
+++ b/third_party/WebKit/Source/core/mojo/tests/JsToCppTest.cpp
@@ -12,6 +12,7 @@
 #include "core/page/Page.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "mojo/public/cpp/system/wait.h"
+#include "platform/SharedBuffer.h"
 #include "platform/testing/UnitTestHelpers.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/WebKit/Source/core/mojo/tests/JsToCpp.mojom-blink.h"
diff --git a/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp b/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp
index 736d0bc..4338034 100644
--- a/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp
+++ b/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp
@@ -106,9 +106,9 @@
       source_code.length(),
       cached_meta_data.get() ? cached_meta_data->size() : 0);
   bool success = ScriptController()->Evaluate(
-      ScriptSourceCode(source_code, ScriptSourceLocationType::kUnknown,
+      ScriptSourceCode(source_code, ScriptSourceLocationType::kUnknown, handler,
                        script_url),
-      nullptr /* error_event */, handler, v8_cache_options_);
+      nullptr /* error_event */, v8_cache_options_);
   ReportingProxy().DidEvaluateWorkerScript(success);
 }
 
@@ -203,8 +203,8 @@
         source_code.length(), cached_meta_data ? cached_meta_data->size() : 0);
     ScriptController()->Evaluate(
         ScriptSourceCode(source_code, ScriptSourceLocationType::kUnknown,
-                         response_url),
-        &error_event, handler, v8_cache_options_);
+                         handler, response_url),
+        &error_event, v8_cache_options_);
     if (error_event) {
       ScriptController()->RethrowExceptionFromImportedScript(error_event,
                                                              exception_state);
diff --git a/third_party/WebKit/Source/platform/loader/fetch/Resource.cpp b/third_party/WebKit/Source/platform/loader/fetch/Resource.cpp
index ecddf0d..db24f1d4 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/Resource.cpp
+++ b/third_party/WebKit/Source/platform/loader/fetch/Resource.cpp
@@ -462,7 +462,7 @@
   if (params.IntegrityMetadata().IsEmpty())
     return false;
 
-  return !IntegrityMetadata::SetsEqual(integrity_metadata_,
+  return !IntegrityMetadata::SetsEqual(IntegrityMetadata(),
                                        params.IntegrityMetadata());
 }
 
diff --git a/third_party/WebKit/Source/platform/loader/fetch/Resource.h b/third_party/WebKit/Source/platform/loader/fetch/Resource.h
index b5d96142..8ae3830 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/Resource.h
+++ b/third_party/WebKit/Source/platform/loader/fetch/Resource.h
@@ -254,11 +254,8 @@
   bool HasCacheControlNoStoreHeader() const;
   bool MustReloadDueToVaryHeader(const ResourceRequest& new_request) const;
 
-  void SetIntegrityMetadata(const IntegrityMetadataSet& metadata) {
-    integrity_metadata_ = metadata;
-  }
   const IntegrityMetadataSet& IntegrityMetadata() const {
-    return integrity_metadata_;
+    return options_.integrity_metadata;
   }
   ResourceIntegrityDisposition IntegrityDisposition() const {
     return integrity_disposition_;
@@ -473,7 +470,6 @@
   bool detachable_ = false;
 
   ResourceIntegrityDisposition integrity_disposition_;
-  IntegrityMetadataSet integrity_metadata_;
   SubresourceIntegrity::ReportInfo integrity_report_info_;
 
   // Ordered list of all redirects followed while fetching this resource.
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/directory_owners_extractor.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/directory_owners_extractor.py
index 3157ce4..ce062d76 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/directory_owners_extractor.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/directory_owners_extractor.py
@@ -5,6 +5,7 @@
 import collections
 import re
 
+from webkitpy.common.memoized import memoized
 from webkitpy.common.path_finder import PathFinder
 from webkitpy.common.system.filesystem import FileSystem
 
@@ -16,6 +17,8 @@
 
 # Recognizes 'X@Y' email addresses. Very simplistic. (from owners.py)
 BASIC_EMAIL_REGEXP = r'^[\w\-\+\%\.]+\@[\w\-\+\%\.]+$'
+WPT_NOTIFY_REGEXP = r'^# *WPT-NOTIFY: *true$'
+COMPONENT_REGEXP = r'^# *COMPONENT: *(.+)$'
 
 
 class DirectoryOwnersExtractor(object):
@@ -97,7 +100,7 @@
         Returns:
             A list of valid owners (email addresses).
         """
-        contents = self.filesystem.read_text_file(owners_file)
+        contents = self._read_text_file(owners_file)
         email_regexp = re.compile(BASIC_EMAIL_REGEXP)
         addresses = []
         for line in contents.splitlines():
@@ -105,3 +108,34 @@
             if email_regexp.match(line):
                 addresses.append(line)
         return addresses
+
+    def extract_component(self, owners_file):
+        """Extract the component from an OWNERS file.
+
+        Args:
+            owners_file: An absolute path to an OWNERS file.
+
+        Returns:
+            A string, or None if not found.
+        """
+        contents = self._read_text_file(owners_file)
+        search = re.search(COMPONENT_REGEXP, contents, re.MULTILINE)
+        if search:
+            return search.group(1)
+        return None
+
+    def is_wpt_notify_enabled(self, owners_file):
+        """Checks if the OWNERS file enables WPT-NOTIFY.
+
+        Args:
+            owners_file: An absolute path to an OWNERS file.
+
+        Returns:
+            A boolean.
+        """
+        contents = self._read_text_file(owners_file)
+        return bool(re.search(WPT_NOTIFY_REGEXP, contents, re.MULTILINE))
+
+    @memoized
+    def _read_text_file(self, path):
+        return self.filesystem.read_text_file(path)
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/directory_owners_extractor_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/directory_owners_extractor_unittest.py
index 6e72505..2b810c4 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/directory_owners_extractor_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/directory_owners_extractor_unittest.py
@@ -100,3 +100,35 @@
         }
         self.assertEqual(self.extractor.extract_owners(ABS_WPT_BASE + '/foo/OWNERS'),
                          ['foo@chromium.org', 'bar@chromium.org'])
+
+    def test_extract_component(self):
+        self.filesystem.files = {
+            ABS_WPT_BASE + '/foo/OWNERS':
+            '# TEAM: some-team@chromium.org\n'
+            '# COMPONENT: Blink>Layout\n'
+        }
+        self.assertEqual(self.extractor.extract_component(ABS_WPT_BASE + '/foo/OWNERS'), 'Blink>Layout')
+
+    def test_is_wpt_notify_enabled_true(self):
+        self.filesystem.files = {
+            ABS_WPT_BASE + '/foo/OWNERS':
+            '# COMPONENT: Blink>Layout\n'
+            '# WPT-NOTIFY: true\n'
+        }
+        self.assertTrue(self.extractor.is_wpt_notify_enabled(ABS_WPT_BASE + '/foo/OWNERS'))
+
+    def test_is_wpt_notify_enabled_false(self):
+        self.filesystem.files = {
+            ABS_WPT_BASE + '/foo/OWNERS':
+            '# COMPONENT: Blink>Layout\n'
+            '# WPT-NOTIFY: false\n'
+        }
+        self.assertFalse(self.extractor.is_wpt_notify_enabled(ABS_WPT_BASE + '/foo/OWNERS'))
+
+    def test_is_wpt_notify_enabled_absence_is_false(self):
+        self.filesystem.files = {
+            ABS_WPT_BASE + '/foo/OWNERS':
+            '# TEAM: some-team@chromium.org\n'
+            '# COMPONENT: Blink>Layout\n'
+        }
+        self.assertFalse(self.extractor.is_wpt_notify_enabled(ABS_WPT_BASE + '/foo/OWNERS'))
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/import_notifier.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/import_notifier.py
index c34b7018..57f85f7 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/import_notifier.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/import_notifier.py
@@ -96,7 +96,7 @@
             gerrit_url_with_ps: Gerrit URL of this CL with the patchset number.
         """
         for test_name, changed_baselines in changed_test_baselines.iteritems():
-            directory = self._find_owned_directory(test_name)
+            directory = self.find_owned_directory(test_name)
             if not directory:
                 _log.warning('Cannot find OWNERS of %s', test_name)
                 continue
@@ -126,7 +126,7 @@
                 be rebaselined to a list of new test expectation lines.
         """
         for test_name, expectation_lines in test_expectations.iteritems():
-            directory = self._find_owned_directory(test_name)
+            directory = self.find_owned_directory(test_name)
             if not directory:
                 _log.warning('Cannot find OWNERS of %s', test_name)
                 continue
@@ -157,9 +157,16 @@
 
             full_directory = self.host.filesystem.join(self.finder.layout_tests_dir(), directory)
             owners_file = self.host.filesystem.join(full_directory, 'OWNERS')
+            is_wpt_notify_enabled = self.owners_extractor.is_wpt_notify_enabled(owners_file)
+            _log.info("WPT-NOTIFY: %s", str(is_wpt_notify_enabled))
+
             owners = self.owners_extractor.extract_owners(owners_file)
             _log.info("Owners: %s", ' '.join(owners))
 
+            component = self.owners_extractor.extract_component(owners_file)
+            # component could be None.
+            _log.info("Component: %s", str(component))
+
             prologue = ('WPT import {} introduced new failures in {}:\n\n'
                         'List of new failures:\n'.format(gerrit_url, directory))
             failure_list = ''
@@ -195,7 +202,7 @@
             commit_list += line + '\n'
         return commit_list
 
-    def _find_owned_directory(self, test_name):
+    def find_owned_directory(self, test_name):
         """Finds the lowest directory that contains the test and has OWNERS.
 
         Args:
@@ -204,6 +211,11 @@
         Returns:
             The path of the found directory relative to LayoutTests.
         """
+        # Always use non-virtual test names when looking up OWNERS.
+        if self.default_port.lookup_virtual_test_base(test_name):
+            test_name = self.default_port.lookup_virtual_test_base(test_name)
+        # find_owners_file takes either a relative path from the *root* of the
+        # repository, or an absolute path.
         abs_test_path = self.finder.path_from_layout_tests(test_name)
         owners_file = self.owners_extractor.find_owners_file(self.host.filesystem.dirname(abs_test_path))
         if not owners_file:
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/import_notifier_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/import_notifier_unittest.py
index 5eec76e1..9259f44 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/import_notifier_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/import_notifier_unittest.py
@@ -7,6 +7,7 @@
 from webkitpy.common.checkout.git_mock import MockGit
 from webkitpy.common.host_mock import MockHost
 from webkitpy.common.system.executive_mock import mock_git_commands
+from webkitpy.common.system.filesystem_mock import MockFileSystem
 from webkitpy.w3c.local_wpt_mock import MockLocalWPT
 from webkitpy.w3c.import_notifier import ImportNotifier, TestFailure
 from webkitpy.w3c.wpt_expectations_updater import UMBRELLA_BUG
@@ -16,6 +17,11 @@
 
     def setUp(self):
         self.host = MockHost()
+        # Mock a virtual test suite at virtual/gpu/external/wpt/foo.
+        self.host.filesystem = MockFileSystem({
+            '/mock-checkout/third_party/WebKit/LayoutTests/VirtualTestSuites':
+            '[{"prefix": "gpu", "base": "external/wpt/foo", "args": ["--foo"]}]'
+        })
         self.git = self.host.git()
         self.local_wpt = MockLocalWPT()
         self.notifier = ImportNotifier(self.host, self.git, self.local_wpt)
@@ -51,25 +57,23 @@
 
     def test_more_failures_in_baseline_fewer_fails(self):
         executive = mock_git_commands({
-            'diff': '''diff --git a/foo-expected.txt b/foo-expected.txt
---- a/foo-expected.txt
-+++ b/foo-expected.txt
--FAIL an old failure
--FAIL new failure 1
-+FAIL new failure 2
-'''
+            'diff': ('diff --git a/foo-expected.txt b/foo-expected.txt\n'
+                     '--- a/foo-expected.txt\n'
+                     '+++ b/foo-expected.txt\n'
+                     '-FAIL an old failure\n'
+                     '-FAIL new failure 1\n'
+                     '+FAIL new failure 2\n')
         })
         self.notifier.git = MockGit(executive=executive)
         self.assertFalse(self.notifier.more_failures_in_baseline('foo-expected.txt'))
 
     def test_more_failures_in_baseline_same_fails(self):
         executive = mock_git_commands({
-            'diff': '''diff --git a/foo-expected.txt b/foo-expected.txt
---- a/foo-expected.txt
-+++ b/foo-expected.txt
--FAIL an old failure
-+FAIL new failure 1
-'''
+            'diff': ('diff --git a/foo-expected.txt b/foo-expected.txt\n'
+                     '--- a/foo-expected.txt\n'
+                     '+++ b/foo-expected.txt\n'
+                     '-FAIL an old failure\n'
+                     '+FAIL a new failure\n')
         })
         self.notifier.git = MockGit(executive=executive)
         self.assertFalse(self.notifier.more_failures_in_baseline('foo-expected.txt'))
@@ -134,6 +138,21 @@
             'Fake subject: https://github.com/w3c/web-platform-tests/commit/SHA2\n'
         )
 
+    def test_find_owned_directory_non_virtual(self):
+        self.host.filesystem.write_text_file(
+            '/mock-checkout/third_party/WebKit/LayoutTests/external/wpt/foo/OWNERS',
+            'test@chromium.org'
+        )
+        self.assertEqual(self.notifier.find_owned_directory('external/wpt/foo/bar.html'), 'external/wpt/foo')
+        self.assertEqual(self.notifier.find_owned_directory('external/wpt/foo/bar/baz.html'), 'external/wpt/foo')
+
+    def test_find_owned_directory_virtual(self):
+        self.host.filesystem.write_text_file(
+            '/mock-checkout/third_party/WebKit/LayoutTests/external/wpt/foo/OWNERS',
+            'test@chromium.org'
+        )
+        self.assertEqual(self.notifier.find_owned_directory('virtual/gpu/external/wpt/foo/bar.html'), 'external/wpt/foo')
+
     def test_test_failure_to_str_baseline_change(self):
         failure = TestFailure(
             TestFailure.BASELINE_CHANGE, 'external/wpt/foo/bar.html',
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer.py
index a860d1ed..1c9ec8c 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer.py
@@ -622,9 +622,7 @@
             return None
 
     def send_notifications(self, local_wpt):
-        # Check the format of these values.
         issue = self.git_cl.run(['status', '--field=id']).strip()
-        # FIXME(robertma): this does not work! https://crbug.com/792611
         patchset = self.git_cl.run(['status', '--field=patch']).strip()
         # Construct the notifier here so that any errors won't affect the import.
         notifier = ImportNotifier(self.host, self.chromium_git, local_wpt)
diff --git a/third_party/bazel/OWNERS b/third_party/bazel/OWNERS
index ea2bde4..aed8b1a 100644
--- a/third_party/bazel/OWNERS
+++ b/third_party/bazel/OWNERS
@@ -1,4 +1,4 @@
 agrieve@chromium.org
-zpeng@chromium.org
+jbudorick@chromium.org
 
 # COMPONENT: Build
diff --git a/third_party/checkstyle/OWNERS b/third_party/checkstyle/OWNERS
index 3daedd9..cf39ee7 100644
--- a/third_party/checkstyle/OWNERS
+++ b/third_party/checkstyle/OWNERS
@@ -1,5 +1,3 @@
 agrieve@chromium.org
 jbudorick@chromium.org
 nyquist@chromium.org
-zpeng@chromium.org
-
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 79634c9..f864171c 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -25030,6 +25030,7 @@
   <int value="-790036192" label="overscroll-start-threshold"/>
   <int value="-787426248" label="ChromeHomeSurvey:disabled"/>
   <int value="-780798969" label="disable-single-click-autofill"/>
+  <int value="-778126349" label="DownloadsLocationChange:enabled"/>
   <int value="-776686417" label="SiteExplorationUi:disabled"/>
   <int value="-775321548" label="UseNewDoodleApi:disabled"/>
   <int value="-772679248" label="MojoVideoEncodeAccelerator:enabled"/>
@@ -25629,6 +25630,7 @@
   <int value="936341613" label="OfflinePagesCT:disabled"/>
   <int value="936919953" label="bypass-app-banner-engagement-checks"/>
   <int value="938191241" label="VrShell:enabled"/>
+  <int value="939366135" label="DownloadsLocationChange:disabled"/>
   <int value="939554480" label="enable-credit-card-scan"/>
   <int value="939603162" label="BackgroundLoadingForDownloads:disabled"/>
   <int value="941036016" label="ContentSuggestionsSettings:disabled"/>
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml
index abc68bf..9c9e9b5 100644
--- a/tools/metrics/ukm/ukm.xml
+++ b/tools/metrics/ukm/ukm.xml
@@ -327,6 +327,12 @@
       interaction. This value should be between [0, 100].
     </summary>
   </metric>
+  <metric name="CheckerboardedImagesCount">
+    <summary>
+      The number of images checker-imaged and re-rasterized during this
+      interaction.
+    </summary>
+  </metric>
   <metric name="NumMissingTiles">
     <summary>
       The number of visible tiles per frame checkerboarded during this
@@ -335,6 +341,18 @@
   </metric>
 </event>
 
+<event name="Compositor.Rendering">
+  <owner>khushalsagar@chromium.org</owner>
+  <summary>
+    Metrics related to rendering in the compositor.
+  </summary>
+  <metric name="CheckerboardedImagesCount">
+    <summary>
+      The number of images checker-imaged and re-rasterized on this page.
+    </summary>
+  </metric>
+</event>
+
 <event name="ContextualSearch">
   <owner>donnd@chromium.org</owner>
   <summary>
diff --git a/tools/perf/benchmarks/blink_perf_unittest.py b/tools/perf/benchmarks/blink_perf_unittest.py
index 0136f58..eef36b3 100644
--- a/tools/perf/benchmarks/blink_perf_unittest.py
+++ b/tools/perf/benchmarks/blink_perf_unittest.py
@@ -5,7 +5,6 @@
 import unittest
 
 from telemetry import story
-from telemetry import decorators
 from telemetry.page import page as page_module
 from telemetry.testing import options_for_unittests
 from telemetry.testing import page_test_test_case
@@ -39,7 +38,6 @@
     story_set.AddStory(page)
     return story_set
 
-  @decorators.Disabled('android')  # crbug.com/793063
   def testBlinkPerfTracingMetricsForMeasureTime(self):
     results = self.RunMeasurement(measurement=self._measurement,
         ps=self._CreateStorySetForTestFile('append-child-measure-time.html'),
@@ -62,7 +60,6 @@
 
     self.assertGreater(update_layout_trees[0].GetRepresentativeNumber(), 0.001)
 
-  @decorators.Disabled('android')  # crbug.com/793063
   def testBlinkPerfTracingMetricsForMeasureFrameTime(self):
     results = self.RunMeasurement(measurement=self._measurement,
         ps=self._CreateStorySetForTestFile(
@@ -87,7 +84,6 @@
     self.assertGreater(frame_view_painttrees[0].GetRepresentativeNumber(),
         0.001)
 
-  @decorators.Disabled('android')  # crbug.com/793063
   def testBlinkPerfTracingMetricsForMeasurePageLoadTime(self):
     results = self.RunMeasurement(measurement=self._measurement,
         ps=self._CreateStorySetForTestFile(
diff --git a/tools/perf/benchmarks/v8.py b/tools/perf/benchmarks/v8.py
index fa22157a..c0117a6d 100644
--- a/tools/perf/benchmarks/v8.py
+++ b/tools/perf/benchmarks/v8.py
@@ -30,7 +30,7 @@
       def SetExpectations(self):
         self.DisableStory('Docs  (1 open document tab)',
                           [story.expectations.ALL_WIN],
-                          'crbug.com/')
+                          'crbug.com/770982')
     return StoryExpectations()
 
 
diff --git a/tools/resources/OWNERS b/tools/resources/OWNERS
index b6a4905e..ea259a7 100644
--- a/tools/resources/OWNERS
+++ b/tools/resources/OWNERS
@@ -1,3 +1,3 @@
 agrieve@chromium.org
+per-file filter_resource_whitelist.*=estevenson@chromium.org
 per-file generate_resource_whitelist.*=estevenson@chromium.org
-per-file filter_resource_whitelist.*=zpeng@chromium.org
diff --git a/ui/ozone/BUILD.gn b/ui/ozone/BUILD.gn
index 247879c..d38a202 100644
--- a/ui/ozone/BUILD.gn
+++ b/ui/ozone/BUILD.gn
@@ -230,3 +230,25 @@
   # 2nd copy of any code via the component.
   assert_no_deps = [ "//ui/ozone" ]
 }
+
+# X11 backend has its own test suite only built when we are using the x11
+# backend.
+if (ozone_platform_x11) {
+  test("ozone_x11_unittests") {
+    deps = [
+      "//base/test:test_support",
+      "//mojo/edk/test:run_all_unittests",
+      "//mojo/public/cpp/bindings",
+      "//testing/gtest",
+      "//ui/gfx:test_support",
+      "//ui/gfx/geometry",
+      "//ui/ozone/public/interfaces:struct_trait_unit_test",
+    ]
+
+    deps += [ "platform/x11:x11_unittests" ]
+
+    # Platform tests link ozone statically. Make sure we're not getting a
+    # 2nd copy of any code via the component.
+    assert_no_deps = [ "//ui/ozone" ]
+  }
+}
diff --git a/ui/ozone/platform/x11/BUILD.gn b/ui/ozone/platform/x11/BUILD.gn
index 86d45117..a060b1f 100644
--- a/ui/ozone/platform/x11/BUILD.gn
+++ b/ui/ozone/platform/x11/BUILD.gn
@@ -47,3 +47,17 @@
 
   public_configs = [ "//third_party/khronos:khronos_headers" ]
 }
+
+source_set("x11_unittests") {
+  testonly = true
+  sources = [
+    "x11_cursor_factory_ozone_unittest.cc",
+  ]
+
+  deps = [
+    ":x11",
+    "//testing/gtest",
+    "//ui/ozone:platform",
+    "//ui/ozone/common",
+  ]
+}
diff --git a/ui/ozone/platform/x11/x11_cursor_factory_ozone_unittest.cc b/ui/ozone/platform/x11/x11_cursor_factory_ozone_unittest.cc
new file mode 100644
index 0000000..8b065eb
--- /dev/null
+++ b/ui/ozone/platform/x11/x11_cursor_factory_ozone_unittest.cc
@@ -0,0 +1,31 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/ozone/platform/x11/x11_cursor_factory_ozone.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/geometry/point.h"
+
+namespace ui {
+
+TEST(X11CursorFactoryOzoneTest, InvisibleRefcount) {
+  X11CursorFactoryOzone factory;
+
+  // Building an image cursor with an invalid SkBitmap should return the
+  // invisible cursor in X11. The invisible cursor instance should have more
+  // than a single reference since the factory should hold a reference and
+  // CreateImageCursor should return an incremented refcount.
+  X11CursorOzone* invisible_cursor = static_cast<X11CursorOzone*>(
+      factory.CreateImageCursor(SkBitmap(), gfx::Point(), 1.0f));
+  ASSERT_FALSE(invisible_cursor->HasOneRef());
+
+  // Release our refcount on the cursor
+  factory.UnrefImageCursor(invisible_cursor);
+
+  // The invisible cursor should still exist.
+  EXPECT_TRUE(invisible_cursor->HasOneRef());
+}
+
+}  // namespace ui