Merge pull request #7540 from deepak1556/form_post_new_window_patch
webContents: handle POST navigation for new windows
This commit is contained in:
commit
4867475cee
18 changed files with 321 additions and 65 deletions
|
@ -528,12 +528,14 @@ void App::OnLogin(LoginHandler* login_handler,
|
||||||
login_handler->CancelAuth();
|
login_handler->CancelAuth();
|
||||||
}
|
}
|
||||||
|
|
||||||
void App::OnCreateWindow(const GURL& target_url,
|
void App::OnCreateWindow(
|
||||||
const std::string& frame_name,
|
const GURL& target_url,
|
||||||
WindowOpenDisposition disposition,
|
const std::string& frame_name,
|
||||||
const std::vector<base::string16>& features,
|
WindowOpenDisposition disposition,
|
||||||
int render_process_id,
|
const std::vector<base::string16>& features,
|
||||||
int render_frame_id) {
|
const scoped_refptr<content::ResourceRequestBodyImpl>& body,
|
||||||
|
int render_process_id,
|
||||||
|
int render_frame_id) {
|
||||||
v8::Locker locker(isolate());
|
v8::Locker locker(isolate());
|
||||||
v8::HandleScope handle_scope(isolate());
|
v8::HandleScope handle_scope(isolate());
|
||||||
content::RenderFrameHost* rfh =
|
content::RenderFrameHost* rfh =
|
||||||
|
@ -545,7 +547,8 @@ void App::OnCreateWindow(const GURL& target_url,
|
||||||
api_web_contents->OnCreateWindow(target_url,
|
api_web_contents->OnCreateWindow(target_url,
|
||||||
frame_name,
|
frame_name,
|
||||||
disposition,
|
disposition,
|
||||||
features);
|
features,
|
||||||
|
body);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,12 +48,14 @@ class App : public AtomBrowserClient::Delegate,
|
||||||
v8::Local<v8::FunctionTemplate> prototype);
|
v8::Local<v8::FunctionTemplate> prototype);
|
||||||
|
|
||||||
// Called when window with disposition needs to be created.
|
// Called when window with disposition needs to be created.
|
||||||
void OnCreateWindow(const GURL& target_url,
|
void OnCreateWindow(
|
||||||
const std::string& frame_name,
|
const GURL& target_url,
|
||||||
WindowOpenDisposition disposition,
|
const std::string& frame_name,
|
||||||
const std::vector<base::string16>& features,
|
WindowOpenDisposition disposition,
|
||||||
int render_process_id,
|
const std::vector<base::string16>& features,
|
||||||
int render_frame_id);
|
const scoped_refptr<content::ResourceRequestBodyImpl>& body,
|
||||||
|
int render_process_id,
|
||||||
|
int render_frame_id);
|
||||||
|
|
||||||
#if defined(USE_NSS_CERTS)
|
#if defined(USE_NSS_CERTS)
|
||||||
void OnCertificateManagerModelCreated(
|
void OnCertificateManagerModelCreated(
|
||||||
|
|
|
@ -387,12 +387,14 @@ bool WebContents::AddMessageToConsole(content::WebContents* source,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebContents::OnCreateWindow(const GURL& target_url,
|
void WebContents::OnCreateWindow(
|
||||||
const std::string& frame_name,
|
const GURL& target_url,
|
||||||
WindowOpenDisposition disposition,
|
const std::string& frame_name,
|
||||||
const std::vector<base::string16>& features) {
|
WindowOpenDisposition disposition,
|
||||||
|
const std::vector<base::string16>& features,
|
||||||
|
const scoped_refptr<content::ResourceRequestBodyImpl>& body) {
|
||||||
if (type_ == BROWSER_WINDOW || type_ == OFF_SCREEN)
|
if (type_ == BROWSER_WINDOW || type_ == OFF_SCREEN)
|
||||||
Emit("-new-window", target_url, frame_name, disposition, features);
|
Emit("-new-window", target_url, frame_name, disposition, features, body);
|
||||||
else
|
else
|
||||||
Emit("new-window", target_url, frame_name, disposition, features);
|
Emit("new-window", target_url, frame_name, disposition, features);
|
||||||
}
|
}
|
||||||
|
@ -855,6 +857,12 @@ void WebContents::LoadURL(const GURL& url, const mate::Dictionary& options) {
|
||||||
if (options.Get("extraHeaders", &extra_headers))
|
if (options.Get("extraHeaders", &extra_headers))
|
||||||
params.extra_headers = extra_headers;
|
params.extra_headers = extra_headers;
|
||||||
|
|
||||||
|
scoped_refptr<content::ResourceRequestBodyImpl> body;
|
||||||
|
if (options.Get("postData", &body)) {
|
||||||
|
params.post_data = body;
|
||||||
|
params.load_type = content::NavigationController::LOAD_TYPE_HTTP_POST;
|
||||||
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
|
|
@ -26,6 +26,10 @@ namespace brightray {
|
||||||
class InspectableWebContents;
|
class InspectableWebContents;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace content {
|
||||||
|
class ResourceRequestBodyImpl;
|
||||||
|
}
|
||||||
|
|
||||||
namespace mate {
|
namespace mate {
|
||||||
class Arguments;
|
class Arguments;
|
||||||
class Dictionary;
|
class Dictionary;
|
||||||
|
@ -176,10 +180,12 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||||
bool allowed);
|
bool allowed);
|
||||||
|
|
||||||
// Create window with the given disposition.
|
// Create window with the given disposition.
|
||||||
void OnCreateWindow(const GURL& target_url,
|
void OnCreateWindow(
|
||||||
const std::string& frame_name,
|
const GURL& target_url,
|
||||||
WindowOpenDisposition disposition,
|
const std::string& frame_name,
|
||||||
const std::vector<base::string16>& features);
|
WindowOpenDisposition disposition,
|
||||||
|
const std::vector<base::string16>& features,
|
||||||
|
const scoped_refptr<content::ResourceRequestBodyImpl>& body);
|
||||||
|
|
||||||
// Returns the web preferences of current WebContents.
|
// Returns the web preferences of current WebContents.
|
||||||
v8::Local<v8::Value> GetWebPreferences(v8::Isolate* isolate);
|
v8::Local<v8::Value> GetWebPreferences(v8::Isolate* isolate);
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include "chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.h"
|
#include "chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.h"
|
||||||
#include "chrome/browser/renderer_host/pepper/widevine_cdm_message_filter.h"
|
#include "chrome/browser/renderer_host/pepper/widevine_cdm_message_filter.h"
|
||||||
#include "chrome/browser/speech/tts_message_filter.h"
|
#include "chrome/browser/speech/tts_message_filter.h"
|
||||||
|
#include "content/common/resource_request_body_impl.h"
|
||||||
#include "content/public/browser/browser_ppapi_host.h"
|
#include "content/public/browser/browser_ppapi_host.h"
|
||||||
#include "content/public/browser/client_certificate_delegate.h"
|
#include "content/public/browser/client_certificate_delegate.h"
|
||||||
#include "content/public/browser/geolocation_delegate.h"
|
#include "content/public/browser/geolocation_delegate.h"
|
||||||
|
@ -319,7 +320,7 @@ bool AtomBrowserClient::CanCreateWindow(
|
||||||
WindowOpenDisposition disposition,
|
WindowOpenDisposition disposition,
|
||||||
const blink::WebWindowFeatures& features,
|
const blink::WebWindowFeatures& features,
|
||||||
const std::vector<base::string16>& additional_features,
|
const std::vector<base::string16>& additional_features,
|
||||||
const scoped_refptr<ResourceRequestBodyImpl>& body,
|
const scoped_refptr<content::ResourceRequestBodyImpl>& body,
|
||||||
bool user_gesture,
|
bool user_gesture,
|
||||||
bool opener_suppressed,
|
bool opener_suppressed,
|
||||||
content::ResourceContext* context,
|
content::ResourceContext* context,
|
||||||
|
@ -342,6 +343,7 @@ bool AtomBrowserClient::CanCreateWindow(
|
||||||
frame_name,
|
frame_name,
|
||||||
disposition,
|
disposition,
|
||||||
additional_features,
|
additional_features,
|
||||||
|
body,
|
||||||
render_process_id,
|
render_process_id,
|
||||||
opener_render_frame_id));
|
opener_render_frame_id));
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,8 +13,6 @@
|
||||||
#include "brightray/browser/browser_client.h"
|
#include "brightray/browser/browser_client.h"
|
||||||
#include "content/public/browser/render_process_host_observer.h"
|
#include "content/public/browser/render_process_host_observer.h"
|
||||||
|
|
||||||
using content::ResourceRequestBodyImpl;
|
|
||||||
|
|
||||||
namespace content {
|
namespace content {
|
||||||
class QuotaPermissionContext;
|
class QuotaPermissionContext;
|
||||||
class ClientCertificateDelegate;
|
class ClientCertificateDelegate;
|
||||||
|
@ -81,24 +79,25 @@ class AtomBrowserClient : public brightray::BrowserClient,
|
||||||
net::SSLCertRequestInfo* cert_request_info,
|
net::SSLCertRequestInfo* cert_request_info,
|
||||||
std::unique_ptr<content::ClientCertificateDelegate> delegate) override;
|
std::unique_ptr<content::ClientCertificateDelegate> delegate) override;
|
||||||
void ResourceDispatcherHostCreated() override;
|
void ResourceDispatcherHostCreated() override;
|
||||||
bool CanCreateWindow(const GURL& opener_url,
|
bool CanCreateWindow(
|
||||||
const GURL& opener_top_level_frame_url,
|
const GURL& opener_url,
|
||||||
const GURL& source_origin,
|
const GURL& opener_top_level_frame_url,
|
||||||
WindowContainerType container_type,
|
const GURL& source_origin,
|
||||||
const std::string& frame_name,
|
WindowContainerType container_type,
|
||||||
const GURL& target_url,
|
const std::string& frame_name,
|
||||||
const content::Referrer& referrer,
|
const GURL& target_url,
|
||||||
WindowOpenDisposition disposition,
|
const content::Referrer& referrer,
|
||||||
const blink::WebWindowFeatures& features,
|
WindowOpenDisposition disposition,
|
||||||
const std::vector<base::string16>& additional_features,
|
const blink::WebWindowFeatures& features,
|
||||||
const scoped_refptr<ResourceRequestBodyImpl>& body,
|
const std::vector<base::string16>& additional_features,
|
||||||
bool user_gesture,
|
const scoped_refptr<content::ResourceRequestBodyImpl>& body,
|
||||||
bool opener_suppressed,
|
bool user_gesture,
|
||||||
content::ResourceContext* context,
|
bool opener_suppressed,
|
||||||
int render_process_id,
|
content::ResourceContext* context,
|
||||||
int opener_render_view_id,
|
int render_process_id,
|
||||||
int opener_render_frame_id,
|
int opener_render_view_id,
|
||||||
bool* no_javascript_access) override;
|
int opener_render_frame_id,
|
||||||
|
bool* no_javascript_access) override;
|
||||||
void GetAdditionalAllowedSchemesForFileSystem(
|
void GetAdditionalAllowedSchemesForFileSystem(
|
||||||
std::vector<std::string>* schemes) override;
|
std::vector<std::string>* schemes) override;
|
||||||
|
|
||||||
|
|
|
@ -14,10 +14,14 @@
|
||||||
#include "atom/common/native_mate_converters/gurl_converter.h"
|
#include "atom/common/native_mate_converters/gurl_converter.h"
|
||||||
#include "atom/common/native_mate_converters/string16_converter.h"
|
#include "atom/common/native_mate_converters/string16_converter.h"
|
||||||
#include "atom/common/native_mate_converters/ui_base_types_converter.h"
|
#include "atom/common/native_mate_converters/ui_base_types_converter.h"
|
||||||
|
#include "atom/common/native_mate_converters/value_converter.h"
|
||||||
|
#include "content/common/resource_request_body_impl.h"
|
||||||
#include "content/public/browser/web_contents.h"
|
#include "content/public/browser/web_contents.h"
|
||||||
#include "content/public/common/context_menu_params.h"
|
#include "content/public/common/context_menu_params.h"
|
||||||
#include "native_mate/dictionary.h"
|
#include "native_mate/dictionary.h"
|
||||||
|
|
||||||
|
using content::ResourceRequestBodyImpl;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
void ExecuteCommand(content::WebContents* web_contents,
|
void ExecuteCommand(content::WebContents* web_contents,
|
||||||
|
@ -195,6 +199,102 @@ bool Converter<content::StopFindAction>::FromV8(
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
v8::Local<v8::Value>
|
||||||
|
Converter<scoped_refptr<ResourceRequestBodyImpl>>::ToV8(
|
||||||
|
v8::Isolate* isolate,
|
||||||
|
const scoped_refptr<ResourceRequestBodyImpl>& val) {
|
||||||
|
if (!val)
|
||||||
|
return v8::Null(isolate);
|
||||||
|
std::unique_ptr<base::ListValue> list(new base::ListValue);
|
||||||
|
for (const auto& element : *(val->elements())) {
|
||||||
|
std::unique_ptr<base::DictionaryValue> post_data_dict(
|
||||||
|
new base::DictionaryValue);
|
||||||
|
auto type = element.type();
|
||||||
|
if (type == ResourceRequestBodyImpl::Element::TYPE_BYTES) {
|
||||||
|
std::unique_ptr<base::Value> bytes(
|
||||||
|
base::BinaryValue::CreateWithCopiedBuffer(
|
||||||
|
element.bytes(), static_cast<size_t>(element.length())));
|
||||||
|
post_data_dict->SetString("type", "rawData");
|
||||||
|
post_data_dict->Set("bytes", std::move(bytes));
|
||||||
|
} else if (type == ResourceRequestBodyImpl::Element::TYPE_FILE) {
|
||||||
|
post_data_dict->SetString("type", "file");
|
||||||
|
post_data_dict->SetStringWithoutPathExpansion(
|
||||||
|
"filePath", element.path().AsUTF8Unsafe());
|
||||||
|
post_data_dict->SetInteger("offset", static_cast<int>(element.offset()));
|
||||||
|
post_data_dict->SetInteger("length", static_cast<int>(element.length()));
|
||||||
|
post_data_dict->SetDouble(
|
||||||
|
"modificationTime", element.expected_modification_time().ToDoubleT());
|
||||||
|
} else if (type == ResourceRequestBodyImpl::Element::TYPE_FILE_FILESYSTEM) {
|
||||||
|
post_data_dict->SetString("type", "fileSystem");
|
||||||
|
post_data_dict->SetStringWithoutPathExpansion(
|
||||||
|
"fileSystemURL", element.filesystem_url().spec());
|
||||||
|
post_data_dict->SetInteger("offset", static_cast<int>(element.offset()));
|
||||||
|
post_data_dict->SetInteger("length", static_cast<int>(element.length()));
|
||||||
|
post_data_dict->SetDouble(
|
||||||
|
"modificationTime", element.expected_modification_time().ToDoubleT());
|
||||||
|
} else if (type == ResourceRequestBodyImpl::Element::TYPE_BLOB) {
|
||||||
|
post_data_dict->SetString("type", "blob");
|
||||||
|
post_data_dict->SetString("blobUUID", element.blob_uuid());
|
||||||
|
}
|
||||||
|
list->Append(std::move(post_data_dict));
|
||||||
|
}
|
||||||
|
return ConvertToV8(isolate, *list);
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
bool Converter<scoped_refptr<ResourceRequestBodyImpl>>::FromV8(
|
||||||
|
v8::Isolate* isolate,
|
||||||
|
v8::Local<v8::Value> val,
|
||||||
|
scoped_refptr<ResourceRequestBodyImpl>* out) {
|
||||||
|
std::unique_ptr<base::ListValue> list(new base::ListValue);
|
||||||
|
if (!ConvertFromV8(isolate, val, list.get()))
|
||||||
|
return false;
|
||||||
|
*out = new content::ResourceRequestBodyImpl();
|
||||||
|
for (size_t i = 0; i < list->GetSize(); ++i) {
|
||||||
|
base::DictionaryValue* dict = nullptr;
|
||||||
|
std::string type;
|
||||||
|
if (!list->GetDictionary(i, &dict))
|
||||||
|
return false;
|
||||||
|
dict->GetString("type", &type);
|
||||||
|
if (type == "rawData") {
|
||||||
|
base::BinaryValue* bytes = nullptr;
|
||||||
|
dict->GetBinary("bytes", &bytes);
|
||||||
|
(*out)->AppendBytes(bytes->GetBuffer(), bytes->GetSize());
|
||||||
|
} else if (type == "file") {
|
||||||
|
std::string file;
|
||||||
|
int offset = 0, length = -1;
|
||||||
|
double modification_time = 0.0;
|
||||||
|
dict->GetStringWithoutPathExpansion("filePath", &file);
|
||||||
|
dict->GetInteger("offset", &offset);
|
||||||
|
dict->GetInteger("file", &length);
|
||||||
|
dict->GetDouble("modificationTime", &modification_time);
|
||||||
|
(*out)->AppendFileRange(base::FilePath::FromUTF8Unsafe(file),
|
||||||
|
static_cast<uint64_t>(offset),
|
||||||
|
static_cast<uint64_t>(length),
|
||||||
|
base::Time::FromDoubleT(modification_time));
|
||||||
|
} else if (type == "fileSystem") {
|
||||||
|
std::string file_system_url;
|
||||||
|
int offset = 0, length = -1;
|
||||||
|
double modification_time = 0.0;
|
||||||
|
dict->GetStringWithoutPathExpansion("fileSystemURL", &file_system_url);
|
||||||
|
dict->GetInteger("offset", &offset);
|
||||||
|
dict->GetInteger("file", &length);
|
||||||
|
dict->GetDouble("modificationTime", &modification_time);
|
||||||
|
(*out)->AppendFileSystemFileRange(
|
||||||
|
GURL(file_system_url),
|
||||||
|
static_cast<uint64_t>(offset),
|
||||||
|
static_cast<uint64_t>(length),
|
||||||
|
base::Time::FromDoubleT(modification_time));
|
||||||
|
} else if (type == "blob") {
|
||||||
|
std::string uuid;
|
||||||
|
dict->GetString("blobUUID", &uuid);
|
||||||
|
(*out)->AppendBlob(uuid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
v8::Local<v8::Value> Converter<content::WebContents*>::ToV8(
|
v8::Local<v8::Value> Converter<content::WebContents*>::ToV8(
|
||||||
v8::Isolate* isolate, content::WebContents* val) {
|
v8::Isolate* isolate, content::WebContents* val) {
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
|
|
||||||
namespace content {
|
namespace content {
|
||||||
struct ContextMenuParams;
|
struct ContextMenuParams;
|
||||||
|
class ResourceRequestBodyImpl;
|
||||||
class WebContents;
|
class WebContents;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,6 +48,15 @@ struct Converter<content::PermissionType> {
|
||||||
const content::PermissionType& val);
|
const content::PermissionType& val);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct Converter<scoped_refptr<content::ResourceRequestBodyImpl>> {
|
||||||
|
static v8::Local<v8::Value> ToV8(
|
||||||
|
v8::Isolate* isolate,
|
||||||
|
const scoped_refptr<content::ResourceRequestBodyImpl>& val);
|
||||||
|
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
|
||||||
|
scoped_refptr<content::ResourceRequestBodyImpl>* out);
|
||||||
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct Converter<content::StopFindAction> {
|
struct Converter<content::StopFindAction> {
|
||||||
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
|
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
|
||||||
|
|
|
@ -969,6 +969,7 @@ Same as `webContents.capturePage([rect, ]callback)`.
|
||||||
* `httpReferrer` String (optional) - A HTTP Referrer url.
|
* `httpReferrer` String (optional) - A HTTP Referrer url.
|
||||||
* `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)
|
||||||
|
|
||||||
Same as `webContents.loadURL(url[, options])`.
|
Same as `webContents.loadURL(url[, options])`.
|
||||||
|
|
||||||
|
|
4
docs/api/structures/upload-blob.md
Normal file
4
docs/api/structures/upload-blob.md
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
# Upload Blob Object
|
||||||
|
|
||||||
|
* `type` String - `blob`.
|
||||||
|
* `blobUUID` String - UUID of blob data to upload.
|
9
docs/api/structures/upload-file-system.md
Normal file
9
docs/api/structures/upload-file-system.md
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
# Upload FileSystem Object
|
||||||
|
|
||||||
|
* `type` String - `fileSystem`.
|
||||||
|
* `filsSystemURL` String - FileSystem url to read data for upload.
|
||||||
|
* `offset` Integer - Defaults to `0`.
|
||||||
|
* `length` Integer - Number of bytes to read from `offset`.
|
||||||
|
Defaults to `0`.
|
||||||
|
* `modificationTime` Double - Last Modification time in
|
||||||
|
number of seconds sine the UNIX epoch.
|
9
docs/api/structures/upload-file.md
Normal file
9
docs/api/structures/upload-file.md
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
# Upload File Object
|
||||||
|
|
||||||
|
* `type` String - `file`.
|
||||||
|
* `filePath` String - Path of file to be uploaded.
|
||||||
|
* `offset` Integer - Defaults to `0`.
|
||||||
|
* `length` Integer - Number of bytes to read from `offset`.
|
||||||
|
Defaults to `0`.
|
||||||
|
* `modificationTime` Double - Last Modification time in
|
||||||
|
number of seconds sine the UNIX epoch.
|
4
docs/api/structures/upload-raw-data.md
Normal file
4
docs/api/structures/upload-raw-data.md
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
# Upload RawData Object
|
||||||
|
|
||||||
|
* `type` String - `rawData`.
|
||||||
|
* `bytes` Buffer - Data to be uploaded.
|
|
@ -487,9 +487,10 @@ win.loadURL('http://github.com')
|
||||||
|
|
||||||
* `url` URL
|
* `url` URL
|
||||||
* `options` Object (optional)
|
* `options` Object (optional)
|
||||||
* `httpReferrer` String - A HTTP Referrer url.
|
* `httpReferrer` String (optional) - A HTTP Referrer url.
|
||||||
* `userAgent` String - A user agent originating the request.
|
* `userAgent` String (optional) - A user agent originating the request.
|
||||||
* `extraHeaders` String - 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)
|
||||||
|
|
||||||
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
|
||||||
|
|
|
@ -262,9 +262,10 @@ webview.addEventListener('dom-ready', () => {
|
||||||
|
|
||||||
* `url` URL
|
* `url` URL
|
||||||
* `options` Object (optional)
|
* `options` Object (optional)
|
||||||
* `httpReferrer` String - A HTTP Referrer url.
|
* `httpReferrer` String (optional) - A HTTP Referrer url.
|
||||||
* `userAgent` String - A user agent originating the request.
|
* `userAgent` String (optional) - A user agent originating the request.
|
||||||
* `extraHeaders` String - 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)
|
||||||
|
|
||||||
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://`.
|
||||||
|
|
|
@ -18,13 +18,17 @@ BrowserWindow.prototype._init = function () {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make new windows requested by links behave like "window.open"
|
// Make new windows requested by links behave like "window.open"
|
||||||
this.webContents.on('-new-window', (event, url, frameName, disposition, additionalFeatures) => {
|
this.webContents.on('-new-window', (event, url, frameName,
|
||||||
|
disposition, additionalFeatures,
|
||||||
|
postData) => {
|
||||||
const options = {
|
const options = {
|
||||||
show: true,
|
show: true,
|
||||||
width: 800,
|
width: 800,
|
||||||
height: 600
|
height: 600
|
||||||
}
|
}
|
||||||
ipcMain.emit('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_OPEN', event, url, frameName, disposition, options, additionalFeatures)
|
ipcMain.emit('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_OPEN',
|
||||||
|
event, url, frameName, disposition,
|
||||||
|
options, additionalFeatures, postData)
|
||||||
})
|
})
|
||||||
|
|
||||||
this.webContents.on('-web-contents-created', (event, webContents, url,
|
this.webContents.on('-web-contents-created', (event, webContents, url,
|
||||||
|
|
|
@ -84,7 +84,7 @@ const setupGuest = function (embedder, frameName, guest, options) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new guest created by |embedder| with |options|.
|
// Create a new guest created by |embedder| with |options|.
|
||||||
const createGuest = function (embedder, url, frameName, options) {
|
const createGuest = function (embedder, url, frameName, options, postData) {
|
||||||
let guest = frameToGuest[frameName]
|
let guest = frameToGuest[frameName]
|
||||||
if (frameName && (guest != null)) {
|
if (frameName && (guest != null)) {
|
||||||
guest.loadURL(url)
|
guest.loadURL(url)
|
||||||
|
@ -119,7 +119,19 @@ const createGuest = function (embedder, url, frameName, options) {
|
||||||
//
|
//
|
||||||
// The above code would not work if a navigation to "about:blank" is done
|
// The above code would not work if a navigation to "about:blank" is done
|
||||||
// here, since the window would be cleared of all changes in the next tick.
|
// here, since the window would be cleared of all changes in the next tick.
|
||||||
guest.loadURL(url)
|
const loadOptions = {}
|
||||||
|
if (postData != null) {
|
||||||
|
loadOptions.postData = postData
|
||||||
|
loadOptions.extraHeaders = 'content-type: application/x-www-form-urlencoded'
|
||||||
|
if (postData.length > 0) {
|
||||||
|
const postDataFront = postData[0].bytes.toString()
|
||||||
|
const boundary = /^--.*[^-\r\n]/.exec(postDataFront)
|
||||||
|
if (boundary != null) {
|
||||||
|
loadOptions.extraHeaders = `content-type: multipart/form-data; boundary=${boundary[0].substr(2)}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
guest.loadURL(url, loadOptions)
|
||||||
}
|
}
|
||||||
|
|
||||||
return setupGuest(embedder, frameName, guest, options)
|
return setupGuest(embedder, frameName, guest, options)
|
||||||
|
@ -140,7 +152,9 @@ const getGuestWindow = function (guestId) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Routed window.open messages.
|
// Routed window.open messages.
|
||||||
ipcMain.on('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_OPEN', function (event, url, frameName, disposition, options, additionalFeatures) {
|
ipcMain.on('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_OPEN', function (event, url, frameName,
|
||||||
|
disposition, options,
|
||||||
|
additionalFeatures, postData) {
|
||||||
options = mergeBrowserWindowOptions(event.sender, options)
|
options = mergeBrowserWindowOptions(event.sender, options)
|
||||||
event.sender.emit('new-window', event, url, frameName, disposition, options, additionalFeatures)
|
event.sender.emit('new-window', event, url, frameName, disposition, options, additionalFeatures)
|
||||||
const newGuest = event.newGuest
|
const newGuest = event.newGuest
|
||||||
|
@ -151,7 +165,7 @@ ipcMain.on('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_OPEN', function (event, url, fr
|
||||||
event.returnValue = null
|
event.returnValue = null
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
event.returnValue = createGuest(event.sender, url, frameName, options)
|
event.returnValue = createGuest(event.sender, url, frameName, options, postData)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -4,28 +4,59 @@ const assert = require('assert')
|
||||||
const fs = require('fs')
|
const fs = require('fs')
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
const os = require('os')
|
const os = require('os')
|
||||||
|
const qs = require('querystring')
|
||||||
const http = require('http')
|
const http = require('http')
|
||||||
const {closeWindow} = require('./window-helpers')
|
const {closeWindow} = require('./window-helpers')
|
||||||
|
|
||||||
const remote = require('electron').remote
|
const {ipcRenderer, remote, screen} = require('electron')
|
||||||
const screen = require('electron').screen
|
const {app, ipcMain, BrowserWindow, protocol} = remote
|
||||||
|
|
||||||
const app = remote.require('electron').app
|
|
||||||
const ipcMain = remote.require('electron').ipcMain
|
|
||||||
const ipcRenderer = require('electron').ipcRenderer
|
|
||||||
const BrowserWindow = remote.require('electron').BrowserWindow
|
|
||||||
|
|
||||||
const isCI = remote.getGlobal('isCi')
|
const isCI = remote.getGlobal('isCi')
|
||||||
const {protocol} = remote
|
|
||||||
|
|
||||||
describe('browser-window module', function () {
|
describe('browser-window module', function () {
|
||||||
var fixtures = path.resolve(__dirname, 'fixtures')
|
var fixtures = path.resolve(__dirname, 'fixtures')
|
||||||
var w = null
|
var w = null
|
||||||
var server
|
var server, postData
|
||||||
|
|
||||||
before(function (done) {
|
before(function (done) {
|
||||||
|
const filePath = path.join(fixtures, 'pages', 'a.html')
|
||||||
|
const fileStats = fs.statSync(filePath)
|
||||||
|
postData = [
|
||||||
|
{
|
||||||
|
type: 'rawData',
|
||||||
|
bytes: new Buffer('username=test&file=')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'file',
|
||||||
|
filePath: filePath,
|
||||||
|
offset: 0,
|
||||||
|
length: fileStats.size,
|
||||||
|
modificationTime: fileStats.mtime.getTime() / 1000
|
||||||
|
}
|
||||||
|
]
|
||||||
server = http.createServer(function (req, res) {
|
server = http.createServer(function (req, res) {
|
||||||
function respond () { res.end('') }
|
function respond () {
|
||||||
|
if (req.method === 'POST') {
|
||||||
|
let body = ''
|
||||||
|
req.on('data', (data) => {
|
||||||
|
if (data) {
|
||||||
|
body += data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
req.on('end', () => {
|
||||||
|
let parsedData = qs.parse(body)
|
||||||
|
fs.readFile(filePath, (err, data) => {
|
||||||
|
if (err) return
|
||||||
|
if (parsedData.username === 'test' &&
|
||||||
|
parsedData.file === data.toString()) {
|
||||||
|
res.end()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
res.end()
|
||||||
|
}
|
||||||
|
}
|
||||||
setTimeout(respond, req.url.includes('slow') ? 200 : 0)
|
setTimeout(respond, req.url.includes('slow') ? 200 : 0)
|
||||||
})
|
})
|
||||||
server.listen(0, '127.0.0.1', function () {
|
server.listen(0, '127.0.0.1', function () {
|
||||||
|
@ -187,6 +218,54 @@ describe('browser-window module', function () {
|
||||||
})
|
})
|
||||||
w.loadURL('http://127.0.0.1:11111')
|
w.loadURL('http://127.0.0.1:11111')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('POST navigations', function () {
|
||||||
|
afterEach(() => {
|
||||||
|
w.webContents.session.webRequest.onBeforeSendHeaders(null)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('supports specifying POST data', function (done) {
|
||||||
|
w.webContents.on('did-finish-load', () => done())
|
||||||
|
w.loadURL(server.url, {postData: postData})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('sets the content type header on URL encoded forms', function (done) {
|
||||||
|
w.webContents.on('did-finish-load', () => {
|
||||||
|
w.webContents.session.webRequest.onBeforeSendHeaders((details, callback) => {
|
||||||
|
assert.equal(details.requestHeaders['content-type'], 'application/x-www-form-urlencoded')
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
w.webContents.executeJavaScript(`
|
||||||
|
form = document.createElement('form')
|
||||||
|
form.method = 'POST'
|
||||||
|
form.target = '_blank'
|
||||||
|
form.submit()
|
||||||
|
`)
|
||||||
|
})
|
||||||
|
w.loadURL(server.url)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('sets the content type header on multi part forms', function (done) {
|
||||||
|
w.webContents.on('did-finish-load', () => {
|
||||||
|
w.webContents.session.webRequest.onBeforeSendHeaders((details, callback) => {
|
||||||
|
assert(details.requestHeaders['content-type'].startsWith('multipart/form-data; boundary=----WebKitFormBoundary'))
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
w.webContents.executeJavaScript(`
|
||||||
|
form = document.createElement('form')
|
||||||
|
form.method = 'POST'
|
||||||
|
form.target = '_blank'
|
||||||
|
form.enctype = 'multipart/form-data'
|
||||||
|
file = document.createElement('input')
|
||||||
|
file.type = 'file'
|
||||||
|
file.name = 'file'
|
||||||
|
form.appendChild(file)
|
||||||
|
form.submit()
|
||||||
|
`)
|
||||||
|
})
|
||||||
|
w.loadURL(server.url)
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('BrowserWindow.show()', function () {
|
describe('BrowserWindow.show()', function () {
|
||||||
|
|
Loading…
Reference in a new issue