Post loading tasks on the appropriate WebFrameScheduler's queue.
Must be submitted after https://codereview.chromium.org/1340343003/
BUG=510398, 538660
Committed: https://crrev.com/bcc4ce71b07ea71a1056c3227c5bc381c52256fd
Cr-Commit-Position: refs/heads/master@{#352036}
Review URL: https://codereview.chromium.org/1366883002
Cr-Commit-Position: refs/heads/master@{#352866}
diff --git a/components/html_viewer/web_url_loader_impl.cc b/components/html_viewer/web_url_loader_impl.cc
index ecffee8..7853532 100644
--- a/components/html_viewer/web_url_loader_impl.cc
+++ b/components/html_viewer/web_url_loader_impl.cc
@@ -350,4 +350,9 @@
   ReadMore();
 }
 
+void WebURLLoaderImpl::setLoadingTaskRunner(
+    blink::WebTaskRunner* web_task_runner) {
+  // TODO(alexclarke): Consider hooking this up.
+}
+
 }  // namespace html_viewer
diff --git a/components/html_viewer/web_url_loader_impl.h b/components/html_viewer/web_url_loader_impl.h
index c8a788f..f829331 100644
--- a/components/html_viewer/web_url_loader_impl.h
+++ b/components/html_viewer/web_url_loader_impl.h
@@ -47,6 +47,7 @@
                                   blink::WebURLLoaderClient* client);
   virtual void cancel();
   virtual void setDefersLoading(bool defers_loading);
+  virtual void setLoadingTaskRunner(blink::WebTaskRunner* web_task_runner);
 
   void OnReceivedResponse(const blink::WebURLRequest& request,
                           mojo::URLResponsePtr response);
diff --git a/components/scheduler/child/web_task_runner_impl.cc b/components/scheduler/child/web_task_runner_impl.cc
index b4794a4c..56591ac4 100644
--- a/components/scheduler/child/web_task_runner_impl.cc
+++ b/components/scheduler/child/web_task_runner_impl.cc
@@ -36,4 +36,8 @@
       base::TimeDelta::FromMillisecondsD(delayMs));
 }
 
+blink::WebTaskRunner* WebTaskRunnerImpl::clone() {
+  return new WebTaskRunnerImpl(task_runner_);
+}
+
 }  // namespace scheduler
diff --git a/components/scheduler/child/web_task_runner_impl.h b/components/scheduler/child/web_task_runner_impl.h
index 73a1e46f..c9cc55d 100644
--- a/components/scheduler/child/web_task_runner_impl.h
+++ b/components/scheduler/child/web_task_runner_impl.h
@@ -34,6 +34,7 @@
   void postDelayedTask(const blink::WebTraceLocation& web_location,
                        blink::WebTaskRunner::Task* task,
                        double delayMs) override;
+  blink::WebTaskRunner* clone() override;
 
  private:
   scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
diff --git a/content/child/blink_platform_impl.cc b/content/child/blink_platform_impl.cc
index c8f4168..3b26b61 100644
--- a/content/child/blink_platform_impl.cc
+++ b/content/child/blink_platform_impl.cc
@@ -34,6 +34,7 @@
 #include "blink/public/resources/grit/blink_image_resources.h"
 #include "blink/public/resources/grit/blink_resources.h"
 #include "components/mime_util/mime_util.h"
+#include "components/scheduler/child/web_task_runner_impl.h"
 #include "components/scheduler/child/webthread_impl_for_worker_scheduler.h"
 #include "content/app/resources/grit/content_resources.h"
 #include "content/app/strings/grit/content_strings.h"
@@ -478,7 +479,8 @@
   // data URLs to bypass the ResourceDispatcher.
   return new WebURLLoaderImpl(
       child_thread ? child_thread->resource_dispatcher() : NULL,
-      MainTaskRunnerForCurrentThread());
+      make_scoped_ptr(new scheduler::WebTaskRunnerImpl(
+            base::ThreadTaskRunnerHandle::Get())));
 }
 
 blink::WebSocketHandle* BlinkPlatformImpl::createWebSocketHandle() {
@@ -1363,16 +1365,6 @@
   return base::trace_event::TraceLog::GetInstance()->process_id();
 }
 
-scoped_refptr<base::SingleThreadTaskRunner>
-BlinkPlatformImpl::MainTaskRunnerForCurrentThread() {
-  if (main_thread_task_runner_.get() &&
-      main_thread_task_runner_->BelongsToCurrentThread()) {
-    return main_thread_task_runner_;
-  } else {
-    return base::ThreadTaskRunnerHandle::Get();
-  }
-}
-
 bool BlinkPlatformImpl::IsMainThread() const {
   return main_thread_task_runner_.get() &&
          main_thread_task_runner_->BelongsToCurrentThread();
diff --git a/content/child/blink_platform_impl.h b/content/child/blink_platform_impl.h
index 4ec1659..f9bf754b9 100644
--- a/content/child/blink_platform_impl.h
+++ b/content/child/blink_platform_impl.h
@@ -195,8 +195,6 @@
 
   bool IsMainThread() const;
 
-  scoped_refptr<base::SingleThreadTaskRunner> MainTaskRunnerForCurrentThread();
-
   scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
   WebThemeEngineImpl native_theme_engine_;
   WebFallbackThemeEngineImpl fallback_theme_engine_;
diff --git a/content/child/request_info.cc b/content/child/request_info.cc
index b115b7d..2af34cd5d 100644
--- a/content/child/request_info.cc
+++ b/content/child/request_info.cc
@@ -27,7 +27,8 @@
       enable_upload_progress(false),
       do_not_prompt_for_login(false),
       report_raw_headers(false),
-      extra_data(NULL) {}
+      extra_data(NULL),
+      loading_web_task_runner(nullptr) {}
 
 RequestInfo::~RequestInfo() {}
 
diff --git a/content/child/request_info.h b/content/child/request_info.h
index e610ac8..037c1db 100644
--- a/content/child/request_info.h
+++ b/content/child/request_info.h
@@ -17,9 +17,14 @@
 #include "content/public/common/resource_type.h"
 #include "net/base/request_priority.h"
 #include "third_party/WebKit/public/platform/WebReferrerPolicy.h"
+#include "third_party/WebKit/public/platform/WebTaskRunner.h"
 #include "third_party/WebKit/public/platform/WebURLRequest.h"
 #include "url/gurl.h"
 
+namespace blink {
+class WebTaskRunner;
+} // namespace blink
+
 namespace content {
 
 // Structure used when calling BlinkPlatformImpl::CreateResourceLoader().
@@ -110,6 +115,9 @@
   // Extra data associated with this request.  We do not own this pointer.
   blink::WebURLRequest::ExtraData* extra_data;
 
+  // Optional, the specific task queue to execute loading tasks on.
+  scoped_ptr<blink::WebTaskRunner> loading_web_task_runner;
+
  private:
   DISALLOW_COPY_AND_ASSIGN(RequestInfo);
 };
diff --git a/content/child/resource_dispatcher.cc b/content/child/resource_dispatcher.cc
index 684f3ee..0c990721 100644
--- a/content/child/resource_dispatcher.cc
+++ b/content/child/resource_dispatcher.cc
@@ -18,6 +18,7 @@
 #include "base/strings/string_util.h"
 #include "content/child/request_extra_data.h"
 #include "content/child/request_info.h"
+#include "content/child/resource_scheduling_filter.h"
 #include "content/child/shared_memory_received_data_factory.h"
 #include "content/child/site_isolation_stats_gatherer.h"
 #include "content/child/sync_load_response.h"
@@ -414,6 +415,9 @@
         new ResourceHostMsg_ReleaseDownloadedFile(request_id));
   }
 
+  if (resource_scheduling_filter_.get())
+    resource_scheduling_filter_->ClearRequestIdTaskRunner(request_id);
+
   return true;
 }
 
@@ -599,6 +603,13 @@
                          request->url,
                          request_info.download_to_file);
 
+  if (resource_scheduling_filter_.get() &&
+      request_info.loading_web_task_runner) {
+    resource_scheduling_filter_->SetRequestIdTaskRunner(
+        request_id,
+        make_scoped_ptr(request_info.loading_web_task_runner->clone()));
+  }
+
   message_sender_->Send(new ResourceHostMsg_RequestResource(
       request_info.routing_id, request_id, *request));
 
@@ -805,4 +816,9 @@
   return request.Pass();
 }
 
+void ResourceDispatcher::SetResourceSchedulingFilter(
+    scoped_refptr<ResourceSchedulingFilter> resource_scheduling_filter) {
+  resource_scheduling_filter_ = resource_scheduling_filter;
+}
+
 }  // namespace content
diff --git a/content/child/resource_dispatcher.h b/content/child/resource_dispatcher.h
index 864b081..05500f5 100644
--- a/content/child/resource_dispatcher.h
+++ b/content/child/resource_dispatcher.h
@@ -39,6 +39,7 @@
 class RequestPeer;
 class ResourceDispatcherDelegate;
 class ResourceRequestBody;
+class ResourceSchedulingFilter;
 class ThreadedDataProvider;
 struct ResourceResponseInfo;
 struct RequestInfo;
@@ -129,6 +130,9 @@
     main_thread_task_runner_ = main_thread_task_runner;
   }
 
+  void SetResourceSchedulingFilter(
+      scoped_refptr<ResourceSchedulingFilter> resource_scheduling_filter);
+
  private:
   friend class ResourceDispatcherTest;
 
