webContents: handle POST navigation for new windows

This commit is contained in:
deepak1556 2016-10-10 05:00:38 +05:30 committed by Kevin Sawicki
parent 7cfe1dd0af
commit 0410a184ce
10 changed files with 187 additions and 49 deletions

View file

@ -528,12 +528,14 @@ void App::OnLogin(LoginHandler* login_handler,
login_handler->CancelAuth();
}
void App::OnCreateWindow(const GURL& target_url,
const std::string& frame_name,
WindowOpenDisposition disposition,
const std::vector<base::string16>& features,
int render_process_id,
int render_frame_id) {
void App::OnCreateWindow(
const GURL& target_url,
const std::string& frame_name,
WindowOpenDisposition disposition,
const std::vector<base::string16>& features,
const scoped_refptr<content::ResourceRequestBodyImpl>& body,
int render_process_id,
int render_frame_id) {
v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate());
content::RenderFrameHost* rfh =
@ -545,7 +547,8 @@ void App::OnCreateWindow(const GURL& target_url,
api_web_contents->OnCreateWindow(target_url,
frame_name,
disposition,
features);
features,
body);
}
}

View file

@ -48,12 +48,14 @@ class App : public AtomBrowserClient::Delegate,
v8::Local<v8::FunctionTemplate> prototype);
// Called when window with disposition needs to be created.
void OnCreateWindow(const GURL& target_url,
const std::string& frame_name,
WindowOpenDisposition disposition,
const std::vector<base::string16>& features,
int render_process_id,
int render_frame_id);
void OnCreateWindow(
const GURL& target_url,
const std::string& frame_name,
WindowOpenDisposition disposition,
const std::vector<base::string16>& features,
const scoped_refptr<content::ResourceRequestBodyImpl>& body,
int render_process_id,
int render_frame_id);
#if defined(USE_NSS_CERTS)
void OnCertificateManagerModelCreated(

View file

@ -387,12 +387,14 @@ bool WebContents::AddMessageToConsole(content::WebContents* source,
}
}
void WebContents::OnCreateWindow(const GURL& target_url,
const std::string& frame_name,
WindowOpenDisposition disposition,
const std::vector<base::string16>& features) {
void WebContents::OnCreateWindow(
const GURL& target_url,
const std::string& frame_name,
WindowOpenDisposition disposition,
const std::vector<base::string16>& features,
const scoped_refptr<content::ResourceRequestBodyImpl>& body) {
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
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))
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.should_clear_history_list = true;
params.override_user_agent = content::NavigationController::UA_OVERRIDE_TRUE;

View file

@ -26,6 +26,10 @@ namespace brightray {
class InspectableWebContents;
}
namespace content {
class ResourceRequestBodyImpl;
}
namespace mate {
class Arguments;
class Dictionary;
@ -176,10 +180,12 @@ class WebContents : public mate::TrackableObject<WebContents>,
bool allowed);
// Create window with the given disposition.
void OnCreateWindow(const GURL& target_url,
const std::string& frame_name,
WindowOpenDisposition disposition,
const std::vector<base::string16>& features);
void OnCreateWindow(
const GURL& target_url,
const std::string& frame_name,
WindowOpenDisposition disposition,
const std::vector<base::string16>& features,
const scoped_refptr<content::ResourceRequestBodyImpl>& body);
// Returns the web preferences of current WebContents.
v8::Local<v8::Value> GetWebPreferences(v8::Isolate* isolate);

View file

@ -30,6 +30,7 @@
#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/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/client_certificate_delegate.h"
#include "content/public/browser/geolocation_delegate.h"
@ -319,7 +320,7 @@ bool AtomBrowserClient::CanCreateWindow(
WindowOpenDisposition disposition,
const blink::WebWindowFeatures& features,
const std::vector<base::string16>& additional_features,
const scoped_refptr<ResourceRequestBodyImpl>& body,
const scoped_refptr<content::ResourceRequestBodyImpl>& body,
bool user_gesture,
bool opener_suppressed,
content::ResourceContext* context,
@ -342,6 +343,7 @@ bool AtomBrowserClient::CanCreateWindow(
frame_name,
disposition,
additional_features,
body,
render_process_id,
opener_render_frame_id));
}

View file

