Issue #8735:Support base URL option to loadURL for data URLs

This commit is contained in:
Nitish Sakhawalkar 2017-02-28 16:49:03 -08:00
parent 8e4bdec6b6
commit 879082b1a6
6 changed files with 122 additions and 106 deletions

View file

@ -114,7 +114,8 @@ struct Converter<atom::SetSizeParams> {
template <> template <>
struct Converter<PrintSettings> { struct Converter<PrintSettings> {
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val, static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
PrintSettings* out) { PrintSettings* out) {
mate::Dictionary dict; mate::Dictionary dict;
if (!ConvertFromV8(isolate, val, &dict)) if (!ConvertFromV8(isolate, val, &dict))
@ -156,7 +157,8 @@ struct Converter<WindowOpenDisposition> {
template <> template <>
struct Converter<content::SavePageType> { struct Converter<content::SavePageType> {
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val, static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
content::SavePageType* out) { content::SavePageType* out) {
std::string save_type; std::string save_type;
if (!ConvertFromV8(isolate, val, &save_type)) if (!ConvertFromV8(isolate, val, &save_type))
@ -182,17 +184,29 @@ struct Converter<atom::api::WebContents::Type> {
using Type = atom::api::WebContents::Type; using Type = atom::api::WebContents::Type;
std::string type = ""; std::string type = "";
switch (val) { switch (val) {
case Type::BACKGROUND_PAGE: type = "backgroundPage"; break; case Type::BACKGROUND_PAGE:
case Type::BROWSER_WINDOW: type = "window"; break; type = "backgroundPage";
case Type::REMOTE: type = "remote"; break; break;
case Type::WEB_VIEW: type = "webview"; break; case Type::BROWSER_WINDOW:
case Type::OFF_SCREEN: type = "offscreen"; break; type = "window";
default: break; break;
case Type::REMOTE:
type = "remote";
break;
case Type::WEB_VIEW:
type = "webview";
break;
case Type::OFF_SCREEN:
type = "offscreen";
break;
default:
break;
} }
return mate::ConvertToV8(isolate, type); return mate::ConvertToV8(isolate, type);
} }
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val, static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
atom::api::WebContents::Type* out) { atom::api::WebContents::Type* out) {
using Type = atom::api::WebContents::Type; using Type = atom::api::WebContents::Type;
std::string type; std::string type;
@ -213,7 +227,6 @@ struct Converter<atom::api::WebContents::Type> {
} // namespace mate } // namespace mate
namespace atom { namespace atom {
namespace api { namespace api {
@ -307,10 +320,10 @@ WebContents::WebContents(v8::Isolate* isolate, const mate::Dictionary& options)
content::WebContents* web_contents; content::WebContents* web_contents;
if (IsGuest()) { if (IsGuest()) {
scoped_refptr<content::SiteInstance> site_instance = scoped_refptr<content::SiteInstance> site_instance =
content::SiteInstance::CreateForURL( content::SiteInstance::CreateForURL(session->browser_context(),
session->browser_context(), GURL("chrome-guest://fake-host")); GURL("chrome-guest://fake-host"));
content::WebContents::CreateParams params( content::WebContents::CreateParams params(session->browser_context(),
session->browser_context(), site_instance); site_instance);
guest_delegate_.reset(new WebViewGuestDelegate); guest_delegate_.reset(new WebViewGuestDelegate);
params.guest_delegate = guest_delegate_.get(); params.guest_delegate = guest_delegate_.get();
web_contents = content::WebContents::Create(params); web_contents = content::WebContents::Create(params);
@ -520,8 +533,8 @@ bool WebContents::PreHandleKeyboardEvent(
content::WebContents* source, content::WebContents* source,
const content::NativeWebKeyboardEvent& event, const content::NativeWebKeyboardEvent& event,
bool* is_keyboard_shortcut) { bool* is_keyboard_shortcut) {
if (event.type == blink::WebInputEvent::Type::RawKeyDown if (event.type == blink::WebInputEvent::Type::RawKeyDown ||
|| event.type == blink::WebInputEvent::Type::KeyUp) event.type == blink::WebInputEvent::Type::KeyUp)
return Emit("before-input-event", event); return Emit("before-input-event", event);
else else
return false; return false;
@ -529,8 +542,7 @@ bool WebContents::PreHandleKeyboardEvent(
void WebContents::EnterFullscreenModeForTab(content::WebContents* source, void WebContents::EnterFullscreenModeForTab(content::WebContents* source,
const GURL& origin) { const GURL& origin) {
auto permission_helper = auto permission_helper = WebContentsPermissionHelper::FromWebContents(source);
WebContentsPermissionHelper::FromWebContents(source);
auto callback = base::Bind(&WebContents::OnEnterFullscreenModeForTab, auto callback = base::Bind(&WebContents::OnEnterFullscreenModeForTab,
base::Unretained(this), source, origin); base::Unretained(this), source, origin);
permission_helper->RequestFullscreenPermission(callback); permission_helper->RequestFullscreenPermission(callback);
@ -600,8 +612,7 @@ void WebContents::FindReply(content::WebContents* web_contents,
Emit("found-in-page", result); Emit("found-in-page", result);
} }
bool WebContents::CheckMediaAccessPermission( bool WebContents::CheckMediaAccessPermission(content::WebContents* web_contents,
content::WebContents* web_contents,
const GURL& security_origin, const GURL& security_origin,
content::MediaStreamType type) { content::MediaStreamType type) {
return true; return true;
@ -616,8 +627,7 @@ void WebContents::RequestMediaAccessPermission(
permission_helper->RequestMediaAccessPermission(request, callback); permission_helper->RequestMediaAccessPermission(request, callback);
} }
void WebContents::RequestToLockMouse( void WebContents::RequestToLockMouse(content::WebContents* web_contents,
content::WebContents* web_contents,
bool user_gesture, bool user_gesture,
bool last_unlocked_by_target) { bool last_unlocked_by_target) {
auto permission_helper = auto permission_helper =
@ -710,26 +720,17 @@ void WebContents::DidStopLoading() {
void WebContents::DidGetResourceResponseStart( void WebContents::DidGetResourceResponseStart(
const content::ResourceRequestDetails& details) { const content::ResourceRequestDetails& details) {
Emit("did-get-response-details", Emit("did-get-response-details", details.socket_address.IsEmpty(),
details.socket_address.IsEmpty(), details.url, details.original_url, details.http_response_code,
details.url, details.method, details.referrer, details.headers.get(),
details.original_url,
details.http_response_code,
details.method,
details.referrer,
details.headers.get(),
ResourceTypeToString(details.resource_type)); ResourceTypeToString(details.resource_type));
} }
void WebContents::DidGetRedirectForResourceRequest( void WebContents::DidGetRedirectForResourceRequest(
const content::ResourceRedirectDetails& details) { const content::ResourceRedirectDetails& details) {
Emit("did-get-redirect-request", Emit("did-get-redirect-request", details.url, details.new_url,
details.url,
details.new_url,
(details.resource_type == content::RESOURCE_TYPE_MAIN_FRAME), (details.resource_type == content::RESOURCE_TYPE_MAIN_FRAME),
details.http_response_code, details.http_response_code, details.method, details.referrer,
details.method,
details.referrer,
details.headers.get()); details.headers.get());
} }
@ -794,8 +795,8 @@ void WebContents::DevToolsOpened() {
// Set inspected tabID. // Set inspected tabID.
base::FundamentalValue tab_id(ID()); base::FundamentalValue tab_id(ID());
managed_web_contents()->CallClientFunction( managed_web_contents()->CallClientFunction("DevToolsAPI.setInspectedTabId",
"DevToolsAPI.setInspectedTabId", &tab_id, nullptr, nullptr); &tab_id, nullptr, nullptr);
// Inherit owner window in devtools. // Inherit owner window in devtools.
if (owner_window()) if (owner_window())
@ -858,14 +859,13 @@ void WebContents::WebContentsDestroyed() {
Emit("destroyed"); Emit("destroyed");
// Destroy the native class in next tick. // Destroy the native class in next tick.
base::ThreadTaskRunnerHandle::Get()->PostTask( base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, GetDestroyClosure());
FROM_HERE, GetDestroyClosure());
} }
void WebContents::NavigationEntryCommitted( void WebContents::NavigationEntryCommitted(
const content::LoadCommittedDetails& details) { const content::LoadCommittedDetails& details) {
Emit("navigation-entry-commited", details.entry->GetURL(), Emit("navigation-entry-commited", details.entry->GetURL(), details.is_in_page,
details.is_in_page, details.did_replace_entry); details.did_replace_entry);
} }
int64_t WebContents::GetID() const { int64_t WebContents::GetID() const {
@ -889,11 +889,9 @@ bool WebContents::Equal(const WebContents* web_contents) const {
void WebContents::LoadURL(const GURL& url, const mate::Dictionary& options) { void WebContents::LoadURL(const GURL& url, const mate::Dictionary& options) {
if (!url.is_valid() || url.spec().size() > url::kMaxURLChars) { if (!url.is_valid() || url.spec().size() > url::kMaxURLChars) {
Emit("did-fail-load", Emit("did-fail-load", static_cast<int>(net::ERR_INVALID_URL),
static_cast<int>(net::ERR_INVALID_URL),
net::ErrorToShortString(net::ERR_INVALID_URL), net::ErrorToShortString(net::ERR_INVALID_URL),
url.possibly_invalid_spec(), url.possibly_invalid_spec(), true);
true);
return; return;
} }
@ -918,6 +916,12 @@ void WebContents::LoadURL(const GURL& url, const mate::Dictionary& options) {
params.load_type = content::NavigationController::LOAD_TYPE_HTTP_POST; params.load_type = content::NavigationController::LOAD_TYPE_HTTP_POST;
} }
GURL base_url_for_data_url;
if (options.Get("baseURLForDataURL", &base_url_for_data_url)) {
params.base_url_for_data_url = base_url_for_data_url;
params.load_type = content::NavigationController::LOAD_TYPE_DATA;
}
params.transition_type = ui::PAGE_TRANSITION_TYPED; params.transition_type = ui::PAGE_TRANSITION_TYPED;
params.should_clear_history_list = true; params.should_clear_history_list = true;
params.override_user_agent = content::NavigationController::UA_OVERRIDE_TRUE; params.override_user_agent = content::NavigationController::UA_OVERRIDE_TRUE;
@ -967,7 +971,8 @@ bool WebContents::IsLoadingMainFrame() const {
// instance when navigating, regardless of origin. See AtomBrowserClient. // instance when navigating, regardless of origin. See AtomBrowserClient.
return (web_contents()->GetLastCommittedURL().is_empty() || return (web_contents()->GetLastCommittedURL().is_empty() ||
web_contents()->GetSiteInstance() != web_contents()->GetSiteInstance() !=
web_contents()->GetPendingSiteInstance()) && IsLoading(); web_contents()->GetPendingSiteInstance()) &&
IsLoading();
} }
bool WebContents::IsWaitingForResponse() const { bool WebContents::IsWaitingForResponse() const {
@ -1111,15 +1116,13 @@ void WebContents::InspectServiceWorker() {
} }
} }
void WebContents::HasServiceWorker( void WebContents::HasServiceWorker(const base::Callback<void(bool)>& callback) {
const base::Callback<void(bool)>& callback) {
auto context = GetServiceWorkerContext(web_contents()); auto context = GetServiceWorkerContext(web_contents());
if (!context) if (!context)
return; return;
context->CheckHasServiceWorker(web_contents()->GetLastCommittedURL(), context->CheckHasServiceWorker(web_contents()->GetLastCommittedURL(),
GURL::EmptyGURL(), GURL::EmptyGURL(), callback);
callback);
} }
void WebContents::UnregisterServiceWorker( void WebContents::UnregisterServiceWorker(
@ -1147,16 +1150,15 @@ void WebContents::Print(mate::Arguments* args) {
return; return;
} }
printing::PrintViewManagerBasic::FromWebContents(web_contents())-> printing::PrintViewManagerBasic::FromWebContents(web_contents())
PrintNow(web_contents()->GetMainFrame(), ->PrintNow(web_contents()->GetMainFrame(), settings.silent,
settings.silent,
settings.print_background); settings.print_background);
} }
void WebContents::PrintToPDF(const base::DictionaryValue& setting, void WebContents::PrintToPDF(const base::DictionaryValue& setting,
const PrintToPDFCallback& callback) { const PrintToPDFCallback& callback) {
printing::PrintPreviewMessageHandler::FromWebContents(web_contents())-> printing::PrintPreviewMessageHandler::FromWebContents(web_contents())
PrintToPDF(setting, callback); ->PrintToPDF(setting, callback);
} }
void WebContents::AddWorkSpace(mate::Arguments* args, void WebContents::AddWorkSpace(mate::Arguments* args,
@ -1261,7 +1263,8 @@ void WebContents::Focus() {
#if !defined(OS_MACOSX) #if !defined(OS_MACOSX)
bool WebContents::IsFocused() const { bool WebContents::IsFocused() const {
auto view = web_contents()->GetRenderWidgetHostView(); auto view = web_contents()->GetRenderWidgetHostView();
if (!view) return false; if (!view)
return false;
if (GetType() != BACKGROUND_PAGE) { if (GetType() != BACKGROUND_PAGE) {
auto window = web_contents()->GetNativeView()->GetToplevelWindow(); auto window = web_contents()->GetNativeView()->GetToplevelWindow();
@ -1313,8 +1316,8 @@ void WebContents::SendInputEvent(v8::Isolate* isolate,
} }
} }
isolate->ThrowException(v8::Exception::Error(mate::StringToV8( isolate->ThrowException(
isolate, "Invalid event object"))); v8::Exception::Error(mate::StringToV8(isolate, "Invalid event object")));
} }
void WebContents::BeginFrameSubscription(mate::Arguments* args) { void WebContents::BeginFrameSubscription(mate::Arguments* args) {
@ -1329,8 +1332,8 @@ void WebContents::BeginFrameSubscription(mate::Arguments* args) {
const auto view = web_contents()->GetRenderWidgetHostView(); const auto view = web_contents()->GetRenderWidgetHostView();
if (view) { if (view) {
std::unique_ptr<FrameSubscriber> frame_subscriber(new FrameSubscriber( std::unique_ptr<FrameSubscriber> frame_subscriber(
isolate(), view, callback, only_dirty)); new FrameSubscriber(isolate(), view, callback, only_dirty));
view->BeginFrameSubscription(std::move(frame_subscriber)); view->BeginFrameSubscription(std::move(frame_subscriber));
} }
} }
@ -1383,8 +1386,8 @@ void WebContents::CapturePage(mate::Arguments* args) {
base::Callback<void(const gfx::Image&)> callback; base::Callback<void(const gfx::Image&)> callback;
if (!(args->Length() == 1 && args->GetNext(&callback)) && if (!(args->Length() == 1 && args->GetNext(&callback)) &&
!(args->Length() == 2 && args->GetNext(&rect) !(args->Length() == 2 && args->GetNext(&rect) &&
&& args->GetNext(&callback))) { args->GetNext(&callback))) {
args->ThrowError(); args->ThrowError();
return; return;
} }
@ -1397,22 +1400,21 @@ void WebContents::CapturePage(mate::Arguments* args) {
} }
// Capture full page if user doesn't specify a |rect|. // Capture full page if user doesn't specify a |rect|.
const gfx::Size view_size = rect.IsEmpty() ? view->GetViewBounds().size() : const gfx::Size view_size =
rect.size(); rect.IsEmpty() ? view->GetViewBounds().size() : rect.size();
// By default, the requested bitmap size is the view size in screen // By default, the requested bitmap size is the view size in screen
// coordinates. However, if there's more pixel detail available on the // coordinates. However, if there's more pixel detail available on the
// current system, increase the requested bitmap size to capture it all. // current system, increase the requested bitmap size to capture it all.
gfx::Size bitmap_size = view_size; gfx::Size bitmap_size = view_size;
const gfx::NativeView native_view = view->GetNativeView(); const gfx::NativeView native_view = view->GetNativeView();
const float scale = const float scale = display::Screen::GetScreen()
display::Screen::GetScreen()->GetDisplayNearestWindow(native_view) ->GetDisplayNearestWindow(native_view)
.device_scale_factor(); .device_scale_factor();
if (scale > 1.0f) if (scale > 1.0f)
bitmap_size = gfx::ScaleToCeiledSize(view_size, scale); bitmap_size = gfx::ScaleToCeiledSize(view_size, scale);
host->CopyFromBackingStore(gfx::Rect(rect.origin(), view_size), host->CopyFromBackingStore(gfx::Rect(rect.origin(), view_size), bitmap_size,
bitmap_size,
base::Bind(&OnCapturePageDone, callback), base::Bind(&OnCapturePageDone, callback),
kBGRA_8888_SkColorType); kBGRA_8888_SkColorType);
} }
@ -1632,10 +1634,8 @@ void WebContents::BuildPrototype(v8::Isolate* isolate,
.SetMethod("closeDevTools", &WebContents::CloseDevTools) .SetMethod("closeDevTools", &WebContents::CloseDevTools)
.SetMethod("isDevToolsOpened", &WebContents::IsDevToolsOpened) .SetMethod("isDevToolsOpened", &WebContents::IsDevToolsOpened)
.SetMethod("isDevToolsFocused", &WebContents::IsDevToolsFocused) .SetMethod("isDevToolsFocused", &WebContents::IsDevToolsFocused)
.SetMethod("enableDeviceEmulation", .SetMethod("enableDeviceEmulation", &WebContents::EnableDeviceEmulation)
&WebContents::EnableDeviceEmulation) .SetMethod("disableDeviceEmulation", &WebContents::DisableDeviceEmulation)
.SetMethod("disableDeviceEmulation",
&WebContents::DisableDeviceEmulation)
.SetMethod("toggleDevTools", &WebContents::ToggleDevTools) .SetMethod("toggleDevTools", &WebContents::ToggleDevTools)
.SetMethod("inspectElement", &WebContents::InspectElement) .SetMethod("inspectElement", &WebContents::InspectElement)
.SetMethod("setAudioMuted", &WebContents::SetAudioMuted) .SetMethod("setAudioMuted", &WebContents::SetAudioMuted)
@ -1658,8 +1658,7 @@ void WebContents::BuildPrototype(v8::Isolate* isolate,
.SetMethod("tabTraverse", &WebContents::TabTraverse) .SetMethod("tabTraverse", &WebContents::TabTraverse)
.SetMethod("_send", &WebContents::SendIPCMessage) .SetMethod("_send", &WebContents::SendIPCMessage)
.SetMethod("sendInputEvent", &WebContents::SendInputEvent) .SetMethod("sendInputEvent", &WebContents::SendInputEvent)
.SetMethod("beginFrameSubscription", .SetMethod("beginFrameSubscription", &WebContents::BeginFrameSubscription)
&WebContents::BeginFrameSubscription)
.SetMethod("endFrameSubscription", &WebContents::EndFrameSubscription) .SetMethod("endFrameSubscription", &WebContents::EndFrameSubscription)
.SetMethod("startDrag", &WebContents::StartDrag) .SetMethod("startDrag", &WebContents::StartDrag)
.SetMethod("setSize", &WebContents::SetSize) .SetMethod("setSize", &WebContents::SetSize)
@ -1717,27 +1716,30 @@ void WebContents::OnRendererMessageSync(const base::string16& channel,
// static // static
mate::Handle<WebContents> WebContents::CreateFrom( mate::Handle<WebContents> WebContents::CreateFrom(
v8::Isolate* isolate, content::WebContents* web_contents) { v8::Isolate* isolate,
content::WebContents* web_contents) {
// We have an existing WebContents object in JS. // We have an existing WebContents object in JS.
auto existing = TrackableObject::FromWrappedClass(isolate, web_contents); auto existing = TrackableObject::FromWrappedClass(isolate, web_contents);
if (existing) if (existing)
return mate::CreateHandle(isolate, static_cast<WebContents*>(existing)); return mate::CreateHandle(isolate, static_cast<WebContents*>(existing));
// Otherwise create a new WebContents wrapper object. // Otherwise create a new WebContents wrapper object.
return mate::CreateHandle(isolate, new WebContents(isolate, web_contents, return mate::CreateHandle(isolate,
REMOTE)); new WebContents(isolate, web_contents, REMOTE));
} }
mate::Handle<WebContents> WebContents::CreateFrom( mate::Handle<WebContents> WebContents::CreateFrom(
v8::Isolate* isolate, content::WebContents* web_contents, Type type) { v8::Isolate* isolate,
content::WebContents* web_contents,
Type type) {
// Otherwise create a new WebContents wrapper object. // Otherwise create a new WebContents wrapper object.
return mate::CreateHandle(isolate, new WebContents(isolate, web_contents, return mate::CreateHandle(isolate,
type)); new WebContents(isolate, web_contents, type));
} }
// static // static
mate::Handle<WebContents> WebContents::Create( mate::Handle<WebContents> WebContents::Create(v8::Isolate* isolate,
v8::Isolate* isolate, const mate::Dictionary& options) { const mate::Dictionary& options) {
return mate::CreateHandle(isolate, new WebContents(isolate, options)); return mate::CreateHandle(isolate, new WebContents(isolate, options));
} }
@ -1749,8 +1751,10 @@ namespace {
using atom::api::WebContents; using atom::api::WebContents;
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused, void Initialize(v8::Local<v8::Object> exports,
v8::Local<v8::Context> context, void* priv) { v8::Local<v8::Value> unused,
v8::Local<v8::Context> context,
void* priv) {
v8::Isolate* isolate = context->GetIsolate(); v8::Isolate* isolate = context->GetIsolate();
mate::Dictionary dict(isolate, exports); mate::Dictionary dict(isolate, exports);
dict.Set("WebContents", WebContents::GetConstructor(isolate)->GetFunction()); dict.Set("WebContents", WebContents::GetConstructor(isolate)->GetFunction());

View file

@ -1004,6 +1004,7 @@ Same as `webContents.capturePage([rect, ]callback)`.
* `userAgent` String (optional) - A user agent originating the request. * `userAgent` String (optional) - A user agent originating the request.
* `extraHeaders` String (optional) - Extra headers separated by "\n" * `extraHeaders` String (optional) - Extra headers separated by "\n"
* `postData` ([UploadRawData](structures/upload-raw-data.md) | [UploadFile](structures/upload-file.md) | [UploadFileSystem](structures/upload-file-system.md) | [UploadBlob](structures/upload-blob.md))[] - (optional) * `postData` ([UploadRawData](structures/upload-raw-data.md) | [UploadFile](structures/upload-file.md) | [UploadFileSystem](structures/upload-file-system.md) | [UploadBlob](structures/upload-blob.md))[] - (optional)
* `baseURLForDataURL` String(optional) - Base url for files to be loaded by the data url. This is needed only if the specified `url` is a data url and needs to load other files.
Same as `webContents.loadURL(url[, options])`. Same as `webContents.loadURL(url[, options])`.

View file

@ -541,6 +541,7 @@ that can't be set via `<webview>` attributes.
* `userAgent` String (optional) - A user agent originating the request. * `userAgent` String (optional) - A user agent originating the request.
* `extraHeaders` String (optional) - Extra headers separated by "\n" * `extraHeaders` String (optional) - Extra headers separated by "\n"
* `postData` ([UploadRawData](structures/upload-raw-data.md) | [UploadFile](structures/upload-file.md) | [UploadFileSystem](structures/upload-file-system.md) | [UploadBlob](structures/upload-blob.md))[] - (optional) * `postData` ([UploadRawData](structures/upload-raw-data.md) | [UploadFile](structures/upload-file.md) | [UploadFileSystem](structures/upload-file-system.md) | [UploadBlob](structures/upload-blob.md))[] - (optional)
* `baseURLForDataURL` String(optional) - Base url for files to be loaded by the data url. This is needed only if the specified `url` is a data url and needs to load other files.
Loads the `url` in the window. The `url` must contain the protocol prefix, Loads the `url` in the window. The `url` must contain the protocol prefix,
e.g. the `http://` or `file://`. If the load should bypass http cache then e.g. the `http://` or `file://`. If the load should bypass http cache then

View file

@ -310,6 +310,7 @@ webview.addEventListener('dom-ready', () => {
* `userAgent` String (optional) - A user agent originating the request. * `userAgent` String (optional) - A user agent originating the request.
* `extraHeaders` String (optional) - Extra headers separated by "\n" * `extraHeaders` String (optional) - Extra headers separated by "\n"
* `postData` ([UploadRawData](structures/upload-raw-data.md) | [UploadFile](structures/upload-file.md) | [UploadFileSystem](structures/upload-file-system.md) | [UploadBlob](structures/upload-blob.md))[] - (optional) * `postData` ([UploadRawData](structures/upload-raw-data.md) | [UploadFile](structures/upload-file.md) | [UploadFileSystem](structures/upload-file-system.md) | [UploadBlob](structures/upload-blob.md))[] - (optional)
* `baseURLForDataURL` String(optional) - Base url for files to be loaded by the data url. This is needed only if the specified `url` is a data url and needs to load other files.
Loads the `url` in the webview, the `url` must contain the protocol prefix, Loads the `url` in the webview, the `url` must contain the protocol prefix,
e.g. the `http://` or `file://`. e.g. the `http://` or `file://`.

View file

@ -256,6 +256,14 @@ describe('BrowserWindow module', function () {
w.loadURL(server.url) w.loadURL(server.url)
}) })
it('should support support base url for data urls', (done) => {
ipcMain.once('answer', function (event, test) {
assert.equal(test, 'test')
done()
})
w.loadURL('data:text/html,<script src="loaded-from-dataurl.js"></script>', {baseURLForDataURL: 'file://' + path.join(fixtures, 'api') + path.sep})
})
it('sets the content type header on multi part forms', function (done) { it('sets the content type header on multi part forms', function (done) {
w.webContents.on('did-finish-load', () => { w.webContents.on('did-finish-load', () => {
w.webContents.session.webRequest.onBeforeSendHeaders((details, callback) => { w.webContents.session.webRequest.onBeforeSendHeaders((details, callback) => {

View file

@ -0,0 +1 @@
require('electron').ipcRenderer.send('answer', 'test')