Skip to content

Commit

Permalink
fix: sourcemaps not loading with network service (#21494)
Browse files Browse the repository at this point in the history
  • Loading branch information
trop[bot] authored and deepak1556 committed Dec 13, 2019
1 parent 8f728af commit 96e7b44
Showing 1 changed file with 140 additions and 36 deletions.
176 changes: 140 additions & 36 deletions shell/browser/ui/inspectable_web_contents_impl.cc
Expand Up @@ -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"
Expand Down Expand Up @@ -61,7 +63,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";
Expand Down Expand Up @@ -149,29 +151,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::ResourceResponseHead& response_head) {
response_headers_ = response_head.headers;
Expand All @@ -198,21 +258,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));
}
Expand All @@ -221,9 +294,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.
Expand Down Expand Up @@ -527,19 +605,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,
Expand Down

0 comments on commit 96e7b44

Please sign in to comment.