@@ -249,6 +253,7 @@
   base::TimeTicks io_timestamp_;
 
   scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
+  scoped_refptr<ResourceSchedulingFilter> resource_scheduling_filter_;
 
   base::WeakPtrFactory<ResourceDispatcher> weak_factory_;
 
diff --git a/content/child/resource_scheduling_filter.cc b/content/child/resource_scheduling_filter.cc
index 843cd871..6445c00 100644
--- a/content/child/resource_scheduling_filter.cc
+++ b/content/child/resource_scheduling_filter.cc
@@ -9,9 +9,32 @@
 #include "content/child/resource_dispatcher.h"
 #include "ipc/ipc_message.h"
 #include "ipc/ipc_message_start.h"
+#include "third_party/WebKit/public/platform/WebTaskRunner.h"
+#include "third_party/WebKit/public/platform/WebTraceLocation.h"
 
 namespace content {
 
+namespace {
+class DispatchMessageTask : public blink::WebTaskRunner::Task {
+ public:
+  DispatchMessageTask(
+      base::WeakPtr<ResourceSchedulingFilter> resource_scheduling_filter,
+      const IPC::Message& message)
+    : resource_scheduling_filter_(resource_scheduling_filter),
+      message_(message) {}
+
+  void run() override {
+    if (!resource_scheduling_filter_.get())
+      return;
+    resource_scheduling_filter_->DispatchMessage(message_);
+  }
+
+ private:
+  base::WeakPtr<ResourceSchedulingFilter> resource_scheduling_filter_;
+  const IPC::Message message_;
+};
+} // namespace
+
 ResourceSchedulingFilter::ResourceSchedulingFilter(
     const scoped_refptr<base::SingleThreadTaskRunner>& main_thread_task_runner,
     ResourceDispatcher* resource_dispatcher)
@@ -26,12 +49,42 @@
 }
 
 bool ResourceSchedulingFilter::OnMessageReceived(const IPC::Message& message) {
-  main_thread_task_runner_->PostTask(
-      FROM_HERE, base::Bind(&ResourceSchedulingFilter::DispatchMessage,
-                            weak_ptr_factory_.GetWeakPtr(), message));
+  base::AutoLock lock(request_id_to_task_runner_map_lock_);
+  int request_id;
+
+  base::PickleIterator pickle_iterator(message);
+  if (!pickle_iterator.ReadInt(&request_id)) {
+    NOTREACHED() << "malformed resource message";
+    return true;
+  }
+  // Dispatch the message on the request id specific task runner, if there is
+  // one, or on the general main_thread_task_runner if there isn't.
+  RequestIdToTaskRunnerMap::const_iterator iter =
+      request_id_to_task_runner_map_.find(request_id);
+  if (iter != request_id_to_task_runner_map_.end()) {
+    // TODO(alexclarke): Find a way to let blink and chromium FROM_HERE coexist.
+    iter->second->postTask(
+        blink::WebTraceLocation(__FUNCTION__, __FILE__),
+        new DispatchMessageTask(weak_ptr_factory_.GetWeakPtr(), message));
+  } else {
+    main_thread_task_runner_->PostTask(
+        FROM_HERE, base::Bind(&ResourceSchedulingFilter::DispatchMessage,
+                              weak_ptr_factory_.GetWeakPtr(), message));
+  }
   return true;
 }
 
+void ResourceSchedulingFilter::SetRequestIdTaskRunner(
+    int id, scoped_ptr<blink::WebTaskRunner> web_task_runner) {
+  base::AutoLock lock(request_id_to_task_runner_map_lock_);
+  request_id_to_task_runner_map_.insert(id, web_task_runner.Pass());
+}
+
+void ResourceSchedulingFilter::ClearRequestIdTaskRunner(int id) {
+  base::AutoLock lock(request_id_to_task_runner_map_lock_);
+  request_id_to_task_runner_map_.erase(id);
+}
+
 bool ResourceSchedulingFilter::GetSupportedMessageClasses(
     std::vector<uint32>* supported_message_classes) const {
   supported_message_classes->push_back(ResourceMsgStart);
diff --git a/content/child/resource_scheduling_filter.h b/content/child/resource_scheduling_filter.h
index 7ea73c90..fd245592 100644
--- a/content/child/resource_scheduling_filter.h
+++ b/content/child/resource_scheduling_filter.h
@@ -5,12 +5,19 @@
 #ifndef CONTENT_CHILD_RESOURCE_SCHEDULING_FILTER_H_
 #define CONTENT_CHILD_RESOURCE_SCHEDULING_FILTER_H_
 
+#include <map>
+
 #include "base/containers/hash_tables.h"
+#include "base/containers/scoped_ptr_map.h"
 #include "base/memory/weak_ptr.h"
 #include "base/single_thread_task_runner.h"
 #include "content/common/content_export.h"
 #include "ipc/message_filter.h"
 
+namespace blink {
+class WebTaskRunner;
+}
+
 namespace content {
 class ResourceDispatcher;
 
@@ -28,11 +35,25 @@
   bool GetSupportedMessageClasses(
       std::vector<uint32>* supported_message_classes) const override;
 
- protected:
-  ~ResourceSchedulingFilter() override;
+  // Sets the task runner associated with request messages with |id|.
+  void SetRequestIdTaskRunner(
+      int id, scoped_ptr<blink::WebTaskRunner> web_task_runner);
+
+  // Removes the task runner associated with |id|.
+  void ClearRequestIdTaskRunner(int id);
 
   void DispatchMessage(const IPC::Message& message);
 
+ private:
+  ~ResourceSchedulingFilter() override;
+
+  typedef base::ScopedPtrMap<int, scoped_ptr<blink::WebTaskRunner>>
+      RequestIdToTaskRunnerMap;
+
+  // This lock guards |request_id_to_task_runner_map_|
+  base::Lock request_id_to_task_runner_map_lock_;
+  RequestIdToTaskRunnerMap request_id_to_task_runner_map_;
+
   scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
   ResourceDispatcher* resource_dispatcher_;  // NOT OWNED
   base::WeakPtrFactory<ResourceSchedulingFilter> weak_ptr_factory_;
diff --git a/content/child/web_url_loader_impl.cc b/content/child/web_url_loader_impl.cc
index bf669cc..68851d4 100644
--- a/content/child/web_url_loader_impl.cc
+++ b/content/child/web_url_loader_impl.cc
@@ -16,6 +16,7 @@
 #include "base/strings/string_util.h"
 #include "base/time/time.h"
 #include "components/mime_util/mime_util.h"
+#include "components/scheduler/child/web_task_runner_impl.h"
 #include "content/child/child_thread_impl.h"
 #include "content/child/ftp_directory_listing_response_delegate.h"
 #include "content/child/multipart_response_delegate.h"
@@ -42,6 +43,7 @@
 #include "net/ssl/ssl_connection_status_flags.h"
 #include "net/url_request/url_request_data_job.h"
 #include "third_party/WebKit/public/platform/WebHTTPLoadInfo.h"
+#include "third_party/WebKit/public/platform/WebTraceLocation.h"
 #include "third_party/WebKit/public/platform/WebURL.h"
 #include "third_party/WebKit/public/platform/WebURLError.h"
 #include "third_party/WebKit/public/platform/WebURLLoadTiming.h"
@@ -254,7 +256,7 @@
  public:
   Context(WebURLLoaderImpl* loader,
           ResourceDispatcher* resource_dispatcher,
-          scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+          scoped_ptr<blink::WebTaskRunner> task_runner);
 
   WebURLLoaderClient* client() const { return client_; }
   void set_client(WebURLLoaderClient* client) { client_ = client; }
@@ -267,6 +269,7 @@
       blink::WebThreadedDataReceiver* threaded_data_receiver);
   void Start(const WebURLRequest& request,
              SyncLoadResponse* sync_load_response);
+  void SetWebTaskRunner(scoped_ptr<blink::WebTaskRunner> task_runner);
 
   // RequestPeer methods:
   void OnUploadProgress(uint64 position, uint64 size) override;
@@ -295,6 +298,19 @@
   friend class base::RefCounted<Context>;
   ~Context() override;
 
+  class HandleDataURLTask : public blink::WebTaskRunner::Task {
+   public:
+    explicit HandleDataURLTask(scoped_refptr<Context> context)
+        : context_(context) {}
+
+    void run() override {
+      context_->HandleDataURL();
+    }
+
+   private:
+    scoped_refptr<Context> context_;
+  };
+
   // Called when the body data stream is detached from the reader side.
   void CancelBodyStreaming();
   // We can optimize the handling of data URLs in most cases.
@@ -305,7 +321,7 @@
   WebURLRequest request_;
   WebURLLoaderClient* client_;
   ResourceDispatcher* resource_dispatcher_;
-  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+  scoped_ptr<blink::WebTaskRunner> web_task_runner_;
   WebReferrerPolicy referrer_policy_;
   scoped_ptr<FtpDirectoryListingResponseDelegate> ftp_listing_delegate_;
   scoped_ptr<MultipartResponseDelegate> multipart_delegate_;
@@ -319,11 +335,11 @@
 WebURLLoaderImpl::Context::Context(
     WebURLLoaderImpl* loader,
     ResourceDispatcher* resource_dispatcher,
-    scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+    scoped_ptr<blink::WebTaskRunner> web_task_runner)
     : loader_(loader),
       client_(NULL),
       resource_dispatcher_(resource_dispatcher),
-      task_runner_(task_runner),
+      web_task_runner_(web_task_runner.Pass()),
       referrer_policy_(blink::WebReferrerPolicyDefault),
       defers_loading_(NOT_DEFERRING),
       request_id_(-1) {
@@ -359,8 +375,11 @@
     defers_loading_ = SHOULD_DEFER;
   } else if (!value && defers_loading_ != NOT_DEFERRING) {
     if (defers_loading_ == DEFERRED_DATA) {
-      task_runner_->PostTask(FROM_HERE,
-                             base::Bind(&Context::HandleDataURL, this));
+      // TODO(alexclarke): Find a way to let blink and chromium FROM_HERE
+      // coexist.
+      web_task_runner_->postTask(
+          ::blink::WebTraceLocation(__FUNCTION__, __FILE__),
+          new HandleDataURLTask(this));
     }
     defers_loading_ = NOT_DEFERRING;
   }
@@ -418,8 +437,11 @@
           GetInfoFromDataURL(sync_load_response->url, sync_load_response,
                              &sync_load_response->data);
     } else {
-      task_runner_->PostTask(FROM_HERE,
-                             base::Bind(&Context::HandleDataURL, this));
+      // TODO(alexclarke): Find a way to let blink and chromium FROM_HERE
+      // coexist.
+      web_task_runner_->postTask(
+          ::blink::WebTraceLocation(__FUNCTION__, __FILE__),
+          new HandleDataURLTask(this));
     }
     return;
   }
