feaf18e371
* chore: bump chromium in DEPS to 112.0.5576.0 * 4211172: Use the Mac ImageTransportSurface on iOS. https://chromium-review.googlesource.com/c/chromium/src/+/4211172 * 4191759: Reuse PrintBackend process from query for printing https://chromium-review.googlesource.com/c/chromium/src/+/4191759 * 4189718: Revert "[code health] Remove NotificationService use by SpellcheckService" https://chromium-review.googlesource.com/c/chromium/src/+/4189718 * 4216074: web_contents_delegate: remove content:: https://chromium-review.googlesource.com/c/chromium/src/+/4216074 * 4192284: ios: Add feature flag for PartitionAlloc. https://chromium-review.googlesource.com/c/chromium/src/+/4192284 * chore: bump chromium in DEPS to 112.0.5578.0 * 4211172: Use the Mac ImageTransportSurface on iOS. https://chromium-review.googlesource.com/c/chromium/src/+/4211172 * 4067682: Define ThirdPartyCookiesUserBypass runtime feature and plumb it through to URLRequest.cookie_setting_overrides. https://chromium-review.googlesource.com/c/chromium/src/+/4067682 * chore: fixup patch indices * 4218354: Disable the use of preserve_most on arm64 Windows https://chromium-review.googlesource.com/c/v8/v8/+/4218354 * chore: fixup patch indices * chore: bump chromium in DEPS to 112.0.5579.0 * chore: update patches * chore: bump chromium in DEPS to 112.0.5581.0 * chore: update patches * refactor: use modern base values in tracing Ref: https://chromium-review.googlesource.com/c/chromium/src/+/4210912 * refactor: remove GetFontLookupTableCacheDir Ref: https://chromium-review.googlesource.com/c/chromium/src/+/4191820 * refactor: base value type DICTIONARY replaced with DICT Ref: https://chromium-review.googlesource.com/c/chromium/src/+/4198081 * chore: add stub impls for WCO routing Refs: https://chromium-review.googlesource.com/c/chromium/src/+/4182690 * refactor: rename latency metrics Refs: https://chromium-review.googlesource.com/c/chromium/src/+/4048262 * refactor: add sanitized context to clipboard write Ref: https://chromium-review.googlesource.com/c/chromium/src/+/4178264 * refactor: s/Rect/WindowFeatures Ref: https://chromium-review.googlesource.com/c/chromium/src/+/4167001 * refacotr: switch mojom::NetworkHintsHandler to use SchemeHostPair instead of URL Ref: https://chromium-review.googlesource.com/c/chromium/src/+/4185417 * chore: remove dead DecodeToken code * refactor: refactoring geolocation manager Ref: https://chromium-review.googlesource.com/c/chromium/src/+/4161603 * chore: iwyu net/cert/cert_verify_result.h * build: use xcode 14 * chore: bump chromium in DEPS to 112.0.5583.0 * chore: update patches * chore: fixup mas patches * refactor: base::span explicit conversion checks Ref: https://chromium-review.googlesource.com/c/chromium/src/+/4219636 * chore: bump chromium in DEPS to 112.0.5591.0 * chore: bump chromium in DEPS to 112.0.5593.0 * chore: bump chromium in DEPS to 112.0.5594.3 * chore: bump chromium in DEPS to 112.0.5597.0 * chore: update chromium patches * 4242507: Move most of GetChromeKeySystems() into components/cdm Ref: https://chromium-review.googlesource.com/c/chromium/src/+/4242507 It seems as though the bug this patch was trying to resolve is now fixed. * chore: update v8 patches * 4240798: Get rid of ShowInvalidPrinterSettingsError() in PrintManagerHost. Ref: https://chromium-review.googlesource.com/c/chromium/src/+/4240798 * 4247938: Bump min required GTK version to 3.20 Ref: https://chromium-review.googlesource.com/c/chromium/src/+/4247938 * 4173660: Remove unused argument in BeforeUnloadCompleted Ref: https://chromium-review.googlesource.com/c/chromium/src/+/4173660 * 4226656: Add response url to SimpleURLLoader::OnRedirectCallback Ref: https://chromium-review.googlesource.com/c/chromium/src/+/4226656 * fixup!: 4240798: Get rid of ShowInvalidPrinterSettingsError() in PrintManager Host. Ref: https://chromium-review.googlesource.com/c/chromium/src/+/4240798 * chore: bump chromium in DEPS to 112.0.5599.0 * chore: update patches * 4251237: [StorageKey Cleanup] (2) Rename CreateFirstParty constructors Ref: https://chromium-review.googlesource.com/c/chromium/src/+/4251237 * 4256866: [Extensions] Replace GetHooksForAPI with a RegisterHooksDelegate Ref: https://chromium-review.googlesource.com/c/chromium/src/+/4256866 * chore: bump chromium in DEPS to 112.0.5601.0 * chore: update patches * chore: bump chromium in DEPS to 112.0.5603.0 * chore: bump chromium in DEPS to 112.0.5605.0 * chore: bump chromium in DEPS to 112.0.5607.0 * update patches * fix mas patch * chore: bump chromium in DEPS to 112.0.5609.0 * chore: update patches * build: update appveyor image 4072083: New toolchain for Windows 11 10.0.22621.755 SDK | https://chromium-review.googlesource.com/c/chromium/src/+/4072083 * chore: bump chromium in DEPS to 112.0.5611.0 * fix patches * chore: update patches * 4261434: Remove browser_watcher (1/3): Move ExitCodeWatcher to chrome/app https://chromium-review.googlesource.com/c/chromium/src/+/4261434 * 4258446: Move network::mojom::ClearDataFilter to its own mojom file https://chromium-review.googlesource.com/c/chromium/src/+/4258446 * 4128591: Enable large pdbs by default https://chromium-review.googlesource.com/c/chromium/src/+/4128591 * move dbgcore/dbghelp to extensions_to_skip * chore: bump chromium in DEPS to 113.0.5624.0 * chore: bump chromium in DEPS to 113.0.5626.0 * chore: bump chromium in DEPS to 113.0.5628.2 * chore: bump chromium in DEPS to 113.0.5630.0 * chore: bump chromium in DEPS to 113.0.5632.0 * chore: bump chromium in DEPS to 113.0.5634.0 * chore: bump chromium in DEPS to 113.0.5636.0 * 4255184: Permit popups from fullscreen-within-tab openers https://chromium-review.googlesource.com/c/chromium/src/+/4255184 * 4297715: [mac] Introduce BluetoothLowEnergyAdapterApple to reuse CoreBluetooth https://chromium-review.googlesource.com/c/chromium/src/+/4297715 * 4301154: Remove GLContextCGL and cleanup relevant code https://chromium-review.googlesource.com/c/chromium/src/+/4301154 * 4278389: CDP: fix Page.addScriptToEvaluateOnNewDocument in iframes https://chromium-review.googlesource.com/c/chromium/src/+/4278389 * 4240798: Get rid of ShowInvalidPrinterSettingsError() in PrintManagerHost. https://chromium-review.googlesource.com/c/chromium/src/+/4240798 * 4291989: Refactor logic determining untrusted mojo invitation flag. https://chromium-review.googlesource.com/c/chromium/src/+/4291989 * 4110189: Add Select option to content touch selection menu. https://chromium-review.googlesource.com/c/chromium/src/+/4110189 * 4309923: [Extensions] Add a unit test for API permissions having features https://chromium-review.googlesource.com/c/chromium/src/+/4309923 * 4282657: Revert "[headless] Route stdio to parent console on Windows." https://chromium-review.googlesource.com/c/chromium/src/+/4282657 * 4306685: [v8] Improve V8 flag configuration to avoid errors https://chromium-review.googlesource.com/c/chromium/src/+/4306685 * 4295455: Add fallback Linux UI for when GTK 3.20 isn't available https://chromium-review.googlesource.com/c/chromium/src/+/4295455 * 4289774: Remove feature for shared sandbox policies https://chromium-review.googlesource.com/c/chromium/src/+/4289774 * 4292705: Rename WebSwapCGLLayer to ANGLESwapCGLLayer outside WebKit. https://chromium-review.googlesource.com/c/angle/angle/+/4292705 * chore: fixup patch indices * fixup! 4297715: [mac] Introduce BluetoothLowEnergyAdapterApple to reuse CoreBluetooth * 4289789: Remove base::JSONReader::ReadDeprecated https://chromium-review.googlesource.com/c/chromium/src/+/4289789 * 4281521: Remove `base::Value::FindKey()` https://chromium-review.googlesource.com/c/chromium/src/+/4281521 * 4276761: Update NAK constructor and GetIsCrossSite https://chromium-review.googlesource.com/c/chromium/src/+/4276761 * 4288119: Let GetUpload work with UploadInfo pointers https://chromium-review.googlesource.com/c/chromium/src/+/4288119 * 4285322: content: Move WebExposedIsolationLevel to its own public header https://chromium-review.googlesource.com/c/chromium/src/+/4285322 * 4251818: [Extensions] Make ExtensionSet moveable. https://chromium-review.googlesource.com/c/chromium/src/+/4251818 * 4299554: [json-schema-compiler] Refactor to Params::Create (14/74) https://chromium-review.googlesource.com/c/chromium/src/+/4299554 * chore: update printing patch indices * chore: update chromium/add_maximized_parameter_to_linuxui_getwindowframeprovider.patch Xref: https://chromium-review.googlesource.com/c/chromium/src/+/4295455 Our patch changes the signature of `LinuxUiTheme::GetWindowFrameProvider()`. Upstream 4295455 added a new subclass (FallbackLinuxUi) so sync its version of GetWindowFrameProvider() to match our changes. * chore: disable node test parallel/test-intl Disabling the test because upstream is still working on this feature. Xref: https://chromium-review.googlesource.com/c/v8/v8/+/4237675 Xref: https://bugs.chromium.org/p/chromium/issues/detail?id=1414292 When upstream churn is done we should re-enable this test and update it as necessary. * win7dep: Remove ResolveCoreWinRTStringDelayload Xref: https://chromium-review.googlesource.com/c/chromium/src/+/4277708 Upstream has removed this since Win7 support is deprecated. This updates our `language_util_win.cc` file using the same approach that 4277708 uses for `base/win/win_util.cc`. * fix: remove use of ResolveCoreWinRTDelayload() Xref: https://chromium-review.googlesource.com/c/chromium/src/+/4297979 A followup to prev commit, which removed ResolveCoreWinRTStringDelayload(). This PR follows the 4297979 approach of simply removing the calls, e.g. https://chromium-review.googlesource.com/c/chromium/src/+/4297979/4/chrome/browser/device_reauth/win/authenticator_win.cc * fix: add d3dcompiler_47 to the zip manifest Xref: https://chromium-review.googlesource.com/c/angle/angle/+/4285717 Xref (24-x-y):0fb1def32b
* This clang roll breaks Linux arm 32-bit Xref (24-x-y):1229114494
Xref (chromium): https://crbug.com/1410101 * fix: WebUSB on ARM64 macs (#37441) * chore: update patches * chore: fix macOS CI build. Xref: https://chromium-review.googlesource.com/c/chromium/src/+/4278307 That whole dir was previously being removed to save space since we don't use it. We still don't use anything in the file, but gn needs it to exist. * fixup! chore: fix macOS CI build. chore: mkdir --parents does not exist on BSD; use mkdir -p * chore: update chromium/mas_disable_remote_accessibility.patch Xref: https://chromium-review.googlesource.com/c/chromium/src/+/4273450 Upstream added a new block of code using NSAccessibilityRemoteUIElement, so stub it out with `#if !IS_MAS_BUILD()` same as we do everwhere else. * chore: address code review nit :) --------- Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com> Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com> Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com> Co-authored-by: Samuel Attard <marshallofsound@electronjs.org> Co-authored-by: Keeley Hammond <vertedinde@electronjs.org> Co-authored-by: Jeremy Rose <jeremya@chromium.org> Co-authored-by: Charles Kerr <charles@charleskerr.com> Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>
811 lines
31 KiB
C++
811 lines
31 KiB
C++
// Copyright (c) 2019 Slack Technologies, Inc.
|
|
// Use of this source code is governed by the MIT license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "shell/browser/api/electron_api_url_loader.h"
|
|
|
|
#include <algorithm>
|
|
#include <memory>
|
|
#include <string>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
#include "base/no_destructor.h"
|
|
#include "gin/handle.h"
|
|
#include "gin/object_template_builder.h"
|
|
#include "gin/wrappable.h"
|
|
#include "mojo/public/cpp/bindings/remote.h"
|
|
#include "mojo/public/cpp/system/data_pipe_producer.h"
|
|
#include "net/base/load_flags.h"
|
|
#include "net/http/http_util.h"
|
|
#include "net/url_request/redirect_util.h"
|
|
#include "services/network/public/cpp/resource_request.h"
|
|
#include "services/network/public/cpp/simple_url_loader.h"
|
|
#include "services/network/public/cpp/url_util.h"
|
|
#include "services/network/public/cpp/wrapper_shared_url_loader_factory.h"
|
|
#include "services/network/public/mojom/chunked_data_pipe_getter.mojom.h"
|
|
#include "services/network/public/mojom/http_raw_headers.mojom.h"
|
|
#include "services/network/public/mojom/url_loader_factory.mojom.h"
|
|
#include "shell/browser/api/electron_api_session.h"
|
|
#include "shell/browser/electron_browser_context.h"
|
|
#include "shell/browser/javascript_environment.h"
|
|
#include "shell/browser/net/asar/asar_url_loader_factory.h"
|
|
#include "shell/browser/protocol_registry.h"
|
|
#include "shell/common/gin_converters/callback_converter.h"
|
|
#include "shell/common/gin_converters/gurl_converter.h"
|
|
#include "shell/common/gin_converters/net_converter.h"
|
|
#include "shell/common/gin_helper/dictionary.h"
|
|
#include "shell/common/gin_helper/object_template_builder.h"
|
|
#include "shell/common/node_includes.h"
|
|
#include "third_party/blink/public/common/loader/referrer_utils.h"
|
|
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom.h"
|
|
|
|
namespace gin {
|
|
|
|
template <>
|
|
struct Converter<network::mojom::HttpRawHeaderPairPtr> {
|
|
static v8::Local<v8::Value> ToV8(
|
|
v8::Isolate* isolate,
|
|
const network::mojom::HttpRawHeaderPairPtr& pair) {
|
|
gin_helper::Dictionary dict = gin::Dictionary::CreateEmpty(isolate);
|
|
dict.Set("key", pair->key);
|
|
dict.Set("value", pair->value);
|
|
return dict.GetHandle();
|
|
}
|
|
};
|
|
|
|
template <>
|
|
struct Converter<network::mojom::CredentialsMode> {
|
|
static bool FromV8(v8::Isolate* isolate,
|
|
v8::Local<v8::Value> val,
|
|
network::mojom::CredentialsMode* out) {
|
|
std::string mode;
|
|
if (!ConvertFromV8(isolate, val, &mode))
|
|
return false;
|
|
if (mode == "omit")
|
|
*out = network::mojom::CredentialsMode::kOmit;
|
|
else if (mode == "include")
|
|
*out = network::mojom::CredentialsMode::kInclude;
|
|
else if (mode == "same-origin")
|
|
// Note: This only makes sense if the request specifies the "origin"
|
|
// option.
|
|
*out = network::mojom::CredentialsMode::kSameOrigin;
|
|
else
|
|
return false;
|
|
return true;
|
|
}
|
|
};
|
|
|
|
template <>
|
|
struct Converter<blink::mojom::FetchCacheMode> {
|
|
static bool FromV8(v8::Isolate* isolate,
|
|
v8::Local<v8::Value> val,
|
|
blink::mojom::FetchCacheMode* out) {
|
|
std::string cache;
|
|
if (!ConvertFromV8(isolate, val, &cache))
|
|
return false;
|
|
if (cache == "default") {
|
|
*out = blink::mojom::FetchCacheMode::kDefault;
|
|
} else if (cache == "no-store") {
|
|
*out = blink::mojom::FetchCacheMode::kNoStore;
|
|
} else if (cache == "reload") {
|
|
*out = blink::mojom::FetchCacheMode::kBypassCache;
|
|
} else if (cache == "no-cache") {
|
|
*out = blink::mojom::FetchCacheMode::kValidateCache;
|
|
} else if (cache == "force-cache") {
|
|
*out = blink::mojom::FetchCacheMode::kForceCache;
|
|
} else if (cache == "only-if-cached") {
|
|
*out = blink::mojom::FetchCacheMode::kOnlyIfCached;
|
|
} else {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
};
|
|
|
|
template <>
|
|
struct Converter<net::ReferrerPolicy> {
|
|
static bool FromV8(v8::Isolate* isolate,
|
|
v8::Local<v8::Value> val,
|
|
net::ReferrerPolicy* out) {
|
|
std::string referrer_policy;
|
|
if (!ConvertFromV8(isolate, val, &referrer_policy))
|
|
return false;
|
|
if (base::CompareCaseInsensitiveASCII(referrer_policy, "no-referrer") ==
|
|
0) {
|
|
*out = net::ReferrerPolicy::NO_REFERRER;
|
|
} else if (base::CompareCaseInsensitiveASCII(
|
|
referrer_policy, "no-referrer-when-downgrade") == 0) {
|
|
*out = net::ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE;
|
|
} else if (base::CompareCaseInsensitiveASCII(referrer_policy, "origin") ==
|
|
0) {
|
|
*out = net::ReferrerPolicy::ORIGIN;
|
|
} else if (base::CompareCaseInsensitiveASCII(
|
|
referrer_policy, "origin-when-cross-origin") == 0) {
|
|
*out = net::ReferrerPolicy::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN;
|
|
} else if (base::CompareCaseInsensitiveASCII(referrer_policy,
|
|
"unsafe-url") == 0) {
|
|
*out = net::ReferrerPolicy::NEVER_CLEAR;
|
|
} else if (base::CompareCaseInsensitiveASCII(referrer_policy,
|
|
"same-origin") == 0) {
|
|
*out = net::ReferrerPolicy::CLEAR_ON_TRANSITION_CROSS_ORIGIN;
|
|
} else if (base::CompareCaseInsensitiveASCII(referrer_policy,
|
|
"strict-origin") == 0) {
|
|
*out = net::ReferrerPolicy::
|
|
ORIGIN_CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE;
|
|
} else if (referrer_policy == "" ||
|
|
base::CompareCaseInsensitiveASCII(
|
|
referrer_policy, "strict-origin-when-cross-origin") == 0) {
|
|
*out = net::ReferrerPolicy::REDUCE_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN;
|
|
} else {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
};
|
|
|
|
} // namespace gin
|
|
|
|
namespace electron::api {
|
|
|
|
namespace {
|
|
|
|
class BufferDataSource : public mojo::DataPipeProducer::DataSource {
|
|
public:
|
|
explicit BufferDataSource(base::span<char> buffer) {
|
|
buffer_.resize(buffer.size());
|
|
memcpy(buffer_.data(), buffer.data(), buffer_.size());
|
|
}
|
|
~BufferDataSource() override = default;
|
|
|
|
private:
|
|
// mojo::DataPipeProducer::DataSource:
|
|
uint64_t GetLength() const override { return buffer_.size(); }
|
|
ReadResult Read(uint64_t offset, base::span<char> buffer) override {
|
|
ReadResult result;
|
|
if (offset <= buffer_.size()) {
|
|
size_t readable_size = buffer_.size() - offset;
|
|
size_t writable_size = buffer.size();
|
|
size_t copyable_size = std::min(readable_size, writable_size);
|
|
if (copyable_size > 0) {
|
|
memcpy(buffer.data(), &buffer_[offset], copyable_size);
|
|
}
|
|
result.bytes_read = copyable_size;
|
|
} else {
|
|
NOTREACHED();
|
|
result.result = MOJO_RESULT_OUT_OF_RANGE;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
std::vector<char> buffer_;
|
|
};
|
|
|
|
class JSChunkedDataPipeGetter : public gin::Wrappable<JSChunkedDataPipeGetter>,
|
|
public network::mojom::ChunkedDataPipeGetter {
|
|
public:
|
|
static gin::Handle<JSChunkedDataPipeGetter> Create(
|
|
v8::Isolate* isolate,
|
|
v8::Local<v8::Function> body_func,
|
|
mojo::PendingReceiver<network::mojom::ChunkedDataPipeGetter>
|
|
chunked_data_pipe_getter) {
|
|
return gin::CreateHandle(
|
|
isolate, new JSChunkedDataPipeGetter(
|
|
isolate, body_func, std::move(chunked_data_pipe_getter)));
|
|
}
|
|
|
|
// gin::Wrappable
|
|
gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
|
|
v8::Isolate* isolate) override {
|
|
return gin::Wrappable<JSChunkedDataPipeGetter>::GetObjectTemplateBuilder(
|
|
isolate)
|
|
.SetMethod("write", &JSChunkedDataPipeGetter::WriteChunk)
|
|
.SetMethod("done", &JSChunkedDataPipeGetter::Done);
|
|
}
|
|
|
|
static gin::WrapperInfo kWrapperInfo;
|
|
~JSChunkedDataPipeGetter() override = default;
|
|
|
|
private:
|
|
JSChunkedDataPipeGetter(
|
|
v8::Isolate* isolate,
|
|
v8::Local<v8::Function> body_func,
|
|
mojo::PendingReceiver<network::mojom::ChunkedDataPipeGetter>
|
|
chunked_data_pipe_getter)
|
|
: isolate_(isolate), body_func_(isolate, body_func) {
|
|
receiver_.Bind(std::move(chunked_data_pipe_getter));
|
|
}
|
|
|
|
// network::mojom::ChunkedDataPipeGetter:
|
|
void GetSize(GetSizeCallback callback) override {
|
|
size_callback_ = std::move(callback);
|
|
}
|
|
|
|
void StartReading(mojo::ScopedDataPipeProducerHandle pipe) override {
|
|
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
|
|
|
if (body_func_.IsEmpty()) {
|
|
LOG(ERROR) << "Tried to read twice from a JSChunkedDataPipeGetter";
|
|
// Drop the handle on the floor.
|
|
return;
|
|
}
|
|
data_producer_ = std::make_unique<mojo::DataPipeProducer>(std::move(pipe));
|
|
|
|
v8::HandleScope handle_scope(isolate_);
|
|
auto maybe_wrapper = GetWrapper(isolate_);
|
|
v8::Local<v8::Value> wrapper;
|
|
if (!maybe_wrapper.ToLocal(&wrapper)) {
|
|
return;
|
|
}
|
|
v8::Local<v8::Value> argv[] = {wrapper};
|
|
node::Environment* env = node::Environment::GetCurrent(isolate_);
|
|
auto global = env->context()->Global();
|
|
node::MakeCallback(isolate_, global, body_func_.Get(isolate_),
|
|
node::arraysize(argv), argv, {0, 0});
|
|
}
|
|
|
|
v8::Local<v8::Promise> WriteChunk(v8::Local<v8::Value> buffer_val) {
|
|
gin_helper::Promise<void> promise(isolate_);
|
|
v8::Local<v8::Promise> handle = promise.GetHandle();
|
|
if (!buffer_val->IsArrayBufferView()) {
|
|
promise.RejectWithErrorMessage("Expected an ArrayBufferView");
|
|
return handle;
|
|
}
|
|
if (is_writing_) {
|
|
promise.RejectWithErrorMessage("Only one write can be pending at a time");
|
|
return handle;
|
|
}
|
|
if (!size_callback_) {
|
|
promise.RejectWithErrorMessage("Can't write after calling done()");
|
|
return handle;
|
|
}
|
|
auto buffer = buffer_val.As<v8::ArrayBufferView>();
|
|
is_writing_ = true;
|
|
bytes_written_ += buffer->ByteLength();
|
|
auto backing_store = buffer->Buffer()->GetBackingStore();
|
|
auto buffer_span = base::make_span(
|
|
static_cast<char*>(backing_store->Data()) + buffer->ByteOffset(),
|
|
buffer->ByteLength());
|
|
auto buffer_source = std::make_unique<BufferDataSource>(buffer_span);
|
|
data_producer_->Write(
|
|
std::move(buffer_source),
|
|
base::BindOnce(&JSChunkedDataPipeGetter::OnWriteChunkComplete,
|
|
// We're OK to use Unretained here because we own
|
|
// |data_producer_|.
|
|
base::Unretained(this), std::move(promise)));
|
|
return handle;
|
|
}
|
|
|
|
void OnWriteChunkComplete(gin_helper::Promise<void> promise,
|
|
MojoResult result) {
|
|
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
|
is_writing_ = false;
|
|
if (result == MOJO_RESULT_OK) {
|
|
promise.Resolve();
|
|
} else {
|
|
promise.RejectWithErrorMessage("mojo result not ok: " +
|
|
std::to_string(result));
|
|
Finished();
|
|
}
|
|
}
|
|
|
|
// TODO(nornagon): accept a net error here to allow the data provider to
|
|
// cancel the request with an error.
|
|
void Done() {
|
|
if (size_callback_) {
|
|
std::move(size_callback_).Run(net::OK, bytes_written_);
|
|
Finished();
|
|
}
|
|
}
|
|
|
|
void Finished() {
|
|
body_func_.Reset();
|
|
data_producer_.reset();
|
|
receiver_.reset();
|
|
size_callback_.Reset();
|
|
}
|
|
|
|
GetSizeCallback size_callback_;
|
|
mojo::Receiver<network::mojom::ChunkedDataPipeGetter> receiver_{this};
|
|
std::unique_ptr<mojo::DataPipeProducer> data_producer_;
|
|
bool is_writing_ = false;
|
|
uint64_t bytes_written_ = 0;
|
|
|
|
v8::Isolate* isolate_;
|
|
v8::Global<v8::Function> body_func_;
|
|
};
|
|
|
|
gin::WrapperInfo JSChunkedDataPipeGetter::kWrapperInfo = {
|
|
gin::kEmbedderNativeGin};
|
|
|
|
const net::NetworkTrafficAnnotationTag kTrafficAnnotation =
|
|
net::DefineNetworkTrafficAnnotation("electron_net_module", R"(
|
|
semantics {
|
|
sender: "Electron Net module"
|
|
description:
|
|
"Issue HTTP/HTTPS requests using Chromium's native networking "
|
|
"library."
|
|
trigger: "Using the Net module"
|
|
data: "Anything the user wants to send."
|
|
destination: OTHER
|
|
}
|
|
policy {
|
|
cookies_allowed: YES
|
|
cookies_store: "user"
|
|
setting: "This feature cannot be disabled."
|
|
})");
|
|
|
|
} // namespace
|
|
|
|
gin::WrapperInfo SimpleURLLoaderWrapper::kWrapperInfo = {
|
|
gin::kEmbedderNativeGin};
|
|
|
|
SimpleURLLoaderWrapper::SimpleURLLoaderWrapper(
|
|
ElectronBrowserContext* browser_context,
|
|
std::unique_ptr<network::ResourceRequest> request,
|
|
int options)
|
|
: browser_context_(browser_context),
|
|
request_options_(options),
|
|
request_(std::move(request)) {
|
|
if (!request_->trusted_params)
|
|
request_->trusted_params = network::ResourceRequest::TrustedParams();
|
|
mojo::PendingRemote<network::mojom::URLLoaderNetworkServiceObserver>
|
|
url_loader_network_observer_remote;
|
|
url_loader_network_observer_receivers_.Add(
|
|
this,
|
|
url_loader_network_observer_remote.InitWithNewPipeAndPassReceiver());
|
|
request_->trusted_params->url_loader_network_observer =
|
|
std::move(url_loader_network_observer_remote);
|
|
// Chromium filters headers using browser rules, while for net module we have
|
|
// every header passed. The following setting will allow us to capture the
|
|
// raw headers in the URLLoader.
|
|
request_->trusted_params->report_raw_headers = true;
|
|
Start();
|
|
}
|
|
|
|
void SimpleURLLoaderWrapper::Start() {
|
|
// Make a copy of the request; we'll need to re-send it if we get redirected.
|
|
auto request = std::make_unique<network::ResourceRequest>();
|
|
*request = *request_;
|
|
|
|
// SimpleURLLoader has no way to set a data pipe as the request body, which
|
|
// we need to do for streaming upload, so instead we "cheat" and pretend to
|
|
// SimpleURLLoader like there is no request_body when we construct it. Later,
|
|
// we will sneakily put the request_body back while it isn't looking.
|
|
scoped_refptr<network::ResourceRequestBody> request_body =
|
|
std::move(request->request_body);
|
|
|
|
network::ResourceRequest* request_ref = request.get();
|
|
loader_ =
|
|
network::SimpleURLLoader::Create(std::move(request), kTrafficAnnotation);
|
|
|
|
if (request_body)
|
|
request_ref->request_body = std::move(request_body);
|
|
|
|
loader_->SetAllowHttpErrorResults(true);
|
|
loader_->SetURLLoaderFactoryOptions(request_options_);
|
|
loader_->SetOnResponseStartedCallback(base::BindOnce(
|
|
&SimpleURLLoaderWrapper::OnResponseStarted, base::Unretained(this)));
|
|
loader_->SetOnRedirectCallback(base::BindRepeating(
|
|
&SimpleURLLoaderWrapper::OnRedirect, base::Unretained(this)));
|
|
loader_->SetOnUploadProgressCallback(base::BindRepeating(
|
|
&SimpleURLLoaderWrapper::OnUploadProgress, base::Unretained(this)));
|
|
loader_->SetOnDownloadProgressCallback(base::BindRepeating(
|
|
&SimpleURLLoaderWrapper::OnDownloadProgress, base::Unretained(this)));
|
|
|
|
url_loader_factory_ = GetURLLoaderFactoryForURL(request_ref->url);
|
|
loader_->DownloadAsStream(url_loader_factory_.get(), this);
|
|
}
|
|
|
|
void SimpleURLLoaderWrapper::Pin() {
|
|
// Prevent ourselves from being GC'd until the request is complete. Must be
|
|
// called after gin::CreateHandle, otherwise the wrapper isn't initialized.
|
|
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
|
|
pinned_wrapper_.Reset(isolate, GetWrapper(isolate).ToLocalChecked());
|
|
}
|
|
|
|
void SimpleURLLoaderWrapper::PinBodyGetter(v8::Local<v8::Value> body_getter) {
|
|
pinned_chunk_pipe_getter_.Reset(JavascriptEnvironment::GetIsolate(),
|
|
body_getter);
|
|
}
|
|
|
|
SimpleURLLoaderWrapper::~SimpleURLLoaderWrapper() = default;
|
|
|
|
void SimpleURLLoaderWrapper::OnAuthRequired(
|
|
const absl::optional<base::UnguessableToken>& window_id,
|
|
uint32_t request_id,
|
|
const GURL& url,
|
|
bool first_auth_attempt,
|
|
const net::AuthChallengeInfo& auth_info,
|
|
const scoped_refptr<net::HttpResponseHeaders>& head_headers,
|
|
mojo::PendingRemote<network::mojom::AuthChallengeResponder>
|
|
auth_challenge_responder) {
|
|
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
|
mojo::Remote<network::mojom::AuthChallengeResponder> auth_responder(
|
|
std::move(auth_challenge_responder));
|
|
// WeakPtr because if we're Cancel()ed while waiting for auth, and the
|
|
// network service also decides to cancel at the same time and kill this
|
|
// pipe, we might end up trying to call Cancel again on dead memory.
|
|
auth_responder.set_disconnect_handler(base::BindOnce(
|
|
&SimpleURLLoaderWrapper::Cancel, weak_factory_.GetWeakPtr()));
|
|
auto cb = base::BindOnce(
|
|
[](mojo::Remote<network::mojom::AuthChallengeResponder> auth_responder,
|
|
gin::Arguments* args) {
|
|
std::u16string username_str, password_str;
|
|
if (!args->GetNext(&username_str) || !args->GetNext(&password_str)) {
|
|
auth_responder->OnAuthCredentials(absl::nullopt);
|
|
return;
|
|
}
|
|
auth_responder->OnAuthCredentials(
|
|
net::AuthCredentials(username_str, password_str));
|
|
},
|
|
std::move(auth_responder));
|
|
Emit("login", auth_info, base::AdaptCallbackForRepeating(std::move(cb)));
|
|
}
|
|
|
|
void SimpleURLLoaderWrapper::OnSSLCertificateError(
|
|
const GURL& url,
|
|
int net_error,
|
|
const net::SSLInfo& ssl_info,
|
|
bool fatal,
|
|
OnSSLCertificateErrorCallback response) {
|
|
std::move(response).Run(net_error);
|
|
}
|
|
|
|
void SimpleURLLoaderWrapper::OnClearSiteData(
|
|
const GURL& url,
|
|
const std::string& header_value,
|
|
int32_t load_flags,
|
|
const absl::optional<net::CookiePartitionKey>& cookie_partition_key,
|
|
OnClearSiteDataCallback callback) {
|
|
std::move(callback).Run();
|
|
}
|
|
void SimpleURLLoaderWrapper::OnLoadingStateUpdate(
|
|
network::mojom::LoadInfoPtr info,
|
|
OnLoadingStateUpdateCallback callback) {
|
|
std::move(callback).Run();
|
|
}
|
|
|
|
void SimpleURLLoaderWrapper::Clone(
|
|
mojo::PendingReceiver<network::mojom::URLLoaderNetworkServiceObserver>
|
|
observer) {
|
|
url_loader_network_observer_receivers_.Add(this, std::move(observer));
|
|
}
|
|
|
|
void SimpleURLLoaderWrapper::Cancel() {
|
|
loader_.reset();
|
|
pinned_wrapper_.Reset();
|
|
pinned_chunk_pipe_getter_.Reset();
|
|
// This ensures that no further callbacks will be called, so there's no need
|
|
// for additional guards.
|
|
}
|
|
scoped_refptr<network::SharedURLLoaderFactory>
|
|
SimpleURLLoaderWrapper::GetURLLoaderFactoryForURL(const GURL& url) {
|
|
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory;
|
|
auto* protocol_registry =
|
|
ProtocolRegistry::FromBrowserContext(browser_context_);
|
|
// Explicitly handle intercepted protocols here, even though
|
|
// ProxyingURLLoaderFactory would handle them later on, so that we can
|
|
// correctly intercept file:// scheme URLs.
|
|
if (protocol_registry->IsProtocolIntercepted(url.scheme())) {
|
|
auto& protocol_handler =
|
|
protocol_registry->intercept_handlers().at(url.scheme());
|
|
mojo::PendingRemote<network::mojom::URLLoaderFactory> pending_remote =
|
|
ElectronURLLoaderFactory::Create(protocol_handler.first,
|
|
protocol_handler.second);
|
|
url_loader_factory = network::SharedURLLoaderFactory::Create(
|
|
std::make_unique<network::WrapperPendingSharedURLLoaderFactory>(
|
|
std::move(pending_remote)));
|
|
} else if (protocol_registry->IsProtocolRegistered(url.scheme())) {
|
|
auto& protocol_handler = protocol_registry->handlers().at(url.scheme());
|
|
mojo::PendingRemote<network::mojom::URLLoaderFactory> pending_remote =
|
|
ElectronURLLoaderFactory::Create(protocol_handler.first,
|
|
protocol_handler.second);
|
|
url_loader_factory = network::SharedURLLoaderFactory::Create(
|
|
std::make_unique<network::WrapperPendingSharedURLLoaderFactory>(
|
|
std::move(pending_remote)));
|
|
} else if (url.SchemeIsFile()) {
|
|
mojo::PendingRemote<network::mojom::URLLoaderFactory> pending_remote =
|
|
AsarURLLoaderFactory::Create();
|
|
url_loader_factory = network::SharedURLLoaderFactory::Create(
|
|
std::make_unique<network::WrapperPendingSharedURLLoaderFactory>(
|
|
std::move(pending_remote)));
|
|
} else {
|
|
url_loader_factory = browser_context_->GetURLLoaderFactory();
|
|
}
|
|
return url_loader_factory;
|
|
}
|
|
|
|
// static
|
|
gin::Handle<SimpleURLLoaderWrapper> SimpleURLLoaderWrapper::Create(
|
|
gin::Arguments* args) {
|
|
gin_helper::Dictionary opts;
|
|
if (!args->GetNext(&opts)) {
|
|
args->ThrowTypeError("Expected a dictionary");
|
|
return gin::Handle<SimpleURLLoaderWrapper>();
|
|
}
|
|
auto request = std::make_unique<network::ResourceRequest>();
|
|
opts.Get("method", &request->method);
|
|
opts.Get("url", &request->url);
|
|
request->site_for_cookies = net::SiteForCookies::FromUrl(request->url);
|
|
opts.Get("referrer", &request->referrer);
|
|
request->referrer_policy =
|
|
blink::ReferrerUtils::GetDefaultNetReferrerPolicy();
|
|
opts.Get("referrerPolicy", &request->referrer_policy);
|
|
std::string origin;
|
|
opts.Get("origin", &origin);
|
|
if (!origin.empty()) {
|
|
request->request_initiator = url::Origin::Create(GURL(origin));
|
|
}
|
|
bool has_user_activation;
|
|
if (opts.Get("hasUserActivation", &has_user_activation)) {
|
|
request->trusted_params = network::ResourceRequest::TrustedParams();
|
|
request->trusted_params->has_user_activation = has_user_activation;
|
|
}
|
|
|
|
std::string mode;
|
|
if (opts.Get("mode", &mode) && !mode.empty()) {
|
|
if (mode == "navigate") {
|
|
request->mode = network::mojom::RequestMode::kNavigate;
|
|
} else if (mode == "cors") {
|
|
request->mode = network::mojom::RequestMode::kCors;
|
|
} else if (mode == "no-cors") {
|
|
request->mode = network::mojom::RequestMode::kNoCors;
|
|
} else if (mode == "same-origin") {
|
|
request->mode = network::mojom::RequestMode::kSameOrigin;
|
|
}
|
|
}
|
|
|
|
std::string destination;
|
|
if (opts.Get("destination", &destination) && !destination.empty()) {
|
|
if (destination == "empty") {
|
|
request->destination = network::mojom::RequestDestination::kEmpty;
|
|
} else if (destination == "audio") {
|
|
request->destination = network::mojom::RequestDestination::kAudio;
|
|
} else if (destination == "audioworklet") {
|
|
request->destination = network::mojom::RequestDestination::kAudioWorklet;
|
|
} else if (destination == "document") {
|
|
request->destination = network::mojom::RequestDestination::kDocument;
|
|
} else if (destination == "embed") {
|
|
request->destination = network::mojom::RequestDestination::kEmbed;
|
|
} else if (destination == "font") {
|
|
request->destination = network::mojom::RequestDestination::kFont;
|
|
} else if (destination == "frame") {
|
|
request->destination = network::mojom::RequestDestination::kFrame;
|
|
} else if (destination == "iframe") {
|
|
request->destination = network::mojom::RequestDestination::kIframe;
|
|
} else if (destination == "image") {
|
|
request->destination = network::mojom::RequestDestination::kImage;
|
|
} else if (destination == "manifest") {
|
|
request->destination = network::mojom::RequestDestination::kManifest;
|
|
} else if (destination == "object") {
|
|
request->destination = network::mojom::RequestDestination::kObject;
|
|
} else if (destination == "paintworklet") {
|
|
request->destination = network::mojom::RequestDestination::kPaintWorklet;
|
|
} else if (destination == "report") {
|
|
request->destination = network::mojom::RequestDestination::kReport;
|
|
} else if (destination == "script") {
|
|
request->destination = network::mojom::RequestDestination::kScript;
|
|
} else if (destination == "serviceworker") {
|
|
request->destination = network::mojom::RequestDestination::kServiceWorker;
|
|
} else if (destination == "style") {
|
|
request->destination = network::mojom::RequestDestination::kStyle;
|
|
} else if (destination == "track") {
|
|
request->destination = network::mojom::RequestDestination::kTrack;
|
|
} else if (destination == "video") {
|
|
request->destination = network::mojom::RequestDestination::kVideo;
|
|
} else if (destination == "worker") {
|
|
request->destination = network::mojom::RequestDestination::kWorker;
|
|
} else if (destination == "xslt") {
|
|
request->destination = network::mojom::RequestDestination::kXslt;
|
|
}
|
|
}
|
|
|
|
bool credentials_specified =
|
|
opts.Get("credentials", &request->credentials_mode);
|
|
std::vector<std::pair<std::string, std::string>> extra_headers;
|
|
if (opts.Get("extraHeaders", &extra_headers)) {
|
|
for (const auto& it : extra_headers) {
|
|
if (!net::HttpUtil::IsValidHeaderName(it.first) ||
|
|
!net::HttpUtil::IsValidHeaderValue(it.second)) {
|
|
args->ThrowTypeError("Invalid header name or value");
|
|
return gin::Handle<SimpleURLLoaderWrapper>();
|
|
}
|
|
request->headers.SetHeader(it.first, it.second);
|
|
}
|
|
}
|
|
|
|
blink::mojom::FetchCacheMode cache_mode =
|
|
blink::mojom::FetchCacheMode::kDefault;
|
|
opts.Get("cache", &cache_mode);
|
|
switch (cache_mode) {
|
|
case blink::mojom::FetchCacheMode::kNoStore:
|
|
request->load_flags |= net::LOAD_DISABLE_CACHE;
|
|
break;
|
|
case blink::mojom::FetchCacheMode::kValidateCache:
|
|
request->load_flags |= net::LOAD_VALIDATE_CACHE;
|
|
break;
|
|
case blink::mojom::FetchCacheMode::kBypassCache:
|
|
request->load_flags |= net::LOAD_BYPASS_CACHE;
|
|
break;
|
|
case blink::mojom::FetchCacheMode::kForceCache:
|
|
request->load_flags |= net::LOAD_SKIP_CACHE_VALIDATION;
|
|
break;
|
|
case blink::mojom::FetchCacheMode::kOnlyIfCached:
|
|
request->load_flags |=
|
|
net::LOAD_ONLY_FROM_CACHE | net::LOAD_SKIP_CACHE_VALIDATION;
|
|
break;
|
|
case blink::mojom::FetchCacheMode::kUnspecifiedOnlyIfCachedStrict:
|
|
request->load_flags |= net::LOAD_ONLY_FROM_CACHE;
|
|
break;
|
|
case blink::mojom::FetchCacheMode::kDefault:
|
|
break;
|
|
case blink::mojom::FetchCacheMode::kUnspecifiedForceCacheMiss:
|
|
request->load_flags |= net::LOAD_ONLY_FROM_CACHE | net::LOAD_BYPASS_CACHE;
|
|
break;
|
|
}
|
|
|
|
bool use_session_cookies = false;
|
|
opts.Get("useSessionCookies", &use_session_cookies);
|
|
int options = 0;
|
|
if (!credentials_specified && !use_session_cookies) {
|
|
// This is the default case, as well as the case when credentials is not
|
|
// specified and useSessionCookies is false. credentials_mode will be
|
|
// kInclude, but cookies will be blocked.
|
|
request->credentials_mode = network::mojom::CredentialsMode::kInclude;
|
|
options |= network::mojom::kURLLoadOptionBlockAllCookies;
|
|
}
|
|
|
|
v8::Local<v8::Value> body;
|
|
v8::Local<v8::Value> chunk_pipe_getter;
|
|
if (opts.Get("body", &body)) {
|
|
if (body->IsArrayBufferView()) {
|
|
auto buffer_body = body.As<v8::ArrayBufferView>();
|
|
auto backing_store = buffer_body->Buffer()->GetBackingStore();
|
|
request->request_body = network::ResourceRequestBody::CreateFromBytes(
|
|
static_cast<char*>(backing_store->Data()) + buffer_body->ByteOffset(),
|
|
buffer_body->ByteLength());
|
|
} else if (body->IsFunction()) {
|
|
auto body_func = body.As<v8::Function>();
|
|
|
|
mojo::PendingRemote<network::mojom::ChunkedDataPipeGetter>
|
|
data_pipe_getter;
|
|
chunk_pipe_getter = JSChunkedDataPipeGetter::Create(
|
|
args->isolate(), body_func,
|
|
data_pipe_getter.InitWithNewPipeAndPassReceiver())
|
|
.ToV8();
|
|
request->request_body =
|
|
base::MakeRefCounted<network::ResourceRequestBody>();
|
|
request->request_body->SetToChunkedDataPipe(
|
|
std::move(data_pipe_getter),
|
|
network::ResourceRequestBody::ReadOnlyOnce(false));
|
|
}
|
|
}
|
|
|
|
std::string partition;
|
|
gin::Handle<Session> session;
|
|
if (!opts.Get("session", &session)) {
|
|
if (opts.Get("partition", &partition))
|
|
session = Session::FromPartition(args->isolate(), partition);
|
|
else // default session
|
|
session = Session::FromPartition(args->isolate(), "");
|
|
}
|
|
|
|
auto ret = gin::CreateHandle(
|
|
args->isolate(), new SimpleURLLoaderWrapper(session->browser_context(),
|
|
std::move(request), options));
|
|
ret->Pin();
|
|
if (!chunk_pipe_getter.IsEmpty()) {
|
|
ret->PinBodyGetter(chunk_pipe_getter);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
void SimpleURLLoaderWrapper::OnDataReceived(base::StringPiece string_piece,
|
|
base::OnceClosure resume) {
|
|
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
|
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
|
|
v8::HandleScope handle_scope(isolate);
|
|
auto array_buffer = v8::ArrayBuffer::New(isolate, string_piece.size());
|
|
auto backing_store = array_buffer->GetBackingStore();
|
|
memcpy(backing_store->Data(), string_piece.data(), string_piece.size());
|
|
Emit("data", array_buffer,
|
|
base::AdaptCallbackForRepeating(std::move(resume)));
|
|
}
|
|
|
|
void SimpleURLLoaderWrapper::OnComplete(bool success) {
|
|
if (success) {
|
|
Emit("complete");
|
|
} else {
|
|
Emit("error", net::ErrorToString(loader_->NetError()));
|
|
}
|
|
loader_.reset();
|
|
pinned_wrapper_.Reset();
|
|
pinned_chunk_pipe_getter_.Reset();
|
|
}
|
|
|
|
void SimpleURLLoaderWrapper::OnRetry(base::OnceClosure start_retry) {}
|
|
|
|
void SimpleURLLoaderWrapper::OnResponseStarted(
|
|
const GURL& final_url,
|
|
const network::mojom::URLResponseHead& response_head) {
|
|
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
|
|
v8::HandleScope scope(isolate);
|
|
gin::Dictionary dict = gin::Dictionary::CreateEmpty(isolate);
|
|
dict.Set("statusCode", response_head.headers->response_code());
|
|
dict.Set("statusMessage", response_head.headers->GetStatusText());
|
|
dict.Set("httpVersion", response_head.headers->GetHttpVersion());
|
|
dict.Set("headers", response_head.headers.get());
|
|
dict.Set("rawHeaders", response_head.raw_response_headers);
|
|
Emit("response-started", final_url, dict);
|
|
}
|
|
|
|
void SimpleURLLoaderWrapper::OnRedirect(
|
|
const GURL& url_before_redirect,
|
|
const net::RedirectInfo& redirect_info,
|
|
const network::mojom::URLResponseHead& response_head,
|
|
std::vector<std::string>* removed_headers) {
|
|
Emit("redirect", redirect_info, response_head.headers.get());
|
|
|
|
if (!loader_)
|
|
// The redirect was aborted by JS.
|
|
return;
|
|
|
|
// Optimization: if both the old and new URLs are handled by the network
|
|
// service, just FollowRedirect.
|
|
if (network::IsURLHandledByNetworkService(redirect_info.new_url) &&
|
|
network::IsURLHandledByNetworkService(request_->url))
|
|
return;
|
|
|
|
// Otherwise, restart the request (potentially picking a new
|
|
// URLLoaderFactory). See
|
|
// https://source.chromium.org/chromium/chromium/src/+/main:content/browser/loader/navigation_url_loader_impl.cc;l=534-550;drc=fbaec92ad5982f83aa4544d5c88d66d08034a9f4
|
|
|
|
bool should_clear_upload = false;
|
|
net::RedirectUtil::UpdateHttpRequest(
|
|
request_->url, request_->method, redirect_info, *removed_headers,
|
|
/* modified_headers = */ absl::nullopt, &request_->headers,
|
|
&should_clear_upload);
|
|
if (should_clear_upload) {
|
|
// The request body is no longer applicable.
|
|
request_->request_body.reset();
|
|
}
|
|
|
|
request_->url = redirect_info.new_url;
|
|
request_->method = redirect_info.new_method;
|
|
request_->site_for_cookies = redirect_info.new_site_for_cookies;
|
|
|
|
// See if navigation network isolation key needs to be updated.
|
|
request_->trusted_params->isolation_info =
|
|
request_->trusted_params->isolation_info.CreateForRedirect(
|
|
url::Origin::Create(request_->url));
|
|
|
|
request_->referrer = GURL(redirect_info.new_referrer);
|
|
request_->referrer_policy = redirect_info.new_referrer_policy;
|
|
request_->navigation_redirect_chain.push_back(redirect_info.new_url);
|
|
|
|
Start();
|
|
}
|
|
|
|
void SimpleURLLoaderWrapper::OnUploadProgress(uint64_t position,
|
|
uint64_t total) {
|
|
Emit("upload-progress", position, total);
|
|
}
|
|
|
|
void SimpleURLLoaderWrapper::OnDownloadProgress(uint64_t current) {
|
|
Emit("download-progress", current);
|
|
}
|
|
|
|
// static
|
|
gin::ObjectTemplateBuilder SimpleURLLoaderWrapper::GetObjectTemplateBuilder(
|
|
v8::Isolate* isolate) {
|
|
return gin_helper::EventEmitterMixin<
|
|
SimpleURLLoaderWrapper>::GetObjectTemplateBuilder(isolate)
|
|
.SetMethod("cancel", &SimpleURLLoaderWrapper::Cancel);
|
|
}
|
|
|
|
const char* SimpleURLLoaderWrapper::GetTypeName() {
|
|
return "SimpleURLLoaderWrapper";
|
|
}
|
|
|
|
} // namespace electron::api
|