@ -13,8 +13,6 @@
#include "brightray/browser/browser_client.h"
#include "content/public/browser/render_process_host_observer.h"
using content::ResourceRequestBodyImpl;
namespace content {
class QuotaPermissionContext;
class ClientCertificateDelegate;
@ -81,24 +79,25 @@ class AtomBrowserClient : public brightray::BrowserClient,
net::SSLCertRequestInfo* cert_request_info,
std::unique_ptr<content::ClientCertificateDelegate> delegate) override;
void ResourceDispatcherHostCreated() override;
bool CanCreateWindow(const GURL& opener_url,
const GURL& opener_top_level_frame_url,
const GURL& source_origin,
WindowContainerType container_type,
const std::string& frame_name,
const GURL& target_url,
const content::Referrer& referrer,
WindowOpenDisposition disposition,
const blink::WebWindowFeatures& features,
const std::vector<base::string16>& additional_features,
const scoped_refptr<ResourceRequestBodyImpl>& body,
bool user_gesture,
bool opener_suppressed,
content::ResourceContext* context,
int render_process_id,
int opener_render_view_id,
int opener_render_frame_id,
bool* no_javascript_access) override;
bool CanCreateWindow(
const GURL& opener_url,
const GURL& opener_top_level_frame_url,
const GURL& source_origin,
WindowContainerType container_type,
const std::string& frame_name,
const GURL& target_url,
const content::Referrer& referrer,
WindowOpenDisposition disposition,
const blink::WebWindowFeatures& features,
const std::vector<base::string16>& additional_features,
const scoped_refptr<content::ResourceRequestBodyImpl>& body,
bool user_gesture,
bool opener_suppressed,
content::ResourceContext* context,
int render_process_id,
int opener_render_view_id,
int opener_render_frame_id,
bool* no_javascript_access) override;
void GetAdditionalAllowedSchemesForFileSystem(
std::vector<std::string>* schemes) override;

View file

@ -14,10 +14,14 @@
#include "atom/common/native_mate_converters/gurl_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/value_converter.h"
#include "content/common/resource_request_body_impl.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/context_menu_params.h"
#include "native_mate/dictionary.h"
using content::ResourceRequestBodyImpl;
namespace {
void ExecuteCommand(content::WebContents* web_contents,
@ -195,6 +199,101 @@ bool Converter<content::StopFindAction>::FromV8(
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", "data");
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 (int i = 0; i < list->GetSize(); ++i) {
base::DictionaryValue* dict = nullptr;
std::string type;
list->GetDictionary(i, &dict);
dict->GetString("type", &type);
if (type == "data") {
base::BinaryValue* bytes = nullptr;
dict->GetBinary("bytes", &bytes);
(*out)->AppendBytes(bytes->GetBuffer(), bytes->GetSize());
} else if (type == "file") {
std::string file;
int offset, length;
double modification_time;
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, length;
double modification_time;
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
v8::Local<v8::Value> Converter<content::WebContents*>::ToV8(
v8::Isolate* isolate, content::WebContents* val) {

View file

@ -15,6 +15,7 @@
namespace content {
struct ContextMenuParams;
class ResourceRequestBodyImpl;
class WebContents;
}
@ -47,6 +48,15 @@ struct Converter<content::PermissionType> {
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<>
struct Converter<content::StopFindAction> {
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,

View file

@ -18,13 +18,17 @@ BrowserWindow.prototype._init = function () {
}
// 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 = {
show: true,
width: 800,
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,

View file

@ -84,7 +84,7 @@ const setupGuest = function (embedder, frameName, guest, 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]
if (frameName && (guest != null)) {
guest.loadURL(url)
@ -119,7 +119,10 @@ const createGuest = function (embedder, url, frameName, options) {
//
// 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.
guest.loadURL(url)
const loadOptions = {}
if (postData)
loadOptions.postData = postData
guest.loadURL(url, loadOptions)
}
return setupGuest(embedder, frameName, guest, options)
@ -140,7 +143,9 @@ const getGuestWindow = function (guestId) {
}
// 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)
event.sender.emit('new-window', event, url, frameName, disposition, options, additionalFeatures)
const newGuest = event.newGuest
@ -151,7 +156,7 @@ ipcMain.on('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_OPEN', function (event, url, fr
event.returnValue = null
}
} else {
event.returnValue = createGuest(event.sender, url, frameName, options)
event.returnValue = createGuest(event.sender, url, frameName, options, postData)
}
})