@@ -482,6 +504,7 @@
       GetRequestContextFrameTypeForWebURLRequest(request);
   request_info.extra_data = request.extraData();
   request_info.report_raw_headers = request.reportRawHeaders();
+  request_info.loading_web_task_runner.reset(web_task_runner_->clone());
 
   scoped_refptr<ResourceRequestBody> request_body =
       GetRequestBodyForWebURLRequest(request).get();
@@ -496,6 +519,11 @@
       request_info, request_body.get(), this);
 }
 
+void WebURLLoaderImpl::Context::SetWebTaskRunner(
+    scoped_ptr<blink::WebTaskRunner> web_task_runner) {
+  web_task_runner_ = web_task_runner.Pass();
+}
+
 void WebURLLoaderImpl::Context::OnUploadProgress(uint64 position, uint64 size) {
   if (client_)
     client_->didSendData(loader_, position, size);
@@ -841,8 +869,8 @@
 
 WebURLLoaderImpl::WebURLLoaderImpl(
     ResourceDispatcher* resource_dispatcher,
-    scoped_refptr<base::SingleThreadTaskRunner> task_runner)
-    : context_(new Context(this, resource_dispatcher, task_runner)) {
+    scoped_ptr<blink::WebTaskRunner> web_task_runner)
+    : context_(new Context(this, resource_dispatcher, web_task_runner.Pass())) {
 }
 
 WebURLLoaderImpl::~WebURLLoaderImpl() {
@@ -1059,4 +1087,11 @@
   return context_->AttachThreadedDataReceiver(threaded_data_receiver);
 }
 
+void WebURLLoaderImpl::setLoadingTaskRunner(
+    blink::WebTaskRunner* loading_task_runner) {
+  // There's no guarantee on the lifetime of |loading_task_runner| so we take a
+  // copy.
+  context_->SetWebTaskRunner(make_scoped_ptr(loading_task_runner->clone()));
+}
+
 }  // namespace content
diff --git a/content/child/web_url_loader_impl.h b/content/child/web_url_loader_impl.h
index ebad018..b31b57e 100644
--- a/content/child/web_url_loader_impl.h
+++ b/content/child/web_url_loader_impl.h
@@ -36,9 +36,10 @@
 class CONTENT_EXPORT WebURLLoaderImpl
     : public NON_EXPORTED_BASE(blink::WebURLLoader) {
  public:
-  explicit WebURLLoaderImpl(
-      ResourceDispatcher* resource_dispatcher,
-      scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+
+  // Takes ownership of |web_task_runner|.
+  WebURLLoaderImpl(ResourceDispatcher* resource_dispatcher,
+                   scoped_ptr<blink::WebTaskRunner> web_task_runner);
   ~WebURLLoaderImpl() override;
 
   static void PopulateURLResponse(const GURL& url,
@@ -67,6 +68,7 @@
                          int intra_priority_value) override;
   bool attachThreadedDataReceiver(
       blink::WebThreadedDataReceiver* threaded_data_receiver) override;
+  void setLoadingTaskRunner(blink::WebTaskRunner* loading_task_runner) override;
 
  private:
   class Context;
diff --git a/content/child/web_url_loader_impl_unittest.cc b/content/child/web_url_loader_impl_unittest.cc
index 6fb686e4..00354dd 100644
--- a/content/child/web_url_loader_impl_unittest.cc
+++ b/content/child/web_url_loader_impl_unittest.cc
@@ -13,6 +13,7 @@
 #include "base/message_loop/message_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/time/time.h"
+#include "components/scheduler/child/web_task_runner_impl.h"
 #include "content/child/request_extra_data.h"
 #include "content/child/request_info.h"
 #include "content/child/resource_dispatcher.h"
@@ -106,7 +107,10 @@
   TestWebURLLoaderClient(
       ResourceDispatcher* dispatcher,
       scoped_refptr<base::SingleThreadTaskRunner> task_runner)
-      : loader_(new WebURLLoaderImpl(dispatcher, task_runner)),
+      : loader_(
+          new WebURLLoaderImpl(
+              dispatcher,
+              make_scoped_ptr(new scheduler::WebTaskRunnerImpl(task_runner)))),
         expect_multipart_response_(false),
         delete_on_receive_redirect_(false),
         delete_on_receive_response_(false),
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
index bfc8cba..c8ca4bdb 100644
--- a/content/renderer/render_thread_impl.cc
+++ b/content/renderer/render_thread_impl.cc
@@ -1047,9 +1047,10 @@
     const scoped_refptr<base::SingleThreadTaskRunner>& resource_task_queue) {
   // Add a filter that forces resource messages to be dispatched via a
   // particular task runner.
-  resource_scheduling_filter_ =
-      new ResourceSchedulingFilter(resource_task_queue, resource_dispatcher());
-  channel()->AddFilter(resource_scheduling_filter_.get());
+  scoped_refptr<ResourceSchedulingFilter> filter(
+      new ResourceSchedulingFilter(resource_task_queue, resource_dispatcher()));
+  channel()->AddFilter(filter.get());
+  resource_dispatcher()->SetResourceSchedulingFilter(filter);
 
   // The ChildResourceMessageFilter and the ResourceDispatcher need to use the
   // same queue to ensure tasks are executed in the expected order.
diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h
index 190d5578..9eed365 100644
--- a/content/renderer/render_thread_impl.h
+++ b/content/renderer/render_thread_impl.h
@@ -109,7 +109,6 @@
 class RendererBlinkPlatformImpl;
 class RendererDemuxerAndroid;
 class ResourceDispatchThrottler;
-class ResourceSchedulingFilter;
 class V8SamplingProfiler;
 class VideoCaptureImplManager;
 class WebGraphicsContext3DCommandBufferImpl;
@@ -616,8 +615,6 @@
   scoped_refptr<base::SingleThreadTaskRunner>
       main_thread_compositor_task_runner_;
 
-  scoped_refptr<ResourceSchedulingFilter> resource_scheduling_filter_;
-
   // Compositor settings.
   bool is_gpu_rasterization_enabled_;
   bool is_gpu_rasterization_forced_;
diff --git a/content/renderer/renderer_blink_platform_impl.cc b/content/renderer/renderer_blink_platform_impl.cc
index 2203239..f366df6 100644
--- a/content/renderer/renderer_blink_platform_impl.cc
+++ b/content/renderer/renderer_blink_platform_impl.cc
@@ -19,6 +19,7 @@
 #include "build/build_config.h"
 #include "cc/blink/context_provider_web_context.h"
 #include "components/scheduler/child/web_scheduler_impl.h"
+#include "components/scheduler/child/web_task_runner_impl.h"
 #include "components/scheduler/renderer/renderer_scheduler.h"
 #include "components/scheduler/renderer/webthread_impl_for_renderer_scheduler.h"
 #include "components/url_formatter/url_formatter.h"
@@ -32,6 +33,7 @@
 #include "content/child/simple_webmimeregistry_impl.h"
 #include "content/child/thread_safe_sender.h"
 #include "content/child/web_database_observer_impl.h"
+#include "content/child/web_url_loader_impl.h"
 #include "content/child/webblobregistry_impl.h"
 #include "content/child/webfileutilities_impl.h"
 #include "content/child/webmessageportchannel_impl.h"
@@ -237,6 +239,7 @@
       sudden_termination_disables_(0),
       plugin_refresh_allowed_(true),
       default_task_runner_(renderer_scheduler->DefaultTaskRunner()),
+      loading_task_runner_(renderer_scheduler->LoadingTaskRunner()),
       web_scrollbar_behavior_(new WebScrollbarBehaviorImpl),
       vibration_manager_(6) {
 #if !defined(OS_ANDROID) && !defined(OS_WIN)
@@ -274,6 +277,19 @@
 
 //------------------------------------------------------------------------------
 
+blink::WebURLLoader* RendererBlinkPlatformImpl::createURLLoader() {
+  ChildThreadImpl* child_thread = ChildThreadImpl::current();
+  // There may be no child thread in RenderViewTests.  These tests can still use
+  // data URLs to bypass the ResourceDispatcher.
+  scoped_ptr<scheduler::WebTaskRunnerImpl> task_runner(
+      new scheduler::WebTaskRunnerImpl(
+        loading_task_runner_->BelongsToCurrentThread()
+            ? loading_task_runner_ : base::ThreadTaskRunnerHandle::Get()));
+  return new content::WebURLLoaderImpl(
+      child_thread ? child_thread->resource_dispatcher() : NULL,
+      task_runner.Pass());
+}
+
 blink::WebThread* RendererBlinkPlatformImpl::currentThread() {
   if (main_thread_->isCurrentThread())
     return main_thread_.get();
diff --git a/content/renderer/renderer_blink_platform_impl.h b/content/renderer/renderer_blink_platform_impl.h
index 6a64c59..32edd5f 100644
--- a/content/renderer/renderer_blink_platform_impl.h
+++ b/content/renderer/renderer_blink_platform_impl.h
@@ -205,6 +205,8 @@
     return web_database_observer_impl_.get();
   }
 
+  blink::WebURLLoader* createURLLoader() override;
+
  private:
   bool CheckPreparsedJsCachingEnabled() const;
 
@@ -254,6 +256,7 @@
   scoped_ptr<DeviceOrientationEventPump> device_orientation_event_pump_;
 
   scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_;
+  scoped_refptr<base::SingleThreadTaskRunner> loading_task_runner_;
   scoped_refptr<IPC::SyncMessageFilter> sync_message_filter_;
   scoped_refptr<ThreadSafeSender> thread_safe_sender_;
   scoped_refptr<QuotaMessageFilter> quota_message_filter_;
diff --git a/content/test/mock_weburlloader.h b/content/test/mock_weburlloader.h
index db26111a..4b96ed3d 100644
--- a/content/test/mock_weburlloader.h
+++ b/content/test/mock_weburlloader.h
@@ -23,6 +23,8 @@
                                         blink::WebURLLoaderClient* client));
   MOCK_METHOD0(cancel, void());
   MOCK_METHOD1(setDefersLoading, void(bool value));
+  MOCK_METHOD1(setLoadingTaskRunner,
+               void(blink::WebTaskRunner* loading_task_runner));
 
  private:
   DISALLOW_COPY_AND_ASSIGN(MockWebURLLoader);
diff --git a/content/test/weburl_loader_mock.cc b/content/test/weburl_loader_mock.cc
index b7f29e4..9e534722 100644
--- a/content/test/weburl_loader_mock.cc
+++ b/content/test/weburl_loader_mock.cc
@@ -147,3 +147,7 @@
   }
   NOTIMPLEMENTED();
 }
