diff --git a/atom/browser/api/event.cc b/atom/browser/api/event.cc index c5465716892..7b617034eca 100644 --- a/atom/browser/api/event.cc +++ b/atom/browser/api/event.cc @@ -6,6 +6,7 @@ #include "atom/common/api/api_messages.h" #include "atom/common/native_mate_converters/string16_converter.h" +#include "atom/common/native_mate_converters/value_converter.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/web_contents.h" #include "native_mate/object_template_builder.h" @@ -52,11 +53,11 @@ void Event::PreventDefault(v8::Isolate* isolate) { GetWrapper()->Set(StringToV8(isolate, "defaultPrevented"), v8::True(isolate)); } -bool Event::SendReply(const base::string16& json) { +bool Event::SendReply(const base::ListValue& result) { if (message_ == nullptr || sender_ == nullptr) return false; - AtomFrameHostMsg_Message_Sync::WriteReplyParams(message_, json); + AtomFrameHostMsg_Message_Sync::WriteReplyParams(message_, result); bool success = sender_->Send(message_); message_ = nullptr; sender_ = nullptr; diff --git a/atom/browser/api/event.h b/atom/browser/api/event.h index d4fee5ae237..fbec8f27574 100644 --- a/atom/browser/api/event.h +++ b/atom/browser/api/event.h @@ -29,8 +29,8 @@ class Event : public Wrappable, public content::WebContentsObserver { // event.PreventDefault(). void PreventDefault(v8::Isolate* isolate); - // event.sendReply(json), used for replying synchronous message. - bool SendReply(const base::string16& json); + // event.sendReply(array), used for replying synchronous message. + bool SendReply(const base::ListValue& result); protected: explicit Event(v8::Isolate* isolate); diff --git a/atom/common/api/api_messages.h b/atom/common/api/api_messages.h index 6dc30988bf7..6131a7a473c 100644 --- a/atom/common/api/api_messages.h +++ b/atom/common/api/api_messages.h @@ -31,7 +31,7 @@ IPC_MESSAGE_ROUTED2(AtomFrameHostMsg_Message, IPC_SYNC_MESSAGE_ROUTED2_1(AtomFrameHostMsg_Message_Sync, base::string16 /* channel */, base::ListValue /* arguments */, - base::string16 /* result (in JSON) */) + base::ListValue /* result */) IPC_MESSAGE_ROUTED3(AtomFrameMsg_Message, bool /* send_to_all */, diff --git a/atom/common/native_mate_converters/v8_value_converter.cc b/atom/common/native_mate_converters/v8_value_converter.cc index 6788a35e530..b97b5fdfd8e 100644 --- a/atom/common/native_mate_converters/v8_value_converter.cc +++ b/atom/common/native_mate_converters/v8_value_converter.cc @@ -13,6 +13,7 @@ #include "base/values.h" #include "native_mate/dictionary.h" +#include "atom/common/node_bindings.h" #include "atom/common/node_includes.h" namespace atom { @@ -136,10 +137,6 @@ void V8ValueConverter::SetStripNullFromObjects(bool val) { strip_null_from_objects_ = val; } -void V8ValueConverter::SetDisableNode(bool val) { - disable_node_ = val; -} - v8::Local V8ValueConverter::ToV8Value( const base::Value* value, v8::Local context) const { @@ -253,7 +250,7 @@ v8::Local V8ValueConverter::ToArrayBuffer( const char* data = value->GetBlob().data(); size_t length = value->GetBlob().size(); - if (!disable_node_) { + if (NodeBindings::IsInitialized()) { return node::Buffer::Copy(isolate, data, length).ToLocalChecked(); } diff --git a/atom/common/native_mate_converters/v8_value_converter.h b/atom/common/native_mate_converters/v8_value_converter.h index 364420d219d..353f5d13597 100644 --- a/atom/common/native_mate_converters/v8_value_converter.h +++ b/atom/common/native_mate_converters/v8_value_converter.h @@ -24,7 +24,6 @@ class V8ValueConverter { void SetRegExpAllowed(bool val); void SetFunctionAllowed(bool val); void SetStripNullFromObjects(bool val); - void SetDisableNode(bool val); v8::Local ToV8Value(const base::Value* value, v8::Local context) const; base::Value* FromV8Value(v8::Local value, @@ -63,13 +62,6 @@ class V8ValueConverter { // If true, we will convert Function JavaScript objects to dictionaries. bool function_allowed_ = false; - // If true, will not use node::Buffer::Copy to deserialize byte arrays. - // node::Buffer::Copy depends on a working node.js environment, and this is - // not desirable in sandboxed renderers. That means Buffer instances sent from - // browser process will be deserialized as browserify-based Buffer(which are - // wrappers around Uint8Array). - bool disable_node_ = false; - // If true, undefined and null values are ignored when converting v8 objects // into Values. bool strip_null_from_objects_ = false; diff --git a/atom/common/node_bindings.cc b/atom/common/node_bindings.cc index e939de07086..a3d5a16f651 100644 --- a/atom/common/node_bindings.cc +++ b/atom/common/node_bindings.cc @@ -104,6 +104,8 @@ void stop_and_close_uv_loop(uv_loop_t* loop) { uv_loop_close(loop); } +bool g_is_initialized = false; + } // namespace namespace atom { @@ -178,6 +180,10 @@ void NodeBindings::RegisterBuiltinModules() { #undef V } +bool NodeBindings::IsInitialized() { + return g_is_initialized; +} + void NodeBindings::Initialize() { // Open node's error reporting system for browser process. node::g_standalone_mode = browser_env_ == BROWSER; @@ -203,6 +209,8 @@ void NodeBindings::Initialize() { if (browser_env_ == BROWSER || env->HasVar("ELECTRON_DEFAULT_ERROR_MODE")) SetErrorMode(GetErrorMode() & ~SEM_NOGPFAULTERRORBOX); #endif + + g_is_initialized = true; } node::Environment* NodeBindings::CreateEnvironment( diff --git a/atom/common/node_bindings.h b/atom/common/node_bindings.h index 46c78cbe02b..7c8cad46cc6 100644 --- a/atom/common/node_bindings.h +++ b/atom/common/node_bindings.h @@ -32,6 +32,7 @@ class NodeBindings { static NodeBindings* Create(BrowserEnvironment browser_env); static void RegisterBuiltinModules(); + static bool IsInitialized(); virtual ~NodeBindings(); diff --git a/atom/renderer/api/atom_api_renderer_ipc.cc b/atom/renderer/api/atom_api_renderer_ipc.cc index dd04c8278d8..3e48a4f7d0c 100644 --- a/atom/renderer/api/atom_api_renderer_ipc.cc +++ b/atom/renderer/api/atom_api_renderer_ipc.cc @@ -6,6 +6,7 @@ #include "atom/common/api/api_messages.h" #include "atom/common/native_mate_converters/string16_converter.h" #include "atom/common/native_mate_converters/value_converter.h" +#include "atom/common/node_bindings.h" #include "atom/common/node_includes.h" #include "content/public/renderer/render_frame.h" #include "native_mate/dictionary.h" @@ -40,23 +41,23 @@ void Send(mate::Arguments* args, args->ThrowError("Unable to send AtomFrameHostMsg_Message"); } -base::string16 SendSync(mate::Arguments* args, - const base::string16& channel, - const base::ListValue& arguments) { - base::string16 json; +base::ListValue SendSync(mate::Arguments* args, + const base::string16& channel, + const base::ListValue& arguments) { + base::ListValue result; RenderFrame* render_frame = GetCurrentRenderFrame(); if (render_frame == nullptr) - return json; + return result; IPC::SyncMessage* message = new AtomFrameHostMsg_Message_Sync( - render_frame->GetRoutingID(), channel, arguments, &json); + render_frame->GetRoutingID(), channel, arguments, &result); bool success = render_frame->Send(message); if (!success) args->ThrowError("Unable to send AtomFrameHostMsg_Message_Sync"); - return json; + return result; } void Initialize(v8::Local exports, diff --git a/atom/renderer/api/atom_api_renderer_ipc.h b/atom/renderer/api/atom_api_renderer_ipc.h index 772d543cf6a..3aff3d02da5 100644 --- a/atom/renderer/api/atom_api_renderer_ipc.h +++ b/atom/renderer/api/atom_api_renderer_ipc.h @@ -16,9 +16,9 @@ void Send(mate::Arguments* args, const base::string16& channel, const base::ListValue& arguments); -base::string16 SendSync(mate::Arguments* args, - const base::string16& channel, - const base::ListValue& arguments); +base::ListValue SendSync(mate::Arguments* args, + const base::string16& channel, + const base::ListValue& arguments); void Initialize(v8::Local exports, v8::Local unused, diff --git a/atom/renderer/atom_sandboxed_renderer_client.cc b/atom/renderer/atom_sandboxed_renderer_client.cc index 9fd8864b9b7..ca66298fce1 100644 --- a/atom/renderer/atom_sandboxed_renderer_client.cc +++ b/atom/renderer/atom_sandboxed_renderer_client.cc @@ -7,7 +7,6 @@ #include "atom/common/api/api_messages.h" #include "atom/common/api/atom_bindings.h" #include "atom/common/native_mate_converters/string16_converter.h" -#include "atom/common/native_mate_converters/v8_value_converter.h" #include "atom/common/native_mate_converters/value_converter.h" #include "atom/common/node_bindings.h" #include "atom/common/options_switches.h" @@ -100,10 +99,7 @@ class AtomSandboxedRenderFrameObserver : public AtomRenderFrameObserver { AtomSandboxedRenderFrameObserver(content::RenderFrame* render_frame, AtomSandboxedRendererClient* renderer_client) : AtomRenderFrameObserver(render_frame, renderer_client), - v8_converter_(new atom::V8ValueConverter), - renderer_client_(renderer_client) { - v8_converter_->SetDisableNode(true); - } + renderer_client_(renderer_client) {} protected: void EmitIPCEvent(blink::WebLocalFrame* frame, @@ -117,14 +113,13 @@ class AtomSandboxedRenderFrameObserver : public AtomRenderFrameObserver { auto context = frame->MainWorldScriptContext(); v8::Context::Scope context_scope(context); v8::Local argv[] = {mate::ConvertToV8(isolate, channel), - v8_converter_->ToV8Value(&args, context)}; + mate::ConvertToV8(isolate, args)}; renderer_client_->InvokeIpcCallback( context, "onMessage", - std::vector>(argv, argv + 2)); + std::vector>(argv, argv + node::arraysize(argv))); } private: - std::unique_ptr v8_converter_; AtomSandboxedRendererClient* renderer_client_; DISALLOW_COPY_AND_ASSIGN(AtomSandboxedRenderFrameObserver); }; diff --git a/lib/browser/api/web-contents.js b/lib/browser/api/web-contents.js index ccfc26d7c01..f5f53f44a31 100644 --- a/lib/browser/api/web-contents.js +++ b/lib/browser/api/web-contents.js @@ -280,7 +280,7 @@ WebContents.prototype._init = function () { this.on('ipc-message-sync', function (event, [channel, ...args]) { Object.defineProperty(event, 'returnValue', { set: function (value) { - return event.sendReply(JSON.stringify(value)) + return event.sendReply([value]) }, get: function () {} }) diff --git a/lib/common/buffer-utils.js b/lib/common/buffer-utils.js index bd1303f4e90..baa73998645 100644 --- a/lib/common/buffer-utils.js +++ b/lib/common/buffer-utils.js @@ -26,25 +26,31 @@ function getType (value) { return null } +function getBuffer (value) { + if (value instanceof Buffer) { + return value + } else if (value instanceof ArrayBuffer) { + return Buffer.from(value) + } else { + return Buffer.from(value.buffer, value.byteOffset, value.byteLength) + } +} + exports.isBuffer = function (value) { return ArrayBuffer.isView(value) || value instanceof ArrayBuffer } exports.bufferToMeta = function (value) { - const buffer = (value instanceof ArrayBuffer) - ? Buffer.from(value) - : Buffer.from(value.buffer, value.byteOffset, value.byteLength) - return { type: getType(value), - data: buffer.toString('base64'), + data: getBuffer(value), length: value.length } } exports.metaToBuffer = function (value) { const constructor = typedArrays[value.type] - const data = Buffer.from(value.data, 'base64') + const data = getBuffer(value.data) if (constructor === Buffer) { return data diff --git a/lib/renderer/api/ipc-renderer.js b/lib/renderer/api/ipc-renderer.js index d173adb7786..3e138c1e5b0 100644 --- a/lib/renderer/api/ipc-renderer.js +++ b/lib/renderer/api/ipc-renderer.js @@ -11,7 +11,7 @@ ipcRenderer.send = function (...args) { } ipcRenderer.sendSync = function (...args) { - return JSON.parse(binding.sendSync('ipc-message-sync', args)) + return binding.sendSync('ipc-message-sync', args)[0] } ipcRenderer.sendToHost = function (...args) { diff --git a/spec/api-browser-window-spec.js b/spec/api-browser-window-spec.js index ae45b330e6d..711354fd6df 100644 --- a/spec/api-browser-window-spec.js +++ b/spec/api-browser-window-spec.js @@ -1381,24 +1381,25 @@ describe('BrowserWindow module', () => { }) let htmlPath = path.join(fixtures, 'api', 'sandbox.html?verify-ipc-sender') const pageUrl = 'file://' + htmlPath - w.loadURL(pageUrl) + let childWc w.webContents.once('new-window', (e, url, frameName, disposition, options) => { - let parentWc = w.webContents - let childWc = options.webContents - assert.notEqual(parentWc, childWc) - ipcMain.once('parent-ready', function (event) { - assert.equal(parentWc, event.sender) - parentWc.send('verified') - }) - ipcMain.once('child-ready', function (event) { - assert.equal(childWc, event.sender) - childWc.send('verified') - }) - waitForEvents(ipcMain, [ - 'parent-answer', - 'child-answer' - ], done) + childWc = options.webContents + assert.notEqual(w.webContents, childWc) }) + ipcMain.once('parent-ready', function (event) { + assert.equal(w.webContents, event.sender) + event.sender.send('verified') + }) + ipcMain.once('child-ready', function (event) { + assert(childWc) + assert.equal(childWc, event.sender) + event.sender.send('verified') + }) + waitForEvents(ipcMain, [ + 'parent-answer', + 'child-answer' + ], done) + w.loadURL(pageUrl) }) describe('event handling', () => { diff --git a/spec/api-remote-spec.js b/spec/api-remote-spec.js index 85a31af0a2b..69b45ac8aa7 100644 --- a/spec/api-remote-spec.js +++ b/spec/api-remote-spec.js @@ -237,6 +237,16 @@ describe('remote module', () => { const print = path.join(fixtures, 'module', 'print_name.js') const printName = remote.require(print) + it('converts NaN to undefined', () => { + assert.strictEqual(printName.getNaN(), undefined) + assert.strictEqual(printName.echo(NaN), undefined) + }) + + it('converts Infinity to undefined', () => { + assert.strictEqual(printName.getInfinity(), undefined) + assert.strictEqual(printName.echo(Infinity), undefined) + }) + it('keeps its constructor name for objects', () => { const buf = Buffer.from('test') assert.equal(printName.print(buf), 'Buffer') diff --git a/spec/fixtures/api/sandbox.html b/spec/fixtures/api/sandbox.html index 5353d8815a7..af796ebc988 100644 --- a/spec/fixtures/api/sandbox.html +++ b/spec/fixtures/api/sandbox.html @@ -98,10 +98,8 @@ popup.ipcRenderer.once('verified', () => { popup.ipcRenderer.send('child-answer') }) - setTimeout(() => { - ipcRenderer.send('parent-ready') - popup.ipcRenderer.send('child-ready') - }, 50) + ipcRenderer.send('parent-ready') + popup.ipcRenderer.send('child-ready') } } diff --git a/spec/fixtures/module/print_name.js b/spec/fixtures/module/print_name.js index 3985b88bf5f..8583af00f4a 100644 --- a/spec/fixtures/module/print_name.js +++ b/spec/fixtures/module/print_name.js @@ -26,3 +26,11 @@ exports.typedArray = function (type, values) { } return array } + +exports.getNaN = function () { + return NaN +} + +exports.getInfinity = function () { + return Infinity +}