Browse Source

fix: sourcemaps not loading with network service (#21493)

Backports https://chromium-review.googlesource.com/c/chromium/src/+/1525270
Backports https://chromium-review.googlesource.com/c/chromium/src/+/1852212
trop[bot] 5 years ago
parent
commit
696c94c08a
1 changed files with 140 additions and 36 deletions
  1. 140 36
      shell/browser/ui/inspectable_web_contents_impl.cc

+ 140 - 36
shell/browser/ui/inspectable_web_contents_impl.cc

@@ -27,10 +27,12 @@
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/file_select_listener.h"
+#include "content/public/browser/file_url_loader.h"
 #include "content/public/browser/host_zoom_map.h"
 #include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_view_host.h"
+#include "content/public/browser/shared_cors_origin_access_list.h"
 #include "content/public/browser/storage_partition.h"
 #include "content/public/common/user_agent.h"
 #include "ipc/ipc_channel.h"
@@ -62,7 +64,7 @@ const char kChromeUIDevToolsURL[] =
     "textColor=rgba(0,0,0,1)&"
     "experiments=true";
 const char kChromeUIDevToolsRemoteFrontendBase[] =
-    "https://devtools-frontend.appspot.com/";
+    "https://chrome-devtools-frontend.appspot.com/";
 const char kChromeUIDevToolsRemoteFrontendPath[] = "serve_file";
 
 const char kDevToolsBoundsPref[] = "electron.devtools.bounds";
@@ -150,29 +152,87 @@ GURL GetDevToolsURL(bool can_dock) {
   return GURL(url_string);
 }
 
+constexpr base::TimeDelta kInitialBackoffDelay =
+    base::TimeDelta::FromMilliseconds(250);
+constexpr base::TimeDelta kMaxBackoffDelay = base::TimeDelta::FromSeconds(10);
+
 }  // namespace
 
 class InspectableWebContentsImpl::NetworkResourceLoader
     : public network::SimpleURLLoaderStreamConsumer {
  public:
-  NetworkResourceLoader(int stream_id,
-                        InspectableWebContentsImpl* bindings,
-                        std::unique_ptr<network::SimpleURLLoader> loader,
-                        network::mojom::URLLoaderFactory* url_loader_factory,
-                        const DispatchCallback& callback)
+  class URLLoaderFactoryHolder {
+   public:
+    network::mojom::URLLoaderFactory* get() {
+      return ptr_.get() ? ptr_.get() : refptr_.get();
+    }
+    void operator=(std::unique_ptr<network::mojom::URLLoaderFactory>&& ptr) {
+      ptr_ = std::move(ptr);
+    }
+    void operator=(scoped_refptr<network::SharedURLLoaderFactory>&& refptr) {
+      refptr_ = std::move(refptr);
+    }
+
+   private:
+    std::unique_ptr<network::mojom::URLLoaderFactory> ptr_;
+    scoped_refptr<network::SharedURLLoaderFactory> refptr_;
+  };
+
+  static void Create(int stream_id,
+                     InspectableWebContentsImpl* bindings,
+                     const network::ResourceRequest& resource_request,
+                     const net::NetworkTrafficAnnotationTag& traffic_annotation,
+                     URLLoaderFactoryHolder url_loader_factory,
+                     const DispatchCallback& callback,
+                     base::TimeDelta retry_delay = base::TimeDelta()) {
+    auto resource_loader =
+        std::make_unique<InspectableWebContentsImpl::NetworkResourceLoader>(
+            stream_id, bindings, resource_request, traffic_annotation,
+            std::move(url_loader_factory), callback, retry_delay);
+    bindings->loaders_.insert(std::move(resource_loader));
+  }
+
+  NetworkResourceLoader(
+      int stream_id,
+      InspectableWebContentsImpl* bindings,
+      const network::ResourceRequest& resource_request,
+      const net::NetworkTrafficAnnotationTag& traffic_annotation,
+      URLLoaderFactoryHolder url_loader_factory,
+      const DispatchCallback& callback,
+      base::TimeDelta delay)
       : stream_id_(stream_id),
         bindings_(bindings),
-        loader_(std::move(loader)),
-        callback_(callback) {
+        resource_request_(resource_request),
+        traffic_annotation_(traffic_annotation),
+        loader_(network::SimpleURLLoader::Create(
+            std::make_unique<network::ResourceRequest>(resource_request),
+            traffic_annotation)),
+        url_loader_factory_(std::move(url_loader_factory)),
+        callback_(callback),
+        retry_delay_(delay) {
     loader_->SetOnResponseStartedCallback(base::BindOnce(
         &NetworkResourceLoader::OnResponseStarted, base::Unretained(this)));
-    loader_->DownloadAsStream(url_loader_factory, this);
+    timer_.Start(FROM_HERE, delay,
+                 base::BindRepeating(&NetworkResourceLoader::DownloadAsStream,
+                                     base::Unretained(this)));
   }
 
   NetworkResourceLoader(const NetworkResourceLoader&) = delete;
   NetworkResourceLoader& operator=(const NetworkResourceLoader&) = delete;
 
  private:
+  void DownloadAsStream() {
+    loader_->DownloadAsStream(url_loader_factory_.get(), this);
+  }
+
+  base::TimeDelta GetNextExponentialBackoffDelay(const base::TimeDelta& delta) {
+    if (delta.is_zero()) {
+      return kInitialBackoffDelay;
+    } else {
+      return delta * 1.3;
+    }
+  }
+
   void OnResponseStarted(const GURL& final_url,
                          const network::mojom::URLResponseHead& response_head) {
     response_headers_ = response_head.headers;
@@ -199,21 +259,34 @@ class InspectableWebContentsImpl::NetworkResourceLoader
   }
 
   void OnComplete(bool success) override {
-    base::DictionaryValue response;
-    response.SetInteger("statusCode", response_headers_
-                                          ? response_headers_->response_code()
-                                          : 200);
-
-    auto headers = std::make_unique<base::DictionaryValue>();
-    size_t iterator = 0;
-    std::string name;
-    std::string value;
-    while (response_headers_ &&
-           response_headers_->EnumerateHeaderLines(&iterator, &name, &value))
-      headers->SetString(name, value);
-
-    response.Set("headers", std::move(headers));
-    callback_.Run(&response);
+    if (!success && loader_->NetError() == net::ERR_INSUFFICIENT_RESOURCES &&
+        retry_delay_ < kMaxBackoffDelay) {
+      const base::TimeDelta delay =
+          GetNextExponentialBackoffDelay(retry_delay_);
+      LOG(WARNING) << "InspectableWebContentsImpl::NetworkResourceLoader id = "
+                   << stream_id_
+                   << " failed with insufficient resources, retrying in "
+                   << delay << "." << std::endl;
+      NetworkResourceLoader::Create(
+          stream_id_, bindings_, resource_request_, traffic_annotation_,
+          std::move(url_loader_factory_), callback_, delay);
+    } else {
+      base::DictionaryValue response;
+      response.SetInteger("statusCode", response_headers_
+                                            ? response_headers_->response_code()
+                                            : 200);
+
+      auto headers = std::make_unique<base::DictionaryValue>();
+      size_t iterator = 0;
+      std::string name;
+      std::string value;
+      while (response_headers_ &&
+             response_headers_->EnumerateHeaderLines(&iterator, &name, &value))
+        headers->SetString(name, value);
+
+      response.Set("headers", std::move(headers));
+      callback_.Run(&response);
+    }
 
     bindings_->loaders_.erase(bindings_->loaders_.find(this));
   }
@@ -222,9 +295,14 @@ class InspectableWebContentsImpl::NetworkResourceLoader
 
   const int stream_id_;
   InspectableWebContentsImpl* const bindings_;
+  const network::ResourceRequest resource_request_;
+  const net::NetworkTrafficAnnotationTag traffic_annotation_;
   std::unique_ptr<network::SimpleURLLoader> loader_;
+  URLLoaderFactoryHolder url_loader_factory_;
   DispatchCallback callback_;
   scoped_refptr<net::HttpResponseHeaders> response_headers_;
+  base::OneShotTimer timer_;
+  base::TimeDelta retry_delay_;
 };
 
 // Implemented separately on each platform.
@@ -528,19 +606,45 @@ void InspectableWebContentsImpl::LoadNetworkResource(
     return;
   }
 
-  auto resource_request = std::make_unique<network::ResourceRequest>();
-  resource_request->url = gurl;
-  resource_request->headers.AddHeadersFromString(headers);
-
-  auto* partition = content::BrowserContext::GetDefaultStoragePartition(
-      GetDevToolsWebContents()->GetBrowserContext());
-  auto factory = partition->GetURLLoaderFactoryForBrowserProcess();
+  // Create traffic annotation tag.
+  net::NetworkTrafficAnnotationTag traffic_annotation =
+      net::DefineNetworkTrafficAnnotation("devtools_network_resource", R"(
+        semantics {
+          sender: "Developer Tools"
+          description:
+            "When user opens Developer Tools, the browser may fetch additional "
+            "resources from the network to enrich the debugging experience "
+            "(e.g. source map resources)."
+          trigger: "User opens Developer Tools to debug a web page."
+          data: "Any resources requested by Developer Tools."
+          destination: WEBSITE
+        }
+        policy {
+          cookies_allowed: YES
+          cookies_store: "user"
+          setting:
+            "It's not possible to disable this feature from settings."
+        })");
+
+  network::ResourceRequest resource_request;
+  resource_request.url = gurl;
+  resource_request.site_for_cookies = gurl;
+  resource_request.headers.AddHeadersFromString(headers);
+
+  NetworkResourceLoader::URLLoaderFactoryHolder url_loader_factory;
+  if (gurl.SchemeIsFile()) {
+    url_loader_factory = content::CreateFileURLLoaderFactory(
+        base::FilePath() /* profile_path */,
+        nullptr /* shared_cors_origin_access_list */);
+  } else {
+    auto* partition = content::BrowserContext::GetDefaultStoragePartition(
+        GetDevToolsWebContents()->GetBrowserContext());
+    url_loader_factory = partition->GetURLLoaderFactoryForBrowserProcess();
+  }
 
-  auto simple_url_loader = network::SimpleURLLoader::Create(
-      std::move(resource_request), MISSING_TRAFFIC_ANNOTATION);
-  auto resource_loader = std::make_unique<NetworkResourceLoader>(
-      stream_id, this, std::move(simple_url_loader), factory.get(), callback);
-  loaders_.insert(std::move(resource_loader));
+  NetworkResourceLoader::Create(stream_id, this, resource_request,
+                                traffic_annotation,
+                                std::move(url_loader_factory), callback);
 }
 
 void InspectableWebContentsImpl::SetIsDocked(const DispatchCallback& callback,