+
+void WebURLLoaderMock::setLoadingTaskRunner(blink::WebTaskRunner*) {
+  NOTIMPLEMENTED();
+}
diff --git a/content/test/weburl_loader_mock.h b/content/test/weburl_loader_mock.h
index 025eaef5..a098a8e 100644
--- a/content/test/weburl_loader_mock.h
+++ b/content/test/weburl_loader_mock.h
@@ -55,6 +55,8 @@
 
   bool isDeferred() { return is_deferred_; }
 
+  void setLoadingTaskRunner(blink::WebTaskRunner*) override;
+
  private:
   WebURLLoaderMockFactory* factory_;
   blink::WebURLLoaderClient* client_;
diff --git a/media/blink/mock_weburlloader.h b/media/blink/mock_weburlloader.h
index 70dd5a6..68cf6da 100644
--- a/media/blink/mock_weburlloader.h
+++ b/media/blink/mock_weburlloader.h
@@ -23,6 +23,7 @@
                                         blink::WebURLLoaderClient* client));
   MOCK_METHOD0(cancel, void());
   MOCK_METHOD1(setDefersLoading, void(bool value));
+  MOCK_METHOD1(setLoadingTaskRunner, void(blink::WebTaskRunner* task_runner));
 
  private:
   DISALLOW_COPY_AND_ASSIGN(MockWebURLLoader);
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptStreamer.cpp b/third_party/WebKit/Source/bindings/core/v8/ScriptStreamer.cpp
index d38e6cc..7c178f9 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptStreamer.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptStreamer.cpp
@@ -18,6 +18,7 @@
 #include "platform/ThreadSafeFunctional.h"
 #include "platform/TraceEvent.h"
 #include "public/platform/Platform.h"
+#include "public/platform/WebScheduler.h"
 #include "wtf/MainThread.h"
 #include "wtf/text/TextEncodingRegistry.h"
 
@@ -162,7 +163,7 @@
 class SourceStream : public v8::ScriptCompiler::ExternalSourceStream {
     WTF_MAKE_NONCOPYABLE(SourceStream);
 public:
-    SourceStream()
+    explicit SourceStream(WebTaskRunner* loadingTaskRunner)
         : v8::ScriptCompiler::ExternalSourceStream()
         , m_cancelled(false)
         , m_finished(false)
@@ -170,6 +171,7 @@
         , m_queueTailPosition(0)
         , m_bookmarkPosition(0)
         , m_lengthOfBOM(0)
+        , m_loadingTaskRunner(adoptPtr(loadingTaskRunner->clone()))
     {
     }
 
@@ -219,7 +221,7 @@
         }
 
         // Inform main thread to re-queue the data.
-        Platform::current()->mainThread()->taskRunner()->postTask(
+        m_loadingTaskRunner->postTask(
             FROM_HERE, bind(&SourceStream::fetchDataFromResourceBuffer, this, 0));
     }
 
@@ -370,16 +372,18 @@
     // We store this separately, to avoid having to guard all
     // m_queueLeadPosition references with a mutex.
     unsigned m_lengthOfBOM; // Used by both threads; guarded by m_mutex.
+
+    OwnPtr<WebTaskRunner> m_loadingTaskRunner;
 };
 
 size_t ScriptStreamer::kSmallScriptThreshold = 30 * 1024;
 
-void ScriptStreamer::startStreaming(PendingScript& script, PendingScript::Type scriptType, Settings* settings, ScriptState* scriptState)
+void ScriptStreamer::startStreaming(PendingScript& script, PendingScript::Type scriptType, Settings* settings, ScriptState* scriptState, WebTaskRunner* loadingTaskRunner)
 {
     // We don't yet know whether the script will really be streamed. E.g.,
     // suppressing streaming for short scripts is done later. Record only the
     // sure negative cases here.
-    bool startedStreaming = startStreamingInternal(script, scriptType, settings, scriptState);
+    bool startedStreaming = startStreamingInternal(script, scriptType, settings, scriptState, loadingTaskRunner);
     if (!startedStreaming)
         Platform::current()->histogramEnumeration(startedStreamingHistogramName(scriptType), 0, 2);
 }
@@ -421,7 +425,7 @@
 
     // notifyFinished might already be called, or it might be called in the
     // future (if the parsing finishes earlier because of a parse error).
-    Platform::current()->mainThread()->taskRunner()->postTask(FROM_HERE, threadSafeBind(&ScriptStreamer::streamingComplete, AllowCrossThreadAccess(this)));
+    m_loadingTaskRunner->postTask(FROM_HERE, threadSafeBind(&ScriptStreamer::streamingComplete, AllowCrossThreadAccess(this)));
 
     // The task might delete ScriptStreamer, so it's not safe to do anything
     // after posting it. Note that there's no way to guarantee that this
@@ -513,7 +517,7 @@
 
         ASSERT(!m_stream);
         ASSERT(!m_source);
-        m_stream = new SourceStream();
+        m_stream = new SourceStream(m_loadingTaskRunner.get());
         // m_source takes ownership of m_stream.
         m_source = adoptPtr(new v8::ScriptCompiler::StreamedSource(m_stream, m_encoding));
 
@@ -564,7 +568,7 @@
     notifyFinishedToClient();
 }
 
-ScriptStreamer::ScriptStreamer(ScriptResource* resource, PendingScript::Type scriptType, ScriptState* scriptState, v8::ScriptCompiler::CompileOptions compileOptions)
+ScriptStreamer::ScriptStreamer(ScriptResource* resource, PendingScript::Type scriptType, ScriptState* scriptState, v8::ScriptCompiler::CompileOptions compileOptions, WebTaskRunner* loadingTaskRunner)
     : m_resource(resource)
     , m_detached(false)
     , m_stream(0)
@@ -577,6 +581,7 @@
     , m_scriptState(scriptState)
     , m_scriptType(scriptType)
     , m_encoding(v8::ScriptCompiler::StreamedSource::TWO_BYTE) // Unfortunately there's no dummy encoding value in the enum; let's use one we don't stream.
+    , m_loadingTaskRunner(adoptPtr(loadingTaskRunner->clone()))
 {
 }
 
@@ -632,7 +637,7 @@
         m_client->notifyFinished(m_resource);
 }
 
