diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 516f6289ac0f..6ca3ea5d2f32 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -30,7 +30,7 @@ possible with your report. If you can, please include: * Follow the CoffeeScript, JavaScript, C++ and Python [coding style defined in docs](/docs/development/coding-style.md). * Write documentation in [Markdown](https://daringfireball.net/projects/markdown). See the [Documentation Styleguide](/docs/styleguide.md). -* Use short, present tense commit messages. See [Commit Message Styleguide](#git-commit-messages-styleguide). +* Use short, present tense commit messages. See [Commit Message Styleguide](#git-commit-messages). ## Styleguides diff --git a/atom.gyp b/atom.gyp index 63defa4273fd..c9d5f924789f 100644 --- a/atom.gyp +++ b/atom.gyp @@ -4,7 +4,7 @@ 'product_name%': 'Electron', 'company_name%': 'GitHub, Inc', 'company_abbr%': 'github', - 'version%': '0.32.3', + 'version%': '0.33.0', }, 'includes': [ 'filenames.gypi', diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index a24200e5a87d..9791a94bb77b 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -15,6 +15,7 @@ #include "atom/browser/web_view_guest_delegate.h" #include "atom/common/api/api_messages.h" #include "atom/common/api/event_emitter_caller.h" +#include "atom/common/native_mate_converters/blink_converter.h" #include "atom/common/native_mate_converters/callback.h" #include "atom/common/native_mate_converters/file_path_converter.h" #include "atom/common/native_mate_converters/gfx_converter.h" @@ -27,13 +28,16 @@ #include "brightray/browser/inspectable_web_contents.h" #include "chrome/browser/printing/print_view_manager_basic.h" #include "chrome/browser/printing/print_preview_message_handler.h" +#include "content/common/view_messages.h" #include "content/public/browser/favicon_status.h" +#include "content/public/browser/native_web_keyboard_event.h" #include "content/public/browser/navigation_details.h" #include "content/public/browser/navigation_entry.h" #include "content/public/browser/plugin_service.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/render_view_host.h" +#include "content/public/browser/render_widget_host_view.h" #include "content/public/browser/resource_request_details.h" #include "content/public/browser/service_worker_context.h" #include "content/public/browser/storage_partition.h" @@ -44,6 +48,7 @@ #include "net/http/http_response_headers.h" #include "net/url_request/static_http_user_agent_settings.h" #include "net/url_request/url_request_context.h" +#include "third_party/WebKit/public/web/WebInputEvent.h" #include "atom/common/node_includes.h" @@ -640,6 +645,21 @@ bool WebContents::IsDevToolsOpened() { return managed_web_contents()->IsDevToolsViewShowing(); } +void WebContents::EnableDeviceEmulation( + const blink::WebDeviceEmulationParams& params) { + if (type_ == REMOTE) + return; + + Send(new ViewMsg_EnableDeviceEmulation(routing_id(), params)); +} + +void WebContents::DisableDeviceEmulation() { + if (type_ == REMOTE) + return; + + Send(new ViewMsg_DisableDeviceEmulation(routing_id())); +} + void WebContents::ToggleDevTools() { if (IsDevToolsOpened()) CloseDevTools(); @@ -796,6 +816,56 @@ bool WebContents::SendIPCMessage(const base::string16& channel, return Send(new AtomViewMsg_Message(routing_id(), channel, args)); } +void WebContents::SendInputEvent(v8::Isolate* isolate, + v8::Local input_event) { + const auto view = web_contents()->GetRenderWidgetHostView(); + if (!view) + return; + const auto host = view->GetRenderWidgetHost(); + if (!host) + return; + + int type = mate::GetWebInputEventType(isolate, input_event); + if (blink::WebInputEvent::isMouseEventType(type)) { + blink::WebMouseEvent mouse_event; + if (mate::ConvertFromV8(isolate, input_event, &mouse_event)) { + host->ForwardMouseEvent(mouse_event); + return; + } + } else if (blink::WebInputEvent::isKeyboardEventType(type)) { + content::NativeWebKeyboardEvent keyboard_event;; + if (mate::ConvertFromV8(isolate, input_event, &keyboard_event)) { + host->ForwardKeyboardEvent(keyboard_event); + return; + } + } else if (type == blink::WebInputEvent::MouseWheel) { + blink::WebMouseWheelEvent mouse_wheel_event; + if (mate::ConvertFromV8(isolate, input_event, &mouse_wheel_event)) { + host->ForwardWheelEvent(mouse_wheel_event); + return; + } + } + + isolate->ThrowException(v8::Exception::Error(mate::StringToV8( + isolate, "Invalid event object"))); +} + +void WebContents::BeginFrameSubscription( + const FrameSubscriber::FrameCaptureCallback& callback) { + const auto view = web_contents()->GetRenderWidgetHostView(); + if (view) { + scoped_ptr frame_subscriber(new FrameSubscriber( + isolate(), view->GetVisibleViewportSize(), callback)); + view->BeginFrameSubscription(frame_subscriber.Pass()); + } +} + +void WebContents::EndFrameSubscription() { + const auto view = web_contents()->GetRenderWidgetHostView(); + if (view) + view->EndFrameSubscription(); +} + void WebContents::SetSize(const SetSizeParams& params) { if (guest_delegate_) guest_delegate_->SetSize(params); @@ -836,6 +906,10 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder( .SetMethod("openDevTools", &WebContents::OpenDevTools) .SetMethod("closeDevTools", &WebContents::CloseDevTools) .SetMethod("isDevToolsOpened", &WebContents::IsDevToolsOpened) + .SetMethod("enableDeviceEmulation", + &WebContents::EnableDeviceEmulation) + .SetMethod("disableDeviceEmulation", + &WebContents::DisableDeviceEmulation) .SetMethod("toggleDevTools", &WebContents::ToggleDevTools) .SetMethod("inspectElement", &WebContents::InspectElement) .SetMethod("setAudioMuted", &WebContents::SetAudioMuted) @@ -854,6 +928,10 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder( .SetMethod("focus", &WebContents::Focus) .SetMethod("tabTraverse", &WebContents::TabTraverse) .SetMethod("_send", &WebContents::SendIPCMessage, true) + .SetMethod("sendInputEvent", &WebContents::SendInputEvent) + .SetMethod("beginFrameSubscription", + &WebContents::BeginFrameSubscription) + .SetMethod("endFrameSubscription", &WebContents::EndFrameSubscription) .SetMethod("setSize", &WebContents::SetSize) .SetMethod("setAllowTransparency", &WebContents::SetAllowTransparency) .SetMethod("isGuest", &WebContents::IsGuest) diff --git a/atom/browser/api/atom_api_web_contents.h b/atom/browser/api/atom_api_web_contents.h index 0001d3e8ef75..c8ea6908bc5b 100644 --- a/atom/browser/api/atom_api_web_contents.h +++ b/atom/browser/api/atom_api_web_contents.h @@ -8,6 +8,7 @@ #include #include +#include "atom/browser/api/frame_subscriber.h" #include "atom/browser/api/trackable_object.h" #include "atom/browser/common_web_contents_delegate.h" #include "content/public/browser/web_contents_observer.h" @@ -15,6 +16,10 @@ #include "native_mate/handle.h" #include "ui/gfx/image/image.h" +namespace blink { +struct WebDeviceEmulationParams; +} + namespace brightray { class InspectableWebContents; } @@ -74,6 +79,8 @@ class WebContents : public mate::TrackableObject, void CloseDevTools(); bool IsDevToolsOpened(); void ToggleDevTools(); + void EnableDeviceEmulation(const blink::WebDeviceEmulationParams& params); + void DisableDeviceEmulation(); void InspectElement(int x, int y); void InspectServiceWorker(); v8::Local Session(v8::Isolate* isolate); @@ -108,10 +115,18 @@ class WebContents : public mate::TrackableObject, void Focus(); void TabTraverse(bool reverse); - // Sending messages to browser. + // Send messages to browser. bool SendIPCMessage(const base::string16& channel, const base::ListValue& args); + // Send WebInputEvent to the page. + void SendInputEvent(v8::Isolate* isolate, v8::Local input_event); + + // Subscribe to the frame updates. + void BeginFrameSubscription( + const FrameSubscriber::FrameCaptureCallback& callback); + void EndFrameSubscription(); + // Methods for creating . void SetSize(const SetSizeParams& params); void SetAllowTransparency(bool allow); diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index 1a76c3e5f078..3a44115da264 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -13,6 +13,7 @@ #include "atom/common/native_mate_converters/gurl_converter.h" #include "atom/common/native_mate_converters/image_converter.h" #include "atom/common/native_mate_converters/string16_converter.h" +#include "atom/common/node_includes.h" #include "atom/common/options_switches.h" #include "content/public/browser/render_process_host.h" #include "native_mate/constructor.h" @@ -24,8 +25,6 @@ #include "atom/browser/ui/win/taskbar_host.h" #endif -#include "atom/common/node_includes.h" - #if defined(OS_WIN) namespace mate { @@ -116,6 +115,9 @@ void Window::OnWindowClosed() { window_->RemoveObserver(this); Emit("closed"); + + // Clean up the resources after window has been closed. + base::MessageLoop::current()->DeleteSoon(FROM_HERE, window_.release()); } void Window::OnWindowBlur() { @@ -220,10 +222,8 @@ bool Window::IsDestroyed() const { } void Window::Destroy() { - if (window_) { + if (window_) window_->CloseContents(nullptr); - window_.reset(); - } } void Window::Close() { diff --git a/atom/browser/api/frame_subscriber.cc b/atom/browser/api/frame_subscriber.cc new file mode 100644 index 000000000000..526769f9cd6c --- /dev/null +++ b/atom/browser/api/frame_subscriber.cc @@ -0,0 +1,66 @@ +// Copyright (c) 2015 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "atom/browser/api/frame_subscriber.h" + +#include "atom/common/node_includes.h" +#include "base/bind.h" +#include "media/base/video_frame.h" +#include "media/base/yuv_convert.h" + +namespace atom { + +namespace api { + +FrameSubscriber::FrameSubscriber(v8::Isolate* isolate, + const gfx::Size& size, + const FrameCaptureCallback& callback) + : isolate_(isolate), size_(size), callback_(callback) { +} + +bool FrameSubscriber::ShouldCaptureFrame( + const gfx::Rect& damage_rect, + base::TimeTicks present_time, + scoped_refptr* storage, + DeliverFrameCallback* callback) { + *storage = media::VideoFrame::CreateFrame(media::VideoFrame::YV12, size_, + gfx::Rect(size_), size_, + base::TimeDelta()); + *callback = base::Bind(&FrameSubscriber::OnFrameDelivered, + base::Unretained(this), + *storage); + return true; +} + +void FrameSubscriber::OnFrameDelivered( + scoped_refptr frame, base::TimeTicks, bool result) { + if (!result) + return; + + gfx::Rect rect = frame->visible_rect(); + size_t rgb_arr_size = rect.width() * rect.height() * 4; + v8::MaybeLocal buffer = node::Buffer::New(isolate_, rgb_arr_size); + if (buffer.IsEmpty()) + return; + + // Convert a frame of YUV to 32 bit ARGB. + media::ConvertYUVToRGB32(frame->data(media::VideoFrame::kYPlane), + frame->data(media::VideoFrame::kUPlane), + frame->data(media::VideoFrame::kVPlane), + reinterpret_cast( + node::Buffer::Data(buffer.ToLocalChecked())), + rect.width(), rect.height(), + frame->stride(media::VideoFrame::kYPlane), + frame->stride(media::VideoFrame::kUVPlane), + rect.width() * 4, + media::YV12); + + v8::Locker locker(isolate_); + v8::HandleScope handle_scope(isolate_); + callback_.Run(buffer.ToLocalChecked()); +} + +} // namespace api + +} // namespace atom diff --git a/atom/browser/api/frame_subscriber.h b/atom/browser/api/frame_subscriber.h new file mode 100644 index 000000000000..f7748aa5790d --- /dev/null +++ b/atom/browser/api/frame_subscriber.h @@ -0,0 +1,45 @@ +// Copyright (c) 2015 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef ATOM_BROWSER_API_FRAME_SUBSCRIBER_H_ +#define ATOM_BROWSER_API_FRAME_SUBSCRIBER_H_ + +#include "base/callback.h" +#include "content/public/browser/render_widget_host_view_frame_subscriber.h" +#include "ui/gfx/geometry/size.h" +#include "v8/include/v8.h" + +namespace atom { + +namespace api { + +class FrameSubscriber : public content::RenderWidgetHostViewFrameSubscriber { + public: + using FrameCaptureCallback = base::Callback)>; + + FrameSubscriber(v8::Isolate* isolate, + const gfx::Size& size, + const FrameCaptureCallback& callback); + + bool ShouldCaptureFrame(const gfx::Rect& damage_rect, + base::TimeTicks present_time, + scoped_refptr* storage, + DeliverFrameCallback* callback) override; + + private: + void OnFrameDelivered( + scoped_refptr frame, base::TimeTicks, bool); + + v8::Isolate* isolate_; + gfx::Size size_; + FrameCaptureCallback callback_; + + DISALLOW_COPY_AND_ASSIGN(FrameSubscriber); +}; + +} // namespace api + +} // namespace atom + +#endif // ATOM_BROWSER_API_FRAME_SUBSCRIBER_H_ diff --git a/atom/browser/native_window.cc b/atom/browser/native_window.cc index f40f7de8dbc3..4d5f273340ab 100644 --- a/atom/browser/native_window.cc +++ b/atom/browser/native_window.cc @@ -39,10 +39,6 @@ #include "ui/gfx/screen.h" #include "ui/gl/gpu_switching_manager.h" -using content::NavigationEntry; -using content::RenderWidgetHostView; -using content::RenderWidgetHost; - DEFINE_WEB_CONTENTS_USER_DATA_KEY(atom::NativeWindowRelay); namespace atom { @@ -200,38 +196,6 @@ bool NativeWindow::IsDocumentEdited() { void NativeWindow::SetMenu(ui::MenuModel* menu) { } -void NativeWindow::ShowDefinitionForSelection() { - NOTIMPLEMENTED(); -} - -void NativeWindow::SetAutoHideMenuBar(bool auto_hide) { -} - -bool NativeWindow::IsMenuBarAutoHide() { - return false; -} - -void NativeWindow::SetMenuBarVisibility(bool visible) { -} - -bool NativeWindow::IsMenuBarVisible() { - return true; -} - -double NativeWindow::GetAspectRatio() { - return aspect_ratio_; -} - -gfx::Size NativeWindow::GetAspectRatioExtraSize() { - return aspect_ratio_extraSize_; -} - -void NativeWindow::SetAspectRatio(double aspect_ratio, - const gfx::Size& extra_size) { - aspect_ratio_ = aspect_ratio; - aspect_ratio_extraSize_ = extra_size; -} - bool NativeWindow::HasModalDialog() { return has_dialog_attached_; } @@ -286,6 +250,38 @@ void NativeWindow::CapturePage(const gfx::Rect& rect, kBGRA_8888_SkColorType); } +void NativeWindow::ShowDefinitionForSelection() { + NOTIMPLEMENTED(); +} + +void NativeWindow::SetAutoHideMenuBar(bool auto_hide) { +} + +bool NativeWindow::IsMenuBarAutoHide() { + return false; +} + +void NativeWindow::SetMenuBarVisibility(bool visible) { +} + +bool NativeWindow::IsMenuBarVisible() { + return true; +} + +double NativeWindow::GetAspectRatio() { + return aspect_ratio_; +} + +gfx::Size NativeWindow::GetAspectRatioExtraSize() { + return aspect_ratio_extraSize_; +} + +void NativeWindow::SetAspectRatio(double aspect_ratio, + const gfx::Size& extra_size) { + aspect_ratio_ = aspect_ratio; + aspect_ratio_extraSize_ = extra_size; +} + void NativeWindow::RequestToClosePage() { bool prevent_default = false; FOR_EACH_OBSERVER(NativeWindowObserver, diff --git a/atom/browser/native_window.h b/atom/browser/native_window.h index f09845aad348..e9a2b9433d13 100644 --- a/atom/browser/native_window.h +++ b/atom/browser/native_window.h @@ -296,7 +296,6 @@ class NativeWindow : public content::WebContentsObserver, DISALLOW_COPY_AND_ASSIGN(NativeWindow); }; - // This class provides a hook to get a NativeWindow from a WebContents. class NativeWindowRelay : public content::WebContentsUserData { diff --git a/atom/browser/resources/mac/Info.plist b/atom/browser/resources/mac/Info.plist index dd4e610d917e..54ba3546a75f 100644 --- a/atom/browser/resources/mac/Info.plist +++ b/atom/browser/resources/mac/Info.plist @@ -17,7 +17,7 @@ CFBundleIconFile atom.icns CFBundleVersion - 0.32.3 + 0.33.0 LSMinimumSystemVersion 10.8.0 NSMainNibFile diff --git a/atom/browser/resources/win/atom.rc b/atom/browser/resources/win/atom.rc index cf894f6b5c33..8863d8be7677 100644 --- a/atom/browser/resources/win/atom.rc +++ b/atom/browser/resources/win/atom.rc @@ -56,8 +56,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,32,3,0 - PRODUCTVERSION 0,32,3,0 + FILEVERSION 0,33,0,0 + PRODUCTVERSION 0,33,0,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -74,12 +74,12 @@ BEGIN BEGIN VALUE "CompanyName", "GitHub, Inc." VALUE "FileDescription", "Electron" - VALUE "FileVersion", "0.32.3" + VALUE "FileVersion", "0.33.0" VALUE "InternalName", "electron.exe" VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved." VALUE "OriginalFilename", "electron.exe" VALUE "ProductName", "Electron" - VALUE "ProductVersion", "0.32.3" + VALUE "ProductVersion", "0.33.0" VALUE "SquirrelAwareVersion", "1" END END diff --git a/atom/browser/ui/accelerator_util.cc b/atom/browser/ui/accelerator_util.cc index 41dde7acf732..e25e14b7968c 100644 --- a/atom/browser/ui/accelerator_util.cc +++ b/atom/browser/ui/accelerator_util.cc @@ -9,6 +9,7 @@ #include #include +#include "atom/common/keyboad_util.h" #include "base/stl_util.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" @@ -17,74 +18,6 @@ namespace accelerator_util { -namespace { - -// Return key code of the char. -ui::KeyboardCode KeyboardCodeFromCharCode(char c, bool* shifted) { - *shifted = false; - switch (c) { - case 8: case 0x7F: return ui::VKEY_BACK; - case 9: return ui::VKEY_TAB; - case 0xD: case 3: return ui::VKEY_RETURN; - case 0x1B: return ui::VKEY_ESCAPE; - case ' ': return ui::VKEY_SPACE; - - case 'a': return ui::VKEY_A; - case 'b': return ui::VKEY_B; - case 'c': return ui::VKEY_C; - case 'd': return ui::VKEY_D; - case 'e': return ui::VKEY_E; - case 'f': return ui::VKEY_F; - case 'g': return ui::VKEY_G; - case 'h': return ui::VKEY_H; - case 'i': return ui::VKEY_I; - case 'j': return ui::VKEY_J; - case 'k': return ui::VKEY_K; - case 'l': return ui::VKEY_L; - case 'm': return ui::VKEY_M; - case 'n': return ui::VKEY_N; - case 'o': return ui::VKEY_O; - case 'p': return ui::VKEY_P; - case 'q': return ui::VKEY_Q; - case 'r': return ui::VKEY_R; - case 's': return ui::VKEY_S; - case 't': return ui::VKEY_T; - case 'u': return ui::VKEY_U; - case 'v': return ui::VKEY_V; - case 'w': return ui::VKEY_W; - case 'x': return ui::VKEY_X; - case 'y': return ui::VKEY_Y; - case 'z': return ui::VKEY_Z; - - case ')': *shifted = true; case '0': return ui::VKEY_0; - case '!': *shifted = true; case '1': return ui::VKEY_1; - case '@': *shifted = true; case '2': return ui::VKEY_2; - case '#': *shifted = true; case '3': return ui::VKEY_3; - case '$': *shifted = true; case '4': return ui::VKEY_4; - case '%': *shifted = true; case '5': return ui::VKEY_5; - case '^': *shifted = true; case '6': return ui::VKEY_6; - case '&': *shifted = true; case '7': return ui::VKEY_7; - case '*': *shifted = true; case '8': return ui::VKEY_8; - case '(': *shifted = true; case '9': return ui::VKEY_9; - - case ':': *shifted = true; case ';': return ui::VKEY_OEM_1; - case '+': *shifted = true; case '=': return ui::VKEY_OEM_PLUS; - case '<': *shifted = true; case ',': return ui::VKEY_OEM_COMMA; - case '_': *shifted = true; case '-': return ui::VKEY_OEM_MINUS; - case '>': *shifted = true; case '.': return ui::VKEY_OEM_PERIOD; - case '?': *shifted = true; case '/': return ui::VKEY_OEM_2; - case '~': *shifted = true; case '`': return ui::VKEY_OEM_3; - case '{': *shifted = true; case '[': return ui::VKEY_OEM_4; - case '|': *shifted = true; case '\\': return ui::VKEY_OEM_5; - case '}': *shifted = true; case ']': return ui::VKEY_OEM_6; - case '"': *shifted = true; case '\'': return ui::VKEY_OEM_7; - - default: return ui::VKEY_UNKNOWN; - } -} - -} // namespace - bool StringToAccelerator(const std::string& description, ui::Accelerator* accelerator) { if (!base::IsStringASCII(description)) { @@ -104,7 +37,7 @@ bool StringToAccelerator(const std::string& description, // to be correct and usually only uses few special tokens. if (tokens[i].size() == 1) { bool shifted = false; - key = KeyboardCodeFromCharCode(tokens[i][0], &shifted); + key = atom::KeyboardCodeFromCharCode(tokens[i][0], &shifted); if (shifted) modifiers |= ui::EF_SHIFT_DOWN; } else if (tokens[i] == "ctrl" || tokens[i] == "control") { diff --git a/atom/common/atom_version.h b/atom/common/atom_version.h index 8d71e9150540..deb09585434e 100644 --- a/atom/common/atom_version.h +++ b/atom/common/atom_version.h @@ -6,8 +6,8 @@ #define ATOM_VERSION_H #define ATOM_MAJOR_VERSION 0 -#define ATOM_MINOR_VERSION 32 -#define ATOM_PATCH_VERSION 3 +#define ATOM_MINOR_VERSION 33 +#define ATOM_PATCH_VERSION 0 #define ATOM_VERSION_IS_RELEASE 1 diff --git a/atom/common/keyboad_util.cc b/atom/common/keyboad_util.cc new file mode 100644 index 000000000000..1baa829ff74a --- /dev/null +++ b/atom/common/keyboad_util.cc @@ -0,0 +1,73 @@ +// Copyright (c) 2015 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "atom/common/keyboad_util.h" + +namespace atom { + +// Return key code of the char. +ui::KeyboardCode KeyboardCodeFromCharCode(char c, bool* shifted) { + *shifted = false; + switch (c) { + case 8: case 0x7F: return ui::VKEY_BACK; + case 9: return ui::VKEY_TAB; + case 0xD: case 3: return ui::VKEY_RETURN; + case 0x1B: return ui::VKEY_ESCAPE; + case ' ': return ui::VKEY_SPACE; + + case 'a': return ui::VKEY_A; + case 'b': return ui::VKEY_B; + case 'c': return ui::VKEY_C; + case 'd': return ui::VKEY_D; + case 'e': return ui::VKEY_E; + case 'f': return ui::VKEY_F; + case 'g': return ui::VKEY_G; + case 'h': return ui::VKEY_H; + case 'i': return ui::VKEY_I; + case 'j': return ui::VKEY_J; + case 'k': return ui::VKEY_K; + case 'l': return ui::VKEY_L; + case 'm': return ui::VKEY_M; + case 'n': return ui::VKEY_N; + case 'o': return ui::VKEY_O; + case 'p': return ui::VKEY_P; + case 'q': return ui::VKEY_Q; + case 'r': return ui::VKEY_R; + case 's': return ui::VKEY_S; + case 't': return ui::VKEY_T; + case 'u': return ui::VKEY_U; + case 'v': return ui::VKEY_V; + case 'w': return ui::VKEY_W; + case 'x': return ui::VKEY_X; + case 'y': return ui::VKEY_Y; + case 'z': return ui::VKEY_Z; + + case ')': *shifted = true; case '0': return ui::VKEY_0; + case '!': *shifted = true; case '1': return ui::VKEY_1; + case '@': *shifted = true; case '2': return ui::VKEY_2; + case '#': *shifted = true; case '3': return ui::VKEY_3; + case '$': *shifted = true; case '4': return ui::VKEY_4; + case '%': *shifted = true; case '5': return ui::VKEY_5; + case '^': *shifted = true; case '6': return ui::VKEY_6; + case '&': *shifted = true; case '7': return ui::VKEY_7; + case '*': *shifted = true; case '8': return ui::VKEY_8; + case '(': *shifted = true; case '9': return ui::VKEY_9; + + case ':': *shifted = true; case ';': return ui::VKEY_OEM_1; + case '+': *shifted = true; case '=': return ui::VKEY_OEM_PLUS; + case '<': *shifted = true; case ',': return ui::VKEY_OEM_COMMA; + case '_': *shifted = true; case '-': return ui::VKEY_OEM_MINUS; + case '>': *shifted = true; case '.': return ui::VKEY_OEM_PERIOD; + case '?': *shifted = true; case '/': return ui::VKEY_OEM_2; + case '~': *shifted = true; case '`': return ui::VKEY_OEM_3; + case '{': *shifted = true; case '[': return ui::VKEY_OEM_4; + case '|': *shifted = true; case '\\': return ui::VKEY_OEM_5; + case '}': *shifted = true; case ']': return ui::VKEY_OEM_6; + case '"': *shifted = true; case '\'': return ui::VKEY_OEM_7; + + default: return ui::VKEY_UNKNOWN; + } +} + +} // namespace atom diff --git a/atom/common/keyboad_util.h b/atom/common/keyboad_util.h new file mode 100644 index 000000000000..0496886e40bd --- /dev/null +++ b/atom/common/keyboad_util.h @@ -0,0 +1,18 @@ +// Copyright (c) 2015 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef ATOM_COMMON_KEYBOAD_UTIL_H_ +#define ATOM_COMMON_KEYBOAD_UTIL_H_ + +#include "ui/events/keycodes/keyboard_codes.h" + +namespace atom { + +// Return key code of the char, and also determine whether the SHIFT key is +// pressed. +ui::KeyboardCode KeyboardCodeFromCharCode(char c, bool* shifted); + +} // namespace atom + +#endif // ATOM_COMMON_KEYBOAD_UTIL_H_ diff --git a/atom/common/native_mate_converters/blink_converter.cc b/atom/common/native_mate_converters/blink_converter.cc new file mode 100644 index 000000000000..67c7e7e95fd8 --- /dev/null +++ b/atom/common/native_mate_converters/blink_converter.cc @@ -0,0 +1,258 @@ +// Copyright (c) 2015 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "atom/common/native_mate_converters/blink_converter.h" + +#include +#include + +#include "atom/common/keyboad_util.h" +#include "base/strings/string_util.h" +#include "content/public/browser/native_web_keyboard_event.h" +#include "native_mate/dictionary.h" +#include "third_party/WebKit/public/web/WebDeviceEmulationParams.h" +#include "third_party/WebKit/public/web/WebInputEvent.h" + +namespace { + +template +int VectorToBitArray(const std::vector& vec) { + int bits = 0; + for (const T& item : vec) + bits |= item; + return bits; +} + +} // namespace + +namespace mate { + +template<> +struct Converter { + static bool FromV8(v8::Isolate* isolate, v8::Handle val, + char* out) { + std::string code = base::StringToLowerASCII(V8ToString(val)); + if (code.length() != 1) + return false; + *out = code[0]; + return true; + } +}; + +template<> +struct Converter { + static bool FromV8(v8::Isolate* isolate, v8::Handle val, + blink::WebInputEvent::Type* out) { + std::string type = base::StringToLowerASCII(V8ToString(val)); + if (type == "mousedown") + *out = blink::WebInputEvent::MouseDown; + else if (type == "mouseup") + *out = blink::WebInputEvent::MouseUp; + else if (type == "mousemove") + *out = blink::WebInputEvent::MouseMove; + else if (type == "mouseenter") + *out = blink::WebInputEvent::MouseEnter; + else if (type == "mouseleave") + *out = blink::WebInputEvent::MouseLeave; + else if (type == "contextmenu") + *out = blink::WebInputEvent::ContextMenu; + else if (type == "mousewheel") + *out = blink::WebInputEvent::MouseWheel; + else if (type == "keydown") + *out = blink::WebInputEvent::KeyDown; + else if (type == "keyup") + *out = blink::WebInputEvent::KeyUp; + else if (type == "char") + *out = blink::WebInputEvent::Char; + else if (type == "touchstart") + *out = blink::WebInputEvent::TouchStart; + else if (type == "touchmove") + *out = blink::WebInputEvent::TouchMove; + else if (type == "touchend") + *out = blink::WebInputEvent::TouchEnd; + else if (type == "touchcancel") + *out = blink::WebInputEvent::TouchCancel; + return true; + } +}; + +template<> +struct Converter { + static bool FromV8(v8::Isolate* isolate, v8::Handle val, + blink::WebInputEvent::Modifiers* out) { + std::string modifier = base::StringToLowerASCII(V8ToString(val)); + if (modifier == "shift") + *out = blink::WebInputEvent::ShiftKey; + else if (modifier == "control" || modifier == "ctrl") + *out = blink::WebInputEvent::ControlKey; + else if (modifier == "alt") + *out = blink::WebInputEvent::AltKey; + else if (modifier == "meta" || modifier == "command" || modifier == "cmd") + *out = blink::WebInputEvent::MetaKey; + else if (modifier == "iskeypad") + *out = blink::WebInputEvent::IsKeyPad; + else if (modifier == "isautorepeat") + *out = blink::WebInputEvent::IsAutoRepeat; + else if (modifier == "leftbuttondown") + *out = blink::WebInputEvent::LeftButtonDown; + else if (modifier == "middlebuttondown") + *out = blink::WebInputEvent::MiddleButtonDown; + else if (modifier == "rightbuttondown") + *out = blink::WebInputEvent::RightButtonDown; + else if (modifier == "capslock") + *out = blink::WebInputEvent::CapsLockOn; + else if (modifier == "numlock") + *out = blink::WebInputEvent::NumLockOn; + else if (modifier == "left") + *out = blink::WebInputEvent::IsLeft; + else if (modifier == "right") + *out = blink::WebInputEvent::IsRight; + return true; + } +}; + +int GetWebInputEventType(v8::Isolate* isolate, v8::Local val) { + blink::WebInputEvent::Type type = blink::WebInputEvent::Undefined; + mate::Dictionary dict; + ConvertFromV8(isolate, val, &dict) && dict.Get("type", &type); + return type; +} + +bool Converter::FromV8( + v8::Isolate* isolate, v8::Local val, + blink::WebInputEvent* out) { + mate::Dictionary dict; + if (!ConvertFromV8(isolate, val, &dict)) + return false; + if (!dict.Get("type", &out->type)) + return false; + std::vector modifiers; + if (dict.Get("modifiers", &modifiers)) + out->modifiers = VectorToBitArray(modifiers); + out->timeStampSeconds = base::Time::Now().ToDoubleT(); + return true; +} + +bool Converter::FromV8( + v8::Isolate* isolate, v8::Local val, + blink::WebKeyboardEvent* out) { + mate::Dictionary dict; + if (!ConvertFromV8(isolate, val, &dict)) + return false; + if (!ConvertFromV8(isolate, val, static_cast(out))) + return false; + char code; + if (!dict.Get("keyCode", &code)) + return false; + bool shifted = false; + out->windowsKeyCode = atom::KeyboardCodeFromCharCode(code, &shifted); + if (out->windowsKeyCode == ui::VKEY_UNKNOWN) + return false; + if (shifted) + out->modifiers |= blink::WebInputEvent::ShiftKey; + out->setKeyIdentifierFromWindowsKeyCode(); + return true; +} + +bool Converter::FromV8( + v8::Isolate* isolate, v8::Local val, + content::NativeWebKeyboardEvent* out) { + mate::Dictionary dict; + if (!ConvertFromV8(isolate, val, &dict)) + return false; + if (!ConvertFromV8(isolate, val, static_cast(out))) + return false; + dict.Get("skipInBrowser", &out->skip_in_browser); + return true; +} + +bool Converter::FromV8( + v8::Isolate* isolate, v8::Local val, blink::WebMouseEvent* out) { + mate::Dictionary dict; + if (!ConvertFromV8(isolate, val, &dict)) + return false; + if (!ConvertFromV8(isolate, val, static_cast(out))) + return false; + if (!dict.Get("x", &out->x) || !dict.Get("y", &out->y)) + return false; + dict.Get("globalX", &out->globalX); + dict.Get("globalY", &out->globalY); + dict.Get("movementX", &out->movementX); + dict.Get("movementY", &out->movementY); + dict.Get("clickCount", &out->clickCount); + return true; +} + +bool Converter::FromV8( + v8::Isolate* isolate, v8::Local val, + blink::WebMouseWheelEvent* out) { + mate::Dictionary dict; + if (!ConvertFromV8(isolate, val, &dict)) + return false; + if (!ConvertFromV8(isolate, val, static_cast(out))) + return false; + dict.Get("deltaX", &out->deltaX); + dict.Get("deltaY", &out->deltaY); + dict.Get("wheelTicksX", &out->wheelTicksX); + dict.Get("wheelTicksY", &out->wheelTicksY); + dict.Get("accelerationRatioX", &out->accelerationRatioX); + dict.Get("accelerationRatioY", &out->accelerationRatioY); + dict.Get("hasPreciseScrollingDeltas", &out->hasPreciseScrollingDeltas); + dict.Get("canScroll", &out->canScroll); + return true; +} + +bool Converter::FromV8( + v8::Isolate* isolate, v8::Local val, blink::WebFloatPoint* out) { + mate::Dictionary dict; + if (!ConvertFromV8(isolate, val, &dict)) + return false; + return dict.Get("x", &out->x) && dict.Get("y", &out->y); +} + +bool Converter::FromV8( + v8::Isolate* isolate, v8::Local val, blink::WebPoint* out) { + mate::Dictionary dict; + if (!ConvertFromV8(isolate, val, &dict)) + return false; + return dict.Get("x", &out->x) && dict.Get("y", &out->y); +} + +bool Converter::FromV8( + v8::Isolate* isolate, v8::Local val, blink::WebSize* out) { + mate::Dictionary dict; + if (!ConvertFromV8(isolate, val, &dict)) + return false; + return dict.Get("width", &out->width) && dict.Get("height", &out->height); +} + +bool Converter::FromV8( + v8::Isolate* isolate, v8::Local val, + blink::WebDeviceEmulationParams* out) { + mate::Dictionary dict; + if (!ConvertFromV8(isolate, val, &dict)) + return false; + + std::string screen_position; + if (dict.Get("screenPosition", &screen_position)) { + screen_position = base::StringToLowerASCII(screen_position); + if (screen_position == "mobile") + out->screenPosition = blink::WebDeviceEmulationParams::Mobile; + else if (screen_position == "desktop") + out->screenPosition = blink::WebDeviceEmulationParams::Desktop; + else + return false; + } + + dict.Get("screenSize", &out->screenSize); + dict.Get("viewPosition", &out->viewPosition); + dict.Get("deviceScaleFactor", &out->deviceScaleFactor); + dict.Get("viewSize", &out->viewSize); + dict.Get("fitToView", &out->fitToView); + dict.Get("offset", &out->offset); + dict.Get("scale", &out->scale); + return true; +} + +} // namespace mate diff --git a/atom/common/native_mate_converters/blink_converter.h b/atom/common/native_mate_converters/blink_converter.h new file mode 100644 index 000000000000..17bb108d349e --- /dev/null +++ b/atom/common/native_mate_converters/blink_converter.h @@ -0,0 +1,85 @@ +// Copyright (c) 2015 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef ATOM_COMMON_NATIVE_MATE_CONVERTERS_BLINK_CONVERTER_H_ +#define ATOM_COMMON_NATIVE_MATE_CONVERTERS_BLINK_CONVERTER_H_ + +#include "native_mate/converter.h" + +namespace blink { +class WebInputEvent; +class WebMouseEvent; +class WebMouseWheelEvent; +class WebKeyboardEvent; +struct WebDeviceEmulationParams; +struct WebFloatPoint; +struct WebPoint; +struct WebSize; +} + +namespace content { +struct NativeWebKeyboardEvent; +} + +namespace mate { + +int GetWebInputEventType(v8::Isolate* isolate, v8::Local val); + +template<> +struct Converter { + static bool FromV8(v8::Isolate* isolate, v8::Local val, + blink::WebInputEvent* out); +}; + +template<> +struct Converter { + static bool FromV8(v8::Isolate* isolate, v8::Local val, + blink::WebKeyboardEvent* out); +}; + +template<> +struct Converter { + static bool FromV8(v8::Isolate* isolate, v8::Local val, + content::NativeWebKeyboardEvent* out); +}; + +template<> +struct Converter { + static bool FromV8(v8::Isolate* isolate, v8::Local val, + blink::WebMouseEvent* out); +}; + +template<> +struct Converter { + static bool FromV8(v8::Isolate* isolate, v8::Local val, + blink::WebMouseWheelEvent* out); +}; + +template<> +struct Converter { + static bool FromV8(v8::Isolate* isolate, v8::Local val, + blink::WebFloatPoint* out); +}; + +template<> +struct Converter { + static bool FromV8(v8::Isolate* isolate, v8::Local val, + blink::WebPoint* out); +}; + +template<> +struct Converter { + static bool FromV8(v8::Isolate* isolate, v8::Local val, + blink::WebSize* out); +}; + +template<> +struct Converter { + static bool FromV8(v8::Isolate* isolate, v8::Local val, + blink::WebDeviceEmulationParams* out); +}; + +} // namespace mate + +#endif // ATOM_COMMON_NATIVE_MATE_CONVERTERS_BLINK_CONVERTER_H_ diff --git a/atom/renderer/lib/web-view/web-view.coffee b/atom/renderer/lib/web-view/web-view.coffee index f5bcf0496f8c..65e4501975fe 100644 --- a/atom/renderer/lib/web-view/web-view.coffee +++ b/atom/renderer/lib/web-view/web-view.coffee @@ -292,6 +292,7 @@ registerWebViewElement = -> "inspectServiceWorker" "print" "printToPDF" + "sendInputEvent" ] # Forward proto.foo* method calls to WebViewImpl.foo*. diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index 29171a2ec504..f1705c291756 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -244,7 +244,7 @@ Emitted when DevTools is closed. Emitted when DevTools is focused / opened. -### Event: 'app-command' _Windows_ +### Event: 'app-command': Emitted when an [App Command](https://msdn.microsoft.com/en-us/library/windows/desktop/ms646275(v=vs.85).aspx) is invoked. These are typically related to keyboard media keys or browser diff --git a/docs/api/remote.md b/docs/api/remote.md index 1c5c831a1790..55893c65f1c4 100644 --- a/docs/api/remote.md +++ b/docs/api/remote.md @@ -79,7 +79,7 @@ exports.withLocalCallback = function() { ```javascript // renderer process -var mapNumbers = require("remote").require("mapNumbers"); +var mapNumbers = require("remote").require("./mapNumbers"); var withRendererCb = mapNumbers.withRendererCallback(function(x) { return x + 1; diff --git a/docs/api/web-contents.md b/docs/api/web-contents.md index 92d91d170e4a..e8f72cd24bf2 100644 --- a/docs/api/web-contents.md +++ b/docs/api/web-contents.md @@ -476,3 +476,92 @@ app.on('ready', function() { which is different from the handlers in the main process. 2. There is no way to send synchronous messages from the main process to a renderer process, because it would be very easy to cause dead locks. + +### `webContents.enableDeviceEmulation(parameters)` + +`parameters` Object, properties: + +* `screenPosition` String - Specify the screen type to emulate + (default: `desktop`) + * `desktop` + * `mobile` +* `screenSize` Object - Set the emulated screen size (screenPosition == mobile) + * `width` Integer - Set the emulated screen width + * `height` Integer - Set the emulated screen height +* `viewPosition` Object - Position the view on the screen + (screenPosition == mobile) (default: `{x: 0, y: 0}`) + * `x` Integer - Set the x axis offset from top left corner + * `y` Integer - Set the y axis offset from top left corner +* `deviceScaleFactor` Integer - Set the device scale factor (if zero defaults to + original device scale factor) (default: `0`) +* `viewSize` Object - Set the emulated view size (empty means no override) + * `width` Integer - Set the emulated view width + * `height` Integer - Set the emulated view height +* `fitToView` Boolean - Whether emulated view should be scaled down if + necessary to fit into available space (default: `false`) +* `offset` Object - Offset of the emulated view inside available space (not in + fit to view mode) (default: `{x: 0, y: 0}`) + * `x` Float - Set the x axis offset from top left corner + * `y` Float - Set the y axis offset from top left corner +* `scale` Float - Scale of emulated view inside available space (not in fit to + view mode) (default: `1`) + +Enable device emulation with the given parameters. + +### `webContents.disableDeviceEmulation()` + +Disable device emulation enabled by `webContents.enableDeviceEmulation`. + +### `webContents.sendInputEvent(event)` + +* `event` Object + * `type` String (**required**) - The type of the event, can be `mouseDown`, + `mouseUp`, `mouseEnter`, `mouseLeave`, `contextMenu`, `mouseWheel`, + `keyDown`, `keyUp`, `char`. + * `modifiers` Array - An array of modifiers of the event, can + include `shift`, `control`, `alt`, `meta`, `isKeypad`, `isAutoRepeat`, + `leftButtonDown`, `middleButtonDown`, `rightButtonDown`, `capsLock`, + `numLock`, `left`, `right`. + +Sends an input `event` to the page. + +For keyboard events, the `event` object also have following properties: + +* `keyCode` String (**required**) - A single character that will be sent as + keyboard event. Can be any ASCII character on the keyboard, like `a`, `1` + and `=`. + +For mouse events, the `event` object also have following properties: + +* `x` Integer (**required**) +* `y` Integer (**required**) +* `globalX` Integer +* `globalY` Integer +* `movementX` Integer +* `movementY` Integer +* `clickCount` Integer + +For the `mouseWheel` event, the `event` object also have following properties: + +* `deltaX` Integer +* `deltaY` Integer +* `wheelTicksX` Integer +* `wheelTicksY` Integer +* `accelerationRatioX` Integer +* `accelerationRatioY` Integer +* `hasPreciseScrollingDeltas` Boolean +* `canScroll` Boolean + +### `webContents.beginFrameSubscription(callback)` + +* `callback` Function + +Begin subscribing for presentation events and captured frames, the `callback` +will be called with `callback(frameBuffer)` when there is a presentation event. + +The `frameBuffer` is a `Buffer` that contains raw pixel data, in the format of +32bit ARGB. + +### `webContents.endFrameSubscription()` + +End subscribing for frame presentation events. diff --git a/docs/api/web-view-tag.md b/docs/api/web-view-tag.md index 4647413b5a43..8eb3857ac970 100644 --- a/docs/api/web-view-tag.md +++ b/docs/api/web-view-tag.md @@ -358,6 +358,15 @@ page can handle it by listening to the `channel` event of `ipc` module. See [WebContents.send](web-contents.md#webcontentssendchannel-args) for examples. +### `.sendInputEvent(event)` + +* `event` Object + +Sends an input `event` to the page. + +See [WebContents.sendInputEvent](web-contents.md##webcontentssendinputeventevent) +for detailed description of `event` object. + ## DOM events The following DOM events are available to the `webview` tag: diff --git a/filenames.gypi b/filenames.gypi index 461c812753c9..99d6bc6d50d3 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -103,6 +103,8 @@ 'atom/browser/api/event_emitter.h', 'atom/browser/api/trackable_object.cc', 'atom/browser/api/trackable_object.h', + 'atom/browser/api/frame_subscriber.cc', + 'atom/browser/api/frame_subscriber.h', 'atom/browser/auto_updater.cc', 'atom/browser/auto_updater.h', 'atom/browser/auto_updater_delegate.h', @@ -283,9 +285,13 @@ 'atom/common/google_api_key.h', 'atom/common/id_weak_map.cc', 'atom/common/id_weak_map.h', + 'atom/common/keyboad_util.cc', + 'atom/common/keyboad_util.h', 'atom/common/linux/application_info.cc', 'atom/common/native_mate_converters/accelerator_converter.cc', 'atom/common/native_mate_converters/accelerator_converter.h', + 'atom/common/native_mate_converters/blink_converter.cc', + 'atom/common/native_mate_converters/blink_converter.h', 'atom/common/native_mate_converters/callback.h', 'atom/common/native_mate_converters/file_path_converter.h', 'atom/common/native_mate_converters/gfx_converter.cc', diff --git a/spec/api-browser-window-spec.coffee b/spec/api-browser-window-spec.coffee index 3e4e2d5db5e2..bb4d782e7ffb 100644 --- a/spec/api-browser-window-spec.coffee +++ b/spec/api-browser-window-spec.coffee @@ -295,11 +295,19 @@ describe 'browser-window module', -> w.minimize() describe 'will-navigate event', -> - return if isCI and process.platform is 'darwin' + @timeout 10000 it 'emits when user starts a navigation', (done) -> - @timeout 10000 - w.webContents.on 'will-navigate', (event, url) -> + url = "file://#{fixtures}/pages/will-navigate.html" + w.webContents.on 'will-navigate', (event, u) -> event.preventDefault() - assert.equal url, 'https://www.github.com/' + assert.equal u, url + done() + w.loadUrl url + + describe 'beginFrameSubscription method', -> + it 'subscribes frame updates', (done) -> + w.loadUrl "file://#{fixtures}/api/blank.html" + w.webContents.beginFrameSubscription (data) -> + assert.notEqual data.length, 0 + w.webContents.endFrameSubscription() done() - w.loadUrl "file://#{fixtures}/pages/will-navigate.html" diff --git a/spec/fixtures/module/set-immediate.js b/spec/fixtures/module/set-immediate.js new file mode 100644 index 000000000000..e7d44a75d1fe --- /dev/null +++ b/spec/fixtures/module/set-immediate.js @@ -0,0 +1,11 @@ +process.on('uncaughtException', function(error) { + process.send(error.message); + process.exit(1); +}); + +process.on('message', function(msg) { + setImmediate(function() { + process.send('ok'); + process.exit(0); + }); +}); diff --git a/spec/fixtures/pages/onkeyup.html b/spec/fixtures/pages/onkeyup.html new file mode 100644 index 000000000000..99e6c3e98382 --- /dev/null +++ b/spec/fixtures/pages/onkeyup.html @@ -0,0 +1,9 @@ + + + + + diff --git a/spec/fixtures/pages/onmouseup.html b/spec/fixtures/pages/onmouseup.html new file mode 100644 index 000000000000..1fd38bc7211f --- /dev/null +++ b/spec/fixtures/pages/onmouseup.html @@ -0,0 +1,9 @@ + + + + + diff --git a/spec/fixtures/pages/will-navigate.html b/spec/fixtures/pages/will-navigate.html index bd2ebdc1cb43..8d0c9b779e2d 100644 --- a/spec/fixtures/pages/will-navigate.html +++ b/spec/fixtures/pages/will-navigate.html @@ -1,7 +1,7 @@ diff --git a/spec/node-spec.coffee b/spec/node-spec.coffee index 94174c38b743..c8d569e01ada 100644 --- a/spec/node-spec.coffee +++ b/spec/node-spec.coffee @@ -56,6 +56,13 @@ describe 'node feature', -> done() child.send 'message' + it 'has setImmediate working in script', (done) -> + child = child_process.fork path.join(fixtures, 'module', 'set-immediate.js') + child.on 'message', (msg) -> + assert.equal msg, 'ok' + done() + child.send 'message' + describe 'contexts', -> describe 'setTimeout in fs callback', -> it 'does not crash', (done) -> @@ -141,3 +148,7 @@ describe 'node feature', -> # Not reliable on some machines xit 'should have isTTY defined', -> assert.equal typeof(process.stdout.isTTY), 'boolean' + + describe 'vm.createContext', -> + it 'should not crash', -> + require('vm').runInNewContext('') diff --git a/spec/webview-spec.coffee b/spec/webview-spec.coffee index e4b40c28ebeb..b310b7b129f8 100644 --- a/spec/webview-spec.coffee +++ b/spec/webview-spec.coffee @@ -336,3 +336,26 @@ describe ' tag', -> webview.addEventListener 'did-finish-load', listener2 webview.src = "file://#{fixtures}/pages/fullscreen.html" document.body.appendChild webview + + describe 'sendInputEvent', -> + it 'can send keyboard event', (done) -> + webview.addEventListener 'ipc-message', (e) -> + assert.equal e.channel, 'keyup' + assert.deepEqual e.args, [67, true, false] + done() + webview.addEventListener 'dom-ready', -> + webview.sendInputEvent type: 'keyup', keyCode: 'c', modifiers: ['shift'] + webview.src = "file://#{fixtures}/pages/onkeyup.html" + webview.setAttribute 'nodeintegration', 'on' + document.body.appendChild webview + + it 'can send mouse event', (done) -> + webview.addEventListener 'ipc-message', (e) -> + assert.equal e.channel, 'mouseup' + assert.deepEqual e.args, [10, 20, false, true] + done() + webview.addEventListener 'dom-ready', -> + webview.sendInputEvent type: 'mouseup', modifiers: ['ctrl'], x: 10, y: 20 + webview.src = "file://#{fixtures}/pages/onmouseup.html" + webview.setAttribute 'nodeintegration', 'on' + document.body.appendChild webview diff --git a/vendor/brightray b/vendor/brightray index d385c9b1b88d..25f3a9d0a5b7 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit d385c9b1b88da3ba1b5426861ec7c63e8c884135 +Subproject commit 25f3a9d0a5b73ec170a65f4e2e4c9ad91e23fc8c diff --git a/vendor/node b/vendor/node index 4098d45fbb82..aa9c7a2316ba 160000 --- a/vendor/node +++ b/vendor/node @@ -1 +1 @@ -Subproject commit 4098d45fbb822370c19d2fe7b88162759db4eb96 +Subproject commit aa9c7a2316ba7762f1d04d091585695be3e6be22