diff --git a/.gitmodules b/.gitmodules index c6e53ed39a69..a3afcef28c84 100644 --- a/.gitmodules +++ b/.gitmodules @@ -12,7 +12,7 @@ url = https://github.com/atom/chromium-breakpad.git [submodule "vendor/native_mate"] path = vendor/native_mate - url = https://github.com/zcbenz/native-mate.git + url = https://github.com/brenca/native-mate.git [submodule "vendor/crashpad"] path = vendor/crashpad url = https://github.com/atom/crashpad.git diff --git a/atom/app/atom_main.cc b/atom/app/atom_main.cc index 47be348522f1..5677adb2eed3 100644 --- a/atom/app/atom_main.cc +++ b/atom/app/atom_main.cc @@ -90,9 +90,11 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) { if (env->GetVar("OS", &os) && os != "cygwin") { AttachConsole(ATTACH_PARENT_PROCESS); - FILE* dontcare; - freopen_s(&dontcare, "CON", "w", stdout); - freopen_s(&dontcare, "CON", "w", stderr); + FILE* dontcare, *out, *err; + out = fopen("out.txt", "w"); + err = fopen("err.txt", "w"); + freopen_s(&out, "CON", "w", stdout); + freopen_s(&err, "CON", "w", stderr); freopen_s(&dontcare, "CON", "r", stdin); } diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index e6d16fe6fa59..c19cf6f7d945 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -17,6 +17,7 @@ #include "native_mate/constructor.h" #include "native_mate/dictionary.h" #include "ui/gfx/geometry/rect.h" +#include "v8/include/v8.h" #if defined(OS_WIN) #include "atom/browser/native_window_views.h" @@ -92,6 +93,16 @@ void Window::WillCloseWindow(bool* prevent_default) { *prevent_default = Emit("close"); } +void Window::OnFrameRendered(scoped_ptr rgb, const int size) { + v8::Locker locker(isolate()); + v8::HandleScope handle_scope(isolate()); + + v8::Local data = v8::ArrayBuffer::New(isolate(), rgb.get(), size); + v8::Local uint_data = v8::Uint8ClampedArray::New(data, 0, size); + + Emit("frame-rendered", uint_data, size); +} + void Window::OnWindowClosed() { if (api_web_contents_) { api_web_contents_->DestroyWebContents(); diff --git a/atom/browser/api/atom_api_window.h b/atom/browser/api/atom_api_window.h index de2f093ea3e1..925aa6749714 100644 --- a/atom/browser/api/atom_api_window.h +++ b/atom/browser/api/atom_api_window.h @@ -53,6 +53,7 @@ class Window : public mate::TrackableObject, void OnPageTitleUpdated(bool* prevent_default, const std::string& title) override; void WillCloseWindow(bool* prevent_default) override; + void OnFrameRendered(scoped_ptr rgb, const int size) override; void OnWindowClosed() override; void OnWindowBlur() override; void OnWindowFocus() override; diff --git a/atom/browser/native_window.cc b/atom/browser/native_window.cc index 96085846bca8..b21d04aa2389 100644 --- a/atom/browser/native_window.cc +++ b/atom/browser/native_window.cc @@ -8,6 +8,9 @@ #include #include +#include "content/public/browser/render_widget_host_view_frame_subscriber.h" +#include "media/base/video_frame.h" +#include "media/base/yuv_convert.h" #include "atom/browser/atom_browser_context.h" #include "atom/browser/atom_browser_main_parts.h" #include "atom/browser/window_list.h" @@ -147,8 +150,9 @@ NativeWindow* NativeWindow::FromWebContents( content::WebContents* web_contents) { WindowList& window_list = *WindowList::GetInstance(); for (NativeWindow* window : window_list) { - if (window->web_contents() == web_contents) + if (window->web_contents() == web_contents){ return window; + } } return nullptr; } @@ -201,6 +205,9 @@ void NativeWindow::InitFromOptions(const mate::Dictionary& options) { options.Get(switches::kTitle, &title); SetTitle(title); + offscreen_ = false; + options.Get(switches::kOffScreenRender, &offscreen_); + // Then show it. bool show = true; options.Get(switches::kShow, &show); @@ -540,6 +547,18 @@ void NativeWindow::DevToolsClosed() { FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnDevToolsClosed()); } +void NativeWindow::RenderViewReady(){ + if(offscreen_){ + const auto view = web_contents()->GetRenderWidgetHostView(); + + scoped_ptr subscriber(new RenderSubscriber( + view->GetVisibleViewportSize(), base::Bind(&NativeWindow::OnFrameReceived, base::Unretained(this)) + )); + + view->BeginFrameSubscription(subscriber.Pass()); + } +} + void NativeWindow::RenderViewCreated( content::RenderViewHost* render_view_host) { if (!transparent_) @@ -617,4 +636,41 @@ void NativeWindow::OnCapturePageDone(const CapturePageCallback& callback, callback.Run(bitmap); } +void NativeWindow::OnFrameReceived(bool result, scoped_refptr frame) { + if(result){ + gfx::Rect rect = frame->visible_rect(); + + const int rgb_arr_size = rect.width()*rect.height()*4; + scoped_ptr rgb_bytes(new uint8[rgb_arr_size]); + + // 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), + rgb_bytes.get(), + rect.width(), rect.height(), + frame->stride(media::VideoFrame::kYPlane), + frame->stride(media::VideoFrame::kUVPlane), + rect.width()*4, + media::YV12); + + FOR_EACH_OBSERVER(NativeWindowObserver, + observers_, + OnFrameRendered(rgb_bytes.Pass(), rgb_arr_size)); + } +} + +bool RenderSubscriber::ShouldCaptureFrame(const gfx::Rect& damage_rect, + base::TimeTicks present_time, + scoped_refptr* storage, + DeliverFrameCallback* callback) { + last_present_time_ = present_time; + *storage = media::VideoFrame::CreateFrame(media::VideoFrame::YV12, size_, + gfx::Rect(size_), size_, + base::TimeDelta()); + + *callback = base::Bind(&RenderSubscriber::CallbackMethod, callback_, *storage); + return true; +} + } // namespace atom diff --git a/atom/browser/native_window.h b/atom/browser/native_window.h index b9294d38c931..793bd614c8d8 100644 --- a/atom/browser/native_window.h +++ b/atom/browser/native_window.h @@ -9,6 +9,8 @@ #include #include +#include "media/base/video_frame.h" +#include "content/public/browser/render_widget_host_view_frame_subscriber.h" #include "atom/browser/native_window_observer.h" #include "atom/browser/ui/accelerator_util.h" #include "base/cancelable_callback.h" @@ -232,6 +234,8 @@ class NativeWindow : public content::WebContentsObserver, has_dialog_attached_ = has_dialog_attached; } + void OnFrameReceived(bool result, scoped_refptr frame); + protected: NativeWindow(brightray::InspectableWebContents* inspectable_web_contents, const mate::Dictionary& options); @@ -243,6 +247,7 @@ class NativeWindow : public content::WebContentsObserver, // content::WebContentsObserver: void RenderViewCreated(content::RenderViewHost* render_view_host) override; + void RenderViewReady() override; void BeforeUnloadDialogCancelled() override; void TitleWasSet(content::NavigationEntry* entry, bool explicit_set) override; bool OnMessageReceived(const IPC::Message& message) override; @@ -263,6 +268,8 @@ class NativeWindow : public content::WebContentsObserver, const SkBitmap& bitmap, content::ReadbackResponse response); + bool offscreen_; + // Whether window has standard frame. bool has_frame_; @@ -317,6 +324,29 @@ class NativeWindow : public content::WebContentsObserver, DISALLOW_COPY_AND_ASSIGN(NativeWindow); }; +class RenderSubscriber : public content::RenderWidgetHostViewFrameSubscriber { + public: + RenderSubscriber(gfx::Size size, base::Callback)> callback) : size_(size), callback_(callback) {} + + bool ShouldCaptureFrame(const gfx::Rect& damage_rect, + base::TimeTicks present_time, + scoped_refptr* storage, + DeliverFrameCallback* callback) override; + + base::TimeTicks last_present_time() const { return last_present_time_; } + + static void CallbackMethod(base::Callback)> callback, + scoped_refptr frame, + base::TimeTicks present_time, + bool success) { + callback.Run(success, frame); + } + + private: + gfx::Size size_; + base::Callback)> callback_; + base::TimeTicks last_present_time_; +}; // This class provides a hook to get a NativeWindow from a WebContents. class NativeWindowRelay : diff --git a/atom/browser/native_window_observer.h b/atom/browser/native_window_observer.h index 5b0a0c56b3de..db6587de1f44 100644 --- a/atom/browser/native_window_observer.h +++ b/atom/browser/native_window_observer.h @@ -27,6 +27,8 @@ class NativeWindowObserver { const std::string& partition_id, WindowOpenDisposition disposition) {} + virtual void OnFrameRendered(scoped_ptr rgb, const int size) {} + // Called when user is starting an navigation in web page. virtual void WillNavigate(bool* prevent_default, const GURL& url) {} diff --git a/atom/common/options_switches.cc b/atom/common/options_switches.cc index 8f457116ec3a..73a54157fabd 100644 --- a/atom/common/options_switches.cc +++ b/atom/common/options_switches.cc @@ -110,6 +110,8 @@ const char kRegisterStandardSchemes[] = "register-standard-schemes"; // The browser process app model ID const char kAppUserModelId[] = "app-user-model-id"; +const char kOffScreenRender[] = "offscreen-render"; + } // namespace switches } // namespace atom diff --git a/atom/common/options_switches.h b/atom/common/options_switches.h index 2dd48ee32a1a..edd37ff03589 100644 --- a/atom/common/options_switches.h +++ b/atom/common/options_switches.h @@ -60,6 +60,8 @@ extern const char kRegisterStandardSchemes[]; extern const char kAppUserModelId[]; +extern const char kOffScreenRender[]; + } // namespace switches } // namespace atom diff --git a/vendor/native_mate b/vendor/native_mate index 67d9eaa215e8..31b6395d9938 160000 --- a/vendor/native_mate +++ b/vendor/native_mate @@ -1 +1 @@ -Subproject commit 67d9eaa215e8727d86dc7b1f7a10be8699848f1f +Subproject commit 31b6395d9938558ea39a77ef2f432beaf2dcd4cb