-bool ScriptStreamer::startStreamingInternal(PendingScript& script, PendingScript::Type scriptType, Settings* settings, ScriptState* scriptState)
+bool ScriptStreamer::startStreamingInternal(PendingScript& script, PendingScript::Type scriptType, Settings* settings, ScriptState* scriptState, WebTaskRunner* loadingTaskRunner)
 {
     ASSERT(isMainThread());
     ASSERT(scriptState->contextIsValid());
@@ -665,7 +670,7 @@
     // The Resource might go out of scope if the script is no longer
     // needed. This makes PendingScript notify the ScriptStreamer when it is
     // destroyed.
-    script.setStreamer(ScriptStreamer::create(resource, scriptType, scriptState, compileOption));
+    script.setStreamer(ScriptStreamer::create(resource, scriptType, scriptState, compileOption, loadingTaskRunner));
 
     return true;
 }
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptStreamer.h b/third_party/WebKit/Source/bindings/core/v8/ScriptStreamer.h
index e3eb425..c002175 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptStreamer.h
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptStreamer.h
@@ -21,6 +21,7 @@
 class ScriptState;
 class Settings;
 class SourceStream;
+class WebTaskRunner;
 
 // ScriptStreamer streams incomplete script data to V8 so that it can be parsed
 // while it's loaded. PendingScript holds a reference to ScriptStreamer. At the
@@ -32,9 +33,9 @@
 class CORE_EXPORT ScriptStreamer final : public RefCountedWillBeRefCountedGarbageCollected<ScriptStreamer> {
     WTF_MAKE_NONCOPYABLE(ScriptStreamer);
 public:
-    static PassRefPtrWillBeRawPtr<ScriptStreamer> create(ScriptResource* resource, PendingScript::Type scriptType, ScriptState* scriptState, v8::ScriptCompiler::CompileOptions compileOptions)
+    static PassRefPtrWillBeRawPtr<ScriptStreamer> create(ScriptResource* resource, PendingScript::Type scriptType, ScriptState* scriptState, v8::ScriptCompiler::CompileOptions compileOptions, WebTaskRunner* loadingTaskRunner)
     {
-        return adoptRefWillBeNoop(new ScriptStreamer(resource, scriptType, scriptState, compileOptions));
+        return adoptRefWillBeNoop(new ScriptStreamer(resource, scriptType, scriptState, compileOptions, loadingTaskRunner));
     }
 
     ~ScriptStreamer();
@@ -42,7 +43,7 @@
 
     // Launches a task (on a background thread) which will stream the given
     // PendingScript into V8 as it loads.
-    static void startStreaming(PendingScript&, PendingScript::Type, Settings*, ScriptState*);
+    static void startStreaming(PendingScript&, PendingScript::Type, Settings*, ScriptState*, WebTaskRunner*);
 
     // Returns false if we cannot stream the given encoding.
     static bool convertEncoding(const char* encodingName, v8::ScriptCompiler::StreamedSource::Encoding*);
@@ -107,12 +108,12 @@
     // streamed. Non-const for testing.
     static size_t kSmallScriptThreshold;
 
-    ScriptStreamer(ScriptResource*, PendingScript::Type, ScriptState*, v8::ScriptCompiler::CompileOptions);
+    ScriptStreamer(ScriptResource*, PendingScript::Type, ScriptState*, v8::ScriptCompiler::CompileOptions, WebTaskRunner*);
 
     void streamingComplete();
     void notifyFinishedToClient();
 
-    static bool startStreamingInternal(PendingScript&, PendingScript::Type, Settings*, ScriptState*);
+    static bool startStreamingInternal(PendingScript&, PendingScript::Type, Settings*, ScriptState*, WebTaskRunner*);
 
     // This pointer is weak. If PendingScript and its Resource are deleted
     // before ScriptStreamer, PendingScript will notify ScriptStreamer of its
@@ -149,6 +150,8 @@
 
     // Encoding of the streamed script. Saved for sanity checking purposes.
     v8::ScriptCompiler::StreamedSource::Encoding m_encoding;
+
+    OwnPtr<WebTaskRunner> m_loadingTaskRunner;
 };
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptStreamerTest.cpp b/third_party/WebKit/Source/bindings/core/v8/ScriptStreamerTest.cpp
index 62d9c84c..cbfdd8c 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptStreamerTest.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptStreamerTest.cpp
@@ -18,6 +18,7 @@
 #include "platform/heap/Handle.h"
 #include "platform/testing/UnitTestHelpers.h"
 #include "public/platform/Platform.h"
+#include "public/platform/WebScheduler.h"
 
 #include <gtest/gtest.h>
 #include <v8.h>
@@ -64,7 +65,8 @@
 class ScriptStreamingTest : public ::testing::Test {
 public:
     ScriptStreamingTest()
-        : m_scope(v8::Isolate::GetCurrent())
+        : m_loadingTaskRunner(Platform::current()->currentThread()->scheduler()->loadingTaskRunner())
+        , m_scope(v8::Isolate::GetCurrent())
         , m_settings(Settings::create())
         , m_resourceRequest("http://www.streaming-test.com/")
         , m_resource(new ScriptResource(m_resourceRequest, "UTF-8"))
@@ -116,6 +118,7 @@
         testing::runPendingTasks();
     }
 
+    WebTaskRunner* m_loadingTaskRunner; // NOT OWNED
     V8TestingScope m_scope;
     OwnPtr<Settings> m_settings;
     // The Resource and PendingScript where we stream from. These don't really
@@ -142,7 +145,7 @@
 TEST_F(ScriptStreamingTest, CompilingStreamedScript)
 {
     // Test that we can successfully compile a streamed script.
-    ScriptStreamer::startStreaming(pendingScript(), PendingScript::ParsingBlocking, m_settings.get(), m_scope.scriptState());
+    ScriptStreamer::startStreaming(pendingScript(), PendingScript::ParsingBlocking, m_settings.get(), m_scope.scriptState(), m_loadingTaskRunner);
     TestScriptResourceClient client;
     pendingScript().watchForLoad(&client);
 
@@ -173,7 +176,7 @@
     // Test that scripts with parse errors are handled properly. In those cases,
     // the V8 side typically finished before loading finishes: make sure we
     // handle it gracefully.
-    ScriptStreamer::startStreaming(pendingScript(), PendingScript::ParsingBlocking, m_settings.get(), m_scope.scriptState());
+    ScriptStreamer::startStreaming(pendingScript(), PendingScript::ParsingBlocking, m_settings.get(), m_scope.scriptState(), m_loadingTaskRunner);
     TestScriptResourceClient client;
     pendingScript().watchForLoad(&client);
     appendData("function foo() {");
@@ -205,7 +208,7 @@
 {
     // Test that the upper layers (PendingScript and up) can be ramped down
     // while streaming is ongoing, and ScriptStreamer handles it gracefully.
-    ScriptStreamer::startStreaming(pendingScript(), PendingScript::ParsingBlocking, m_settings.get(), m_scope.scriptState());
+    ScriptStreamer::startStreaming(pendingScript(), PendingScript::ParsingBlocking, m_settings.get(), m_scope.scriptState(), m_loadingTaskRunner);
     TestScriptResourceClient client;
     pendingScript().watchForLoad(&client);
     appendData("function foo() {");
@@ -234,7 +237,7 @@
     // is suppressed (V8 doesn't parse while the script is loading), and the
     // upper layer (ScriptResourceClient) should get a notification when the
     // script is loaded.
-    ScriptStreamer::startStreaming(pendingScript(), PendingScript::ParsingBlocking, m_settings.get(), m_scope.scriptState());
+    ScriptStreamer::startStreaming(pendingScript(), PendingScript::ParsingBlocking, m_settings.get(), m_scope.scriptState(), m_loadingTaskRunner);
     TestScriptResourceClient client;
     pendingScript().watchForLoad(&client);
     appendData("function foo() {");
@@ -263,7 +266,7 @@
     // Empty scripts should also be streamed properly, that is, the upper layer
     // (ScriptResourceClient) should be notified when an empty script has been
     // loaded.
-    ScriptStreamer::startStreaming(pendingScript(), PendingScript::ParsingBlocking, m_settings.get(), m_scope.scriptState());
+    ScriptStreamer::startStreaming(pendingScript(), PendingScript::ParsingBlocking, m_settings.get(), m_scope.scriptState(), m_loadingTaskRunner);
     TestScriptResourceClient client;
     pendingScript().watchForLoad(&client);
 
@@ -284,7 +287,7 @@
     // Small scripts shouldn't be streamed.
     ScriptStreamer::setSmallScriptThresholdForTesting(100);
 
-    ScriptStreamer::startStreaming(pendingScript(), PendingScript::ParsingBlocking, m_settings.get(), m_scope.scriptState());
+    ScriptStreamer::startStreaming(pendingScript(), PendingScript::ParsingBlocking, m_settings.get(), m_scope.scriptState(), m_loadingTaskRunner);
     TestScriptResourceClient client;
     pendingScript().watchForLoad(&client);
 
@@ -308,7 +311,7 @@
     // chunk is small.
     ScriptStreamer::setSmallScriptThresholdForTesting(100);
 
-    ScriptStreamer::startStreaming(pendingScript(), PendingScript::ParsingBlocking, m_settings.get(), m_scope.scriptState());
+    ScriptStreamer::startStreaming(pendingScript(), PendingScript::ParsingBlocking, m_settings.get(), m_scope.scriptState(), m_loadingTaskRunner);
     TestScriptResourceClient client;
     pendingScript().watchForLoad(&client);
 
@@ -338,7 +341,7 @@
     // loading it.
     m_resource->setEncoding("windows-1252");
 
-    ScriptStreamer::startStreaming(pendingScript(), PendingScript::ParsingBlocking, m_settings.get(), m_scope.scriptState());
+    ScriptStreamer::startStreaming(pendingScript(), PendingScript::ParsingBlocking, m_settings.get(), m_scope.scriptState(), m_loadingTaskRunner);
     TestScriptResourceClient client;
     pendingScript().watchForLoad(&client);
 
@@ -367,7 +370,7 @@
     // will also affect encoding detection.
     m_resource->setEncoding("windows-1252"); // This encoding is wrong on purpose.
 
-    ScriptStreamer::startStreaming(pendingScript(), PendingScript::ParsingBlocking, m_settings.get(), m_scope.scriptState());
+    ScriptStreamer::startStreaming(pendingScript(), PendingScript::ParsingBlocking, m_settings.get(), m_scope.scriptState(), m_loadingTaskRunner);
     TestScriptResourceClient client;
     pendingScript().watchForLoad(&client);
 
diff --git a/third_party/WebKit/Source/core/dom/Document.cpp b/third_party/WebKit/Source/core/dom/Document.cpp
index e5202e1..a8de8a5 100644
--- a/third_party/WebKit/Source/core/dom/Document.cpp
+++ b/third_party/WebKit/Source/core/dom/Document.cpp
@@ -5693,6 +5693,13 @@
     return true;
 }
 
+WebTaskRunner* Document::loadingTaskRunner() const
+{
+    if (frame())
+        return frame()->frameScheduler()->loadingTaskRunner();
+    return Platform::current()->currentThread()->scheduler()->loadingTaskRunner();
+}
+
 DEFINE_TRACE(Document)
 {
 #if ENABLE(OILPAN)
diff --git a/third_party/WebKit/Source/core/dom/Document.h b/third_party/WebKit/Source/core/dom/Document.h
index 6e3c490..cf8a131 100644
--- a/third_party/WebKit/Source/core/dom/Document.h
+++ b/third_party/WebKit/Source/core/dom/Document.h
@@ -1050,6 +1050,8 @@
     using WeakDocumentSet = WillBeHeapHashSet<RawPtrWillBeWeakMember<Document>>;
     static WeakDocumentSet& liveDocumentSet();
 
+    WebTaskRunner* loadingTaskRunner() const;
+
 protected:
     Document(const DocumentInit&, DocumentClassFlags = DefaultDocumentClass);
 
diff --git a/third_party/WebKit/Source/core/dom/ScriptLoader.cpp b/third_party/WebKit/Source/core/dom/ScriptLoader.cpp
index e63ea29d..8f8b617 100644
--- a/third_party/WebKit/Source/core/dom/ScriptLoader.cpp
+++ b/third_party/WebKit/Source/core/dom/ScriptLoader.cpp
@@ -50,6 +50,7 @@
 #include "core/svg/SVGScriptElement.h"
 #include "platform/MIMETypeRegistry.h"
 #include "platform/weborigin/SecurityOrigin.h"
+#include "public/platform/WebFrameScheduler.h"
 #include "wtf/StdLibExtras.h"
 #include "wtf/text/StringBuilder.h"
 #include "wtf/text/StringHash.h"
@@ -259,7 +260,7 @@
         if (frame) {
             ScriptState* scriptState = ScriptState::forMainWorld(frame);
             if (scriptState->contextIsValid())
-                ScriptStreamer::startStreaming(m_pendingScript, PendingScript::Async, frame->settings(), scriptState);
+                ScriptStreamer::startStreaming(m_pendingScript, PendingScript::Async, frame->settings(), scriptState, frame->frameScheduler()->loadingTaskRunner());
         }
         contextDocument->scriptRunner()->queueScriptForExecution(this, ScriptRunner::ASYNC_EXECUTION);
         // Note that watchForLoad can immediately call notifyFinished.
diff --git a/third_party/WebKit/Source/core/dom/ScriptRunnerTest.cpp b/third_party/WebKit/Source/core/dom/ScriptRunnerTest.cpp
index 6db3012..18683001 100644
--- a/third_party/WebKit/Source/core/dom/ScriptRunnerTest.cpp
+++ b/third_party/WebKit/Source/core/dom/ScriptRunnerTest.cpp
@@ -72,7 +72,7 @@
     explicit MockWebTaskRunner(Deque<OwnPtr<WebTaskRunner::Task>>* tasks) : m_tasks(tasks) { }
     ~MockWebTaskRunner() override { }
 
-    virtual void postTask(const WebTraceLocation&, Task* task)
+    void postTask(const WebTraceLocation&, Task* task) override
     {
         m_tasks->append(adoptPtr(task));
     }
@@ -82,6 +82,12 @@
         ASSERT_NOT_REACHED();
     }
 
+    WebTaskRunner* clone() override
+    {
+        ASSERT_NOT_REACHED();
+        return nullptr;
+    }
+
     Deque<OwnPtr<WebTaskRunner::Task>>* m_tasks; // NOT OWNED
 };
 
diff --git a/third_party/WebKit/Source/core/fetch/FetchContext.h b/third_party/WebKit/Source/core/fetch/FetchContext.h
index dbcb39b..243bf2b 100644
--- a/third_party/WebKit/Source/core/fetch/FetchContext.h
+++ b/third_party/WebKit/Source/core/fetch/FetchContext.h
@@ -48,6 +48,7 @@
 class ResourceResponse;
 class ResourceRequest;
 class ResourceTimingInfo;
+class WebTaskRunner;
 
 enum FetchResourceType {
     FetchMainResource,
@@ -106,6 +107,7 @@
 
     virtual bool fetchIncreasePriorities() const { return false; }
     virtual ResourceLoadPriority modifyPriorityForExperiments(ResourceLoadPriority priority, Resource::Type, const FetchRequest&) { return priority; }
+    virtual WebTaskRunner* loadingTaskRunner() const { return nullptr; }
 
 protected:
     FetchContext() { }
diff --git a/third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp b/third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp
index 8e09575..bea44b3 100644
--- a/third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp
+++ b/third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp
@@ -172,6 +172,14 @@
 #endif
 }
 
+WebTaskRunner* ResourceFetcher::loadingTaskRunner()
+{
+    if (!m_context)
+        return nullptr;
+
+    return m_context->loadingTaskRunner();
+}
+
 Resource* ResourceFetcher::cachedResource(const KURL& resourceURL) const
 {
     KURL url = MemoryCache::removeFragmentIdentifierIfNeeded(resourceURL);
diff --git a/third_party/WebKit/Source/core/fetch/ResourceFetcher.h b/third_party/WebKit/Source/core/fetch/ResourceFetcher.h
index 670f1ca..26cdfdc 100644
--- a/third_party/WebKit/Source/core/fetch/ResourceFetcher.h
+++ b/third_party/WebKit/Source/core/fetch/ResourceFetcher.h
@@ -147,6 +147,8 @@
     bool clientDefersImage(const KURL&) const;
     void determineRequestContext(ResourceRequest&, Resource::Type);
 
+    WebTaskRunner* loadingTaskRunner();
+
 private:
     friend class ResourceCacheValidationSuppressor;
 
diff --git a/third_party/WebKit/Source/core/fetch/ResourceLoader.cpp b/third_party/WebKit/Source/core/fetch/ResourceLoader.cpp
index 800e826..935c7e8 100644
--- a/third_party/WebKit/Source/core/fetch/ResourceLoader.cpp
+++ b/third_party/WebKit/Source/core/fetch/ResourceLoader.cpp
@@ -142,6 +142,7 @@
 
     m_loader = adoptPtr(Platform::current()->createURLLoader());
     ASSERT(m_loader);
+    m_loader->setLoadingTaskRunner(m_fetcher->loadingTaskRunner());
     WrappedResourceRequest wrappedRequest(m_request);
     m_loader->loadAsynchronously(wrappedRequest, this);
 }
diff --git a/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.cpp b/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.cpp
index 3589b67..3e92482 100644
--- a/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.cpp
+++ b/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.cpp
@@ -33,7 +33,7 @@
 #include "platform/Task.h"
 #include "platform/ThreadSafeFunctional.h"
 #include "public/platform/Platform.h"
