diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index 99cb2e007482..2b1d03dbd27f 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -65,6 +65,7 @@ #include "net/url_request/url_request_context.h" #include "third_party/WebKit/public/web/WebInputEvent.h" #include "third_party/WebKit/public/web/WebFindOptions.h" +#include "ui/gfx/screen.h" #include "atom/common/node_includes.h" @@ -238,6 +239,13 @@ content::ServiceWorkerContext* GetServiceWorkerContext( return storage_partition->GetServiceWorkerContext(); } +// Called when CapturePage is done. +void OnCapturePageDone(base::Callback callback, + const SkBitmap& bitmap, + content::ReadbackResponse response) { + callback.Run(gfx::Image::CreateFrom1xBitmap(bitmap)); +} + } // namespace WebContents::WebContents(v8::Isolate* isolate, @@ -1235,6 +1243,45 @@ void WebContents::StartDrag(const mate::Dictionary& item, } } +void WebContents::CapturePage(mate::Arguments* args) { + gfx::Rect rect; + base::Callback callback; + + if (!(args->Length() == 1 && args->GetNext(&callback)) && + !(args->Length() == 2 && args->GetNext(&rect) + && args->GetNext(&callback))) { + args->ThrowError(); + return; + } + + const auto view = web_contents()->GetRenderWidgetHostView(); + const auto host = view ? view->GetRenderWidgetHost() : nullptr; + if (!view || !host) { + callback.Run(gfx::Image()); + return; + } + + // Capture full page if user doesn't specify a |rect|. + const gfx::Size view_size = rect.IsEmpty() ? view->GetViewBounds().size() : + rect.size(); + + // By default, the requested bitmap size is the view size in screen + // coordinates. However, if there's more pixel detail available on the + // current system, increase the requested bitmap size to capture it all. + gfx::Size bitmap_size = view_size; + const gfx::NativeView native_view = view->GetNativeView(); + const float scale = + gfx::Screen::GetScreen()->GetDisplayNearestWindow(native_view) + .device_scale_factor(); + if (scale > 1.0f) + bitmap_size = gfx::ScaleToCeiledSize(view_size, scale); + + host->CopyFromBackingStore(gfx::Rect(rect.origin(), view_size), + bitmap_size, + base::Bind(&OnCapturePageDone, callback), + kBGRA_8888_SkColorType); +} + void WebContents::OnCursorChange(const content::WebCursor& cursor) { content::WebCursor::CursorInfo info; cursor.GetCursorInfo(&info); @@ -1370,6 +1417,7 @@ void WebContents::BuildPrototype(v8::Isolate* isolate, .SetMethod("removeWorkSpace", &WebContents::RemoveWorkSpace) .SetMethod("showDefinitionForSelection", &WebContents::ShowDefinitionForSelection) + .SetMethod("capturePage", &WebContents::CapturePage) .SetProperty("id", &WebContents::ID) .SetProperty("session", &WebContents::Session) .SetProperty("hostWebContents", &WebContents::HostWebContents) diff --git a/atom/browser/api/atom_api_web_contents.h b/atom/browser/api/atom_api_web_contents.h index 2917aa860a81..389550390beb 100644 --- a/atom/browser/api/atom_api_web_contents.h +++ b/atom/browser/api/atom_api_web_contents.h @@ -145,6 +145,10 @@ class WebContents : public mate::TrackableObject, // Dragging native items. void StartDrag(const mate::Dictionary& item, mate::Arguments* args); + // Captures the page with |rect|, |callback| would be called when capturing is + // done. + void CapturePage(mate::Arguments* args); + // Methods for creating . void SetSize(const SetSizeParams& params); bool IsGuest() const; diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index ac5fb87c7535..afa04c31a46e 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -55,15 +55,6 @@ namespace api { namespace { -void OnCapturePageDone( - v8::Isolate* isolate, - const base::Callback& callback, - const SkBitmap& bitmap) { - v8::Locker locker(isolate); - v8::HandleScope handle_scope(isolate); - callback.Run(gfx::Image::CreateFrom1xBitmap(bitmap)); -} - // Converts binary data to Buffer. v8::Local ToBuffer(v8::Isolate* isolate, void* val, int size) { auto buffer = node::Buffer::Copy(isolate, static_cast(val), size); @@ -581,21 +572,6 @@ void Window::SetFocusable(bool focusable) { return window_->SetFocusable(focusable); } -void Window::CapturePage(mate::Arguments* args) { - gfx::Rect rect; - base::Callback callback; - - if (!(args->Length() == 1 && args->GetNext(&callback)) && - !(args->Length() == 2 && args->GetNext(&rect) - && args->GetNext(&callback))) { - args->ThrowError(); - return; - } - - window_->CapturePage( - rect, base::Bind(&OnCapturePageDone, args->isolate(), callback)); -} - void Window::SetProgressBar(double progress) { window_->SetProgressBar(progress); } @@ -843,7 +819,6 @@ void Window::BuildPrototype(v8::Isolate* isolate, .SetMethod("focusOnWebView", &Window::FocusOnWebView) .SetMethod("blurWebView", &Window::BlurWebView) .SetMethod("isWebViewFocused", &Window::IsWebViewFocused) - .SetMethod("capturePage", &Window::CapturePage) .SetMethod("setProgressBar", &Window::SetProgressBar) .SetMethod("setOverlayIcon", &Window::SetOverlayIcon) .SetMethod("setThumbarButtons", &Window::SetThumbarButtons) diff --git a/atom/browser/api/atom_api_window.h b/atom/browser/api/atom_api_window.h index a204b70e296c..f4b481a5cef8 100644 --- a/atom/browser/api/atom_api_window.h +++ b/atom/browser/api/atom_api_window.h @@ -155,7 +155,6 @@ class Window : public mate::TrackableObject, void SetIgnoreMouseEvents(bool ignore); void SetContentProtection(bool enable); void SetFocusable(bool focusable); - void CapturePage(mate::Arguments* args); void SetProgressBar(double progress); void SetOverlayIcon(const gfx::Image& overlay, const std::string& description); diff --git a/atom/browser/native_window.cc b/atom/browser/native_window.cc index 4eb72dfe08cd..0a1fb474a6d1 100644 --- a/atom/browser/native_window.cc +++ b/atom/browser/native_window.cc @@ -37,7 +37,6 @@ #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/size.h" #include "ui/gfx/geometry/size_conversions.h" -#include "ui/gfx/screen.h" #include "ui/gl/gpu_switching_manager.h" DEFINE_WEB_CONTENTS_USER_DATA_KEY(atom::NativeWindowRelay); @@ -315,39 +314,6 @@ bool NativeWindow::IsWebViewFocused() { return host_view && host_view->HasFocus(); } -void NativeWindow::CapturePage(const gfx::Rect& rect, - const CapturePageCallback& callback) { - const auto view = web_contents()->GetRenderWidgetHostView(); - const auto host = view ? view->GetRenderWidgetHost() : nullptr; - if (!view || !host) { - callback.Run(SkBitmap()); - return; - } - - // Capture full page if user doesn't specify a |rect|. - const gfx::Size view_size = rect.IsEmpty() ? view->GetViewBounds().size() : - rect.size(); - - // By default, the requested bitmap size is the view size in screen - // coordinates. However, if there's more pixel detail available on the - // current system, increase the requested bitmap size to capture it all. - gfx::Size bitmap_size = view_size; - const gfx::NativeView native_view = view->GetNativeView(); - const float scale = - gfx::Screen::GetScreen()->GetDisplayNearestWindow(native_view) - .device_scale_factor(); - if (scale > 1.0f) - bitmap_size = gfx::ScaleToCeiledSize(view_size, scale); - - host->CopyFromBackingStore( - gfx::Rect(rect.origin(), view_size), - bitmap_size, - base::Bind(&NativeWindow::OnCapturePageDone, - weak_factory_.GetWeakPtr(), - callback), - kBGRA_8888_SkColorType); -} - void NativeWindow::SetAutoHideMenuBar(bool auto_hide) { } @@ -634,10 +600,4 @@ void NativeWindow::NotifyReadyToShow() { FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnReadyToShow()); } -void NativeWindow::OnCapturePageDone(const CapturePageCallback& callback, - const SkBitmap& bitmap, - content::ReadbackResponse response) { - callback.Run(bitmap); -} - } // namespace atom diff --git a/atom/browser/native_window.h b/atom/browser/native_window.h index 8656c02ca939..bb2015128338 100644 --- a/atom/browser/native_window.h +++ b/atom/browser/native_window.h @@ -54,8 +54,6 @@ struct DraggableRegion; class NativeWindow : public base::SupportsUserData, public content::WebContentsObserver { public: - using CapturePageCallback = base::Callback; - class DialogScope { public: explicit DialogScope(NativeWindow* window) @@ -179,11 +177,6 @@ class NativeWindow : public base::SupportsUserData, virtual void BlurWebView(); virtual bool IsWebViewFocused(); - // Captures the page with |rect|, |callback| would be called when capturing is - // done. - virtual void CapturePage(const gfx::Rect& rect, - const CapturePageCallback& callback); - // Toggle the menu bar. virtual void SetAutoHideMenuBar(bool auto_hide); virtual bool IsMenuBarAutoHide(); @@ -296,11 +289,6 @@ class NativeWindow : public base::SupportsUserData, // Dispatch ReadyToShow event to observers. void NotifyReadyToShow(); - // Called when CapturePage has done. - void OnCapturePageDone(const CapturePageCallback& callback, - const SkBitmap& bitmap, - content::ReadbackResponse response); - // Whether window has standard frame. bool has_frame_; diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index 1f3d9d49bf06..ba07e0bf167b 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -892,17 +892,7 @@ Whether the window's document has been edited. ### `win.capturePage([rect, ]callback)` -* `rect` Object (optional) - The area of page to be captured - * `x` Integer - * `y` Integer - * `width` Integer - * `height` Integer -* `callback` Function - -Captures a snapshot of the page within `rect`. Upon completion `callback` will -be called with `callback(image)`. The `image` is an instance of -[NativeImage](native-image.md) that stores data of the snapshot. Omitting -`rect` will capture the whole visible page. +Same as `webContents.capturePage([rect, ]callback)`. ### `win.loadURL(url[, options])` diff --git a/docs/api/web-contents.md b/docs/api/web-contents.md index e33d3d0caccf..47e395740b90 100644 --- a/docs/api/web-contents.md +++ b/docs/api/web-contents.md @@ -664,6 +664,20 @@ webContents.on('found-in-page', (event, result) => { const requestId = webContents.findInPage('api'); ``` +### `webContents.capturePage([rect, ]callback)` + +* `rect` Object (optional) - The area of the page to be captured + * `x` Integer + * `y` Integer + * `width` Integer + * `height` Integer +* `callback` Function + +Captures a snapshot of the page within `rect`. Upon completion `callback` will +be called with `callback(image)`. The `image` is an instance of +[NativeImage](native-image.md) that stores data of the snapshot. Omitting +`rect` will capture the whole visible page. + ### `webContents.hasServiceWorker(callback)` * `callback` Function diff --git a/docs/api/web-view-tag.md b/docs/api/web-view-tag.md index 25725cecea2c..3dea0f95c7cd 100644 --- a/docs/api/web-view-tag.md +++ b/docs/api/web-view-tag.md @@ -463,11 +463,15 @@ Stops any `findInPage` request for the `webview` with the provided `action`. ### `.print([options])` -Prints `webview`'s web page. Same with `webContents.print([options])`. +Prints `webview`'s web page. Same as `webContents.print([options])`. ### `.printToPDF(options, callback)` -Prints `webview`'s web page as PDF, Same with `webContents.printToPDF(options, callback)` +Prints `webview`'s web page as PDF, Same as `webContents.printToPDF(options, callback)`. + +### `.capturePage([rect, ]callback)` + +Captures a snapshot of the `webview`'s page. Same as `webContents.capturePage([rect, ]callback)`. ### `.send(channel[, arg1][, arg2][, ...])` diff --git a/lib/browser/api/browser-window.js b/lib/browser/api/browser-window.js index 388e396844df..ecfdda05f8db 100644 --- a/lib/browser/api/browser-window.js +++ b/lib/browser/api/browser-window.js @@ -153,6 +153,9 @@ Object.assign(BrowserWindow.prototype, { }, showDefinitionForSelection () { return this.webContents.showDefinitionForSelection() + }, + capturePage (...args) { + return this.webContents.capturePage.apply(this.webContents, args) } }) diff --git a/lib/renderer/web-view/web-view.js b/lib/renderer/web-view/web-view.js index 98ca22d94986..6e5e81798544 100644 --- a/lib/renderer/web-view/web-view.js +++ b/lib/renderer/web-view/web-view.js @@ -386,7 +386,8 @@ var registerWebViewElement = function () { 'inspectServiceWorker', 'print', 'printToPDF', - 'showDefinitionForSelection' + 'showDefinitionForSelection', + 'capturePage' ] nonblockMethods = [ 'insertCSS',