-#include "public/platform/WebScheduler.h"
+#include "public/platform/WebTaskRunner.h"
 #include "wtf/text/TextPosition.h"
 
 namespace blink {
@@ -81,9 +81,9 @@
 
 #endif
 
-void BackgroundHTMLParser::start(PassRefPtr<WeakReference<BackgroundHTMLParser>> reference, PassOwnPtr<Configuration> config, WebScheduler* scheduler)
+void BackgroundHTMLParser::start(PassRefPtr<WeakReference<BackgroundHTMLParser>> reference, PassOwnPtr<Configuration> config, WebTaskRunner* loadingTaskRunner)
 {
-    new BackgroundHTMLParser(reference, config, scheduler);
+    new BackgroundHTMLParser(reference, config, loadingTaskRunner);
     // Caller must free by calling stop().
 }
 
@@ -93,7 +93,7 @@
 {
 }
 
-BackgroundHTMLParser::BackgroundHTMLParser(PassRefPtr<WeakReference<BackgroundHTMLParser>> reference, PassOwnPtr<Configuration> config, WebScheduler* scheduler)
+BackgroundHTMLParser::BackgroundHTMLParser(PassRefPtr<WeakReference<BackgroundHTMLParser>> reference, PassOwnPtr<Configuration> config, WebTaskRunner* loadingTaskRunner)
     : m_weakFactory(reference, this)
     , m_token(adoptPtr(new HTMLToken))
     , m_tokenizer(HTMLTokenizer::create(config->options))
@@ -106,7 +106,7 @@
     , m_xssAuditor(config->xssAuditor.release())
     , m_preloadScanner(config->preloadScanner.release())
     , m_decoder(config->decoder.release())
-    , m_scheduler(scheduler)
+    , m_loadingTaskRunner(adoptPtr(loadingTaskRunner->clone()))
     , m_startingScript(false)
 {
     ASSERT(m_outstandingTokenLimit > 0);
@@ -157,7 +157,7 @@
         m_lastSeenEncodingData = encodingData;
 
         m_xssAuditor->setEncoding(encodingData.encoding());
-        m_scheduler->loadingTaskRunner()->postTask(
+        m_loadingTaskRunner->postTask(
             FROM_HERE,
             threadSafeBind(&HTMLDocumentParser::didReceiveEncodingDataFromBackgroundParser, AllowCrossThreadAccess(m_parser), encodingData));
     }
@@ -291,7 +291,7 @@
     chunk->startingScript = m_startingScript;
     m_startingScript = false;
 
-    m_scheduler->loadingTaskRunner()->postTask(
+    m_loadingTaskRunner->postTask(
         FROM_HERE,
         new Task(threadSafeBind(&HTMLDocumentParser::didReceiveParsedChunkFromBackgroundParser, AllowCrossThreadAccess(m_parser), chunk.release())));
 
diff --git a/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.h b/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.h
index 6922c310..f07ad2e 100644
--- a/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.h
+++ b/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.h
@@ -42,7 +42,7 @@
 
 class HTMLDocumentParser;
 class XSSAuditor;
-class WebScheduler;
+class WebTaskRunner;
 
 class BackgroundHTMLParser {
     WTF_MAKE_FAST_ALLOCATED(BackgroundHTMLParser);
@@ -63,7 +63,7 @@
         size_t pendingTokenLimit;
     };
 
-    static void start(PassRefPtr<WeakReference<BackgroundHTMLParser>>, PassOwnPtr<Configuration>, WebScheduler*);
+    static void start(PassRefPtr<WeakReference<BackgroundHTMLParser>>, PassOwnPtr<Configuration>, WebTaskRunner*);
 
     struct Checkpoint {
         WTF_MAKE_FAST_ALLOCATED(CheckPoint);
@@ -90,7 +90,7 @@
     void forcePlaintextForTextDocument();
 
 private:
-    BackgroundHTMLParser(PassRefPtr<WeakReference<BackgroundHTMLParser>>, PassOwnPtr<Configuration>, WebScheduler*);
+    BackgroundHTMLParser(PassRefPtr<WeakReference<BackgroundHTMLParser>>, PassOwnPtr<Configuration>, WebTaskRunner*);
     ~BackgroundHTMLParser();
 
     void appendDecodedBytes(const String&);
@@ -118,7 +118,7 @@
     OwnPtr<TokenPreloadScanner> m_preloadScanner;
     OwnPtr<TextResourceDecoder> m_decoder;
     DocumentEncodingData m_lastSeenEncodingData;
-    WebScheduler* m_scheduler; // NOT OWNED, scheduler will outlive BackgroundHTMLParser
+    OwnPtr<WebTaskRunner> m_loadingTaskRunner;
 
     bool m_startingScript;
 };
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp b/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp
index 070fd43..07a2709 100644
--- a/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp
+++ b/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp
@@ -50,6 +50,7 @@
 #include "platform/TraceEvent.h"
 #include "platform/heap/Handle.h"
 #include "public/platform/Platform.h"
+#include "public/platform/WebFrameScheduler.h"
 #include "public/platform/WebScheduler.h"
 #include "public/platform/WebThread.h"
 #include "wtf/RefCounted.h"
@@ -143,7 +144,8 @@
     , m_tokenizer(syncPolicy == ForceSynchronousParsing ? HTMLTokenizer::create(m_options) : nullptr)
     , m_scriptRunner(HTMLScriptRunner::create(&document, this))
     , m_treeBuilder(HTMLTreeBuilder::create(this, &document, parserContentPolicy(), reportErrors, m_options))
-    , m_parserScheduler(HTMLParserScheduler::create(this))
+    , m_loadingTaskRunner(adoptPtr(document.loadingTaskRunner()->clone()))
+    , m_parserScheduler(HTMLParserScheduler::create(this, m_loadingTaskRunner.get()))
     , m_xssAuditorDelegate(&document)
     , m_weakFactory(this)
     , m_preloader(HTMLResourcePreloader::create(document))
@@ -166,6 +168,7 @@
     , m_token(adoptPtr(new HTMLToken))
     , m_tokenizer(HTMLTokenizer::create(m_options))
     , m_treeBuilder(HTMLTreeBuilder::create(this, fragment, contextElement, this->parserContentPolicy(), m_options))
+    , m_loadingTaskRunner(adoptPtr(fragment->document().loadingTaskRunner()->clone()))
     , m_xssAuditorDelegate(&fragment->document())
     , m_weakFactory(this)
     , m_shouldUseThreading(false)
@@ -801,7 +804,7 @@
     ASSERT(config->xssAuditor->isSafeToSendToAnotherThread());
     ASSERT(config->preloadScanner->isSafeToSendToAnotherThread());
     HTMLParserThread::shared()->postTask(threadSafeBind(&BackgroundHTMLParser::start, reference.release(), config.release(),
-        AllowCrossThreadAccess(Platform::current()->currentThread()->scheduler())));
+        AllowCrossThreadAccess(m_loadingTaskRunner.get())));
 }
 
 void HTMLDocumentParser::stopBackgroundParser()
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.h b/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.h
index 8fba554..f41d9b03 100644
--- a/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.h
+++ b/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.h
@@ -187,6 +187,7 @@
     OwnPtrWillBeMember<HTMLTreeBuilder> m_treeBuilder;
     OwnPtr<HTMLPreloadScanner> m_preloadScanner;
     OwnPtr<HTMLPreloadScanner> m_insertionPreloadScanner;
+    OwnPtr<WebTaskRunner> m_loadingTaskRunner;
     OwnPtr<HTMLParserScheduler> m_parserScheduler;
     HTMLSourceTracker m_sourceTracker;
     TextPosition m_textPosition;
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLParserScheduler.cpp b/third_party/WebKit/Source/core/html/parser/HTMLParserScheduler.cpp
index c15e43b5..58a3ded9 100644
--- a/third_party/WebKit/Source/core/html/parser/HTMLParserScheduler.cpp
+++ b/third_party/WebKit/Source/core/html/parser/HTMLParserScheduler.cpp
@@ -82,9 +82,9 @@
     m_processedElementTokens += count;
 }
 
-HTMLParserScheduler::HTMLParserScheduler(HTMLDocumentParser* parser)
+HTMLParserScheduler::HTMLParserScheduler(HTMLDocumentParser* parser, WebTaskRunner* loadingTaskRunner)
     : m_parser(parser)
-    , m_loadingTaskRunner(Platform::current()->currentThread()->scheduler()->loadingTaskRunner())
+    , m_loadingTaskRunner(adoptPtr(loadingTaskRunner->clone()))
     , m_cancellableContinueParse(CancellableTaskFactory::create(this, &HTMLParserScheduler::continueParsing))
     , m_isSuspendedWithActiveTimer(false)
 {
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLParserScheduler.h b/third_party/WebKit/Source/core/html/parser/HTMLParserScheduler.h
index d7878dbc..ad3ccaa 100644
--- a/third_party/WebKit/Source/core/html/parser/HTMLParserScheduler.h
+++ b/third_party/WebKit/Source/core/html/parser/HTMLParserScheduler.h
@@ -36,6 +36,7 @@
 
 class Document;
 class HTMLDocumentParser;
+class WebTaskRunner;
 
 class ActiveParserSession : public NestingLevelIncrementer {
     STACK_ALLOCATED();
@@ -72,9 +73,9 @@
 class HTMLParserScheduler {
     WTF_MAKE_NONCOPYABLE(HTMLParserScheduler); WTF_MAKE_FAST_ALLOCATED(HTMLParserScheduler);
 public:
-    static PassOwnPtr<HTMLParserScheduler> create(HTMLDocumentParser* parser)
+    static PassOwnPtr<HTMLParserScheduler> create(HTMLDocumentParser* parser, WebTaskRunner* loadingTaskRunner)
     {
-        return adoptPtr(new HTMLParserScheduler(parser));
+        return adoptPtr(new HTMLParserScheduler(parser, loadingTaskRunner));
     }
     ~HTMLParserScheduler();
 
@@ -98,13 +99,13 @@
     void detach(); // Clear active tasks if any.
 
 private:
-    explicit HTMLParserScheduler(HTMLDocumentParser*);
+    HTMLParserScheduler(HTMLDocumentParser*, WebTaskRunner*);
 
     bool shouldYield(const SpeculationsPumpSession&, bool startingScript) const;
     void continueParsing();
 
     HTMLDocumentParser* m_parser;
-    WebTaskRunner* m_loadingTaskRunner; // NOT OWNED
+    OwnPtr<WebTaskRunner> m_loadingTaskRunner;
 
     OwnPtr<CancellableTaskFactory> m_cancellableContinueParse;
     bool m_isSuspendedWithActiveTimer;
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLScriptRunner.cpp b/third_party/WebKit/Source/core/html/parser/HTMLScriptRunner.cpp
index 3d80848..35b1258 100644
--- a/third_party/WebKit/Source/core/html/parser/HTMLScriptRunner.cpp
+++ b/third_party/WebKit/Source/core/html/parser/HTMLScriptRunner.cpp
@@ -40,6 +40,7 @@
 #include "core/html/parser/NestingLevelIncrementer.h"
 #include "platform/NotImplemented.h"
 #include "public/platform/Platform.h"
+#include "public/platform/WebFrameScheduler.h"
 
 namespace blink {
 
@@ -287,7 +288,7 @@
         if (m_document->frame()) {
             ScriptState* scriptState = ScriptState::forMainWorld(m_document->frame());
             if (scriptState->contextIsValid())
-                ScriptStreamer::startStreaming(m_parserBlockingScript, PendingScript::ParsingBlocking, m_document->frame()->settings(), scriptState);
+                ScriptStreamer::startStreaming(m_parserBlockingScript, PendingScript::ParsingBlocking, m_document->frame()->settings(), scriptState, m_document->loadingTaskRunner());
         }
 
         m_parserBlockingScript.watchForLoad(this);
@@ -303,7 +304,7 @@
     if (m_document->frame() && !pendingScript.isReady()) {
         ScriptState* scriptState = ScriptState::forMainWorld(m_document->frame());
         if (scriptState->contextIsValid())
-            ScriptStreamer::startStreaming(pendingScript, PendingScript::Deferred, m_document->frame()->settings(), scriptState);
+            ScriptStreamer::startStreaming(pendingScript, PendingScript::Deferred, m_document->frame()->settings(), scriptState, m_document->loadingTaskRunner());
     }
 
     ASSERT(pendingScript.resource());
diff --git a/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp b/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp
index 3404185..644098b 100644
--- a/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp
+++ b/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp
@@ -64,6 +64,7 @@
 #include "platform/network/ResourceTimingInfo.h"
 #include "platform/weborigin/SchemeRegistry.h"
 #include "platform/weborigin/SecurityPolicy.h"
+#include "public/platform/WebFrameScheduler.h"
 
 #include <algorithm>
 
@@ -733,6 +734,11 @@
     return static_cast<ResourceLoadPriority>(modifiedPriority);
 }
 
+WebTaskRunner* FrameFetchContext::loadingTaskRunner() const
+{
+    return frame()->frameScheduler()->loadingTaskRunner();
+}
+
 DEFINE_TRACE(FrameFetchContext)
 {
     visitor->trace(m_document);
diff --git a/third_party/WebKit/Source/core/loader/FrameFetchContext.h b/third_party/WebKit/Source/core/loader/FrameFetchContext.h
index de5c5165..a71afae 100644
--- a/third_party/WebKit/Source/core/loader/FrameFetchContext.h
+++ b/third_party/WebKit/Source/core/loader/FrameFetchContext.h
@@ -109,6 +109,8 @@
     void countClientHintsResourceWidth() override;
     void countClientHintsViewportWidth() override;
 
+    WebTaskRunner* loadingTaskRunner() const override;
+
     DECLARE_VIRTUAL_TRACE();
 
 private:
diff --git a/third_party/WebKit/Source/core/loader/FrameLoader.cpp b/third_party/WebKit/Source/core/loader/FrameLoader.cpp
index 05fe067..c3abf16 100644
--- a/third_party/WebKit/Source/core/loader/FrameLoader.cpp
+++ b/third_party/WebKit/Source/core/loader/FrameLoader.cpp
@@ -1072,6 +1072,7 @@
     if (m_frame->document())
         m_frame->document()->detach();
     m_documentLoader = m_provisionalDocumentLoader.release();
+    m_frame->updateFrameSecurityOrigin();
 
     return true;
 }
diff --git a/third_party/WebKit/Source/platform/TimerTest.cpp b/third_party/WebKit/Source/platform/TimerTest.cpp
index 91b62dc..a75a16a 100644
--- a/third_party/WebKit/Source/platform/TimerTest.cpp
+++ b/third_party/WebKit/Source/platform/TimerTest.cpp
@@ -77,7 +77,7 @@
     explicit MockWebTaskRunner(std::priority_queue<DelayedTask>* timerTasks) : m_timerTasks(timerTasks) { }
     ~MockWebTaskRunner() override { }
 
-    virtual void postTask(const WebTraceLocation&, Task* task)
+    void postTask(const WebTraceLocation&, Task* task) override
     {
         m_timerTasks->push(DelayedTask(task, 0));
     }
@@ -87,6 +87,12 @@
         m_timerTasks->push(DelayedTask(task, delayMs * 0.001));
     }
 
+    WebTaskRunner* clone() override
+    {
+        ASSERT_NOT_REACHED();
+        return nullptr;
+    }
+
     std::priority_queue<DelayedTask>* m_timerTasks; // NOT OWNED
 };
 
diff --git a/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurfaceTest.cpp b/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurfaceTest.cpp
index 8cf1c048..abc94b7 100644
--- a/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurfaceTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurfaceTest.cpp
@@ -260,7 +260,7 @@
         MockWebTaskRunner() : m_task(0) { }
         ~MockWebTaskRunner() override { }
 
-        virtual void postTask(const WebTraceLocation&, Task* task)
+        void postTask(const WebTraceLocation&, Task* task) override
         {
             EXPECT_EQ((Task*)0, m_task);
             m_task = task;
@@ -268,6 +268,12 @@
 
         void postDelayedTask(const WebTraceLocation&, Task*, double delayMs) override { ASSERT_NOT_REACHED(); };
 
+        WebTaskRunner* clone() override
+        {
+            ASSERT_NOT_REACHED();
+            return nullptr;
+        }
+
         Task* m_task;
     };
 
diff --git a/third_party/WebKit/Source/web/AssociatedURLLoader.cpp b/third_party/WebKit/Source/web/AssociatedURLLoader.cpp
index 6170c8d..4c838f7 100644
--- a/third_party/WebKit/Source/web/AssociatedURLLoader.cpp
+++ b/third_party/WebKit/Source/web/AssociatedURLLoader.cpp
@@ -383,4 +383,9 @@
         m_loader->setDefersLoading(defersLoading);
 }
 
+void AssociatedURLLoader::setLoadingTaskRunner(blink::WebTaskRunner*)
+{
+    // TODO(alexclarke): Maybe support this one day if it proves worthwhile.
+}
+
 } // namespace blink
diff --git a/third_party/WebKit/Source/web/AssociatedURLLoader.h b/third_party/WebKit/Source/web/AssociatedURLLoader.h
index 41b0c26..6dcd06e 100644
--- a/third_party/WebKit/Source/web/AssociatedURLLoader.h
+++ b/third_party/WebKit/Source/web/AssociatedURLLoader.h
@@ -54,6 +54,7 @@
     void loadAsynchronously(const WebURLRequest&, WebURLLoaderClient*) override;
     void cancel() override;
     void setDefersLoading(bool) override;
+    void setLoadingTaskRunner(blink::WebTaskRunner*) override;
 
 private:
 
diff --git a/third_party/WebKit/public/platform/WebTaskRunner.h b/third_party/WebKit/public/platform/WebTaskRunner.h
index 4369ad9..6d12febc 100644
--- a/third_party/WebKit/public/platform/WebTaskRunner.h
+++ b/third_party/WebKit/public/platform/WebTaskRunner.h
@@ -28,11 +28,14 @@
 
     // Schedule a task to be run on the the associated WebThread.
     // Takes ownership of |Task|. Can be called from any thread.
-    virtual void postTask(const WebTraceLocation&, Task*) {}
+    virtual void postTask(const WebTraceLocation&, Task*) = 0;
 
     // Schedule a task to be run after |delayMs| on the the associated WebThread.
     // Takes ownership of |Task|. Can be called from any thread.
-    virtual void postDelayedTask(const WebTraceLocation&, Task*, double delayMs) {}
+    virtual void postDelayedTask(const WebTraceLocation&, Task*, double delayMs) = 0;
+
+    // Returns a clone of the WebTaskRunner.
+    virtual WebTaskRunner* clone() = 0;
 
 #ifdef INSIDE_BLINK
     // Helpers for posting bound functions as tasks.
diff --git a/third_party/WebKit/public/platform/WebURLLoader.h b/third_party/WebKit/public/platform/WebURLLoader.h
index eada222..3a91423 100644
--- a/third_party/WebKit/public/platform/WebURLLoader.h
+++ b/third_party/WebKit/public/platform/WebURLLoader.h
@@ -37,6 +37,7 @@
 namespace blink {
 
 class WebData;
+class WebTaskRunner;
 class WebThreadedDataReceiver;
 class WebURLLoaderClient;
 class WebURLResponse;
@@ -78,6 +79,10 @@
     // of the data receiver is assumed by the WebURLLoader and the receiver should
     // be deleted on the main thread when no longer needed.
     virtual bool attachThreadedDataReceiver(WebThreadedDataReceiver*) { return false; }
+
+    // Sets the task runner for which any loading tasks should be posted on.
+    // Takes ownership of the WebTaskRunner.
+    virtual void setLoadingTaskRunner(WebTaskRunner*) = 0;
 };
 
 } // namespace blink