Skip to content

Commit 464310f

Browse files
committed
Merge pull request nwjs#436 from zhchbin/issue81
[API] Support api in the window to capture the visible page.
2 parents e26605f + 07664fc commit 464310f

13 files changed

+545
-1
lines changed

nw.gypi

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,8 @@
129129
'src/api/window/window.h',
130130
'src/browser/app_controller_mac.h',
131131
'src/browser/app_controller_mac.mm',
132+
'src/browser/capture_page_helper.h',
133+
'src/browser/capture_page_helper.cc',
132134
'src/browser/file_select_helper.cc',
133135
'src/browser/file_select_helper.h',
134136
'src/browser/native_window.cc',
@@ -201,8 +203,12 @@
201203
'src/paths_mac.mm',
202204
'src/renderer/autofill_agent.h',
203205
'src/renderer/autofill_agent.cc',
206+
'src/renderer/common/render_messages.cc',
207+
'src/renderer/common/render_messages.h',
204208
'src/renderer/prerenderer/prerenderer_client.cc',
205209
'src/renderer/prerenderer/prerenderer_client.h',
210+
'src/renderer/nw_render_view_observer.cc',
211+
'src/renderer/nw_render_view_observer.h',
206212
'src/renderer/shell_content_renderer_client.cc',
207213
'src/renderer/shell_content_renderer_client.h',
208214
'src/renderer/shell_render_process_observer.cc',

src/api/window/window.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,10 @@ void Window::Call(const std::string& method,
118118
int type;
119119
if (arguments.GetInteger(0, &type))
120120
shell_->Reload(static_cast<content::Shell::ReloadType>(type));
121+
} else if (method == "CapturePage") {
122+
std::string image_format_str;
123+
if (arguments.GetString(0, &image_format_str))
124+
shell_->window()->CapturePage(image_format_str);
121125
} else {
122126
NOTREACHED() << "Invalid call to Window method:" << method
123127
<< " arguments:" << arguments;

src/api/window_bindings.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,4 +320,18 @@ Window.prototype.reloadDev = function() {
320320
this.reload(3);
321321
}
322322

323+
Window.prototype.capturePage = function(callback, image_format) {
324+
if (image_format != 'jpeg' && image_format != 'png') {
325+
image_format = 'jpeg';
326+
}
327+
328+
if (typeof callback == 'function') {
329+
this.once('capturepagedone', function(imgdata) {
330+
callback(imgdata);
331+
});
332+
}
333+
334+
CallObjectMethod(this, 'CapturePage', [image_format]);
335+
}
336+
323337
} // function Window.init

src/browser/capture_page_helper.cc

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
// Copyright (c) 2012 Intel Corp
2+
// Copyright (c) 2012 The Chromium Authors
3+
//
4+
// Permission is hereby granted, free of charge, to any person obtaining a copy
5+
// of this software and associated documentation files (the "Software"), to deal
6+
// in the Software without restriction, including without limitation the rights
7+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell co
8+
// pies of the Software, and to permit persons to whom the Software is furnished
9+
// to do so, subject to the following conditions:
10+
//
11+
// The above copyright notice and this permission notice shall be included in al
12+
// l copies or substantial portions of the Software.
13+
//
14+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IM
15+
// PLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNES
16+
// S FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
17+
// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WH
18+
// ETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19+
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20+
21+
#include "content/nw/src/browser/capture_page_helper.h"
22+
23+
#include <vector>
24+
25+
#include "base/base64.h"
26+
#include "base/bind.h"
27+
#include "base/stl_util.h"
28+
#include "base/stringprintf.h"
29+
#include "content/nw/src/api/api_messages.h"
30+
#include "content/nw/src/nw_shell.h"
31+
#include "content/nw/src/renderer/common/render_messages.h"
32+
#include "content/public/browser/render_view_host.h"
33+
#include "content/public/browser/render_widget_host_view.h"
34+
#include "content/public/browser/web_contents.h"
35+
#include "skia/ext/platform_canvas.h"
36+
#include "ui/gfx/codec/jpeg_codec.h"
37+
#include "ui/gfx/codec/png_codec.h"
38+
#include "ui/gfx/rect.h"
39+
40+
namespace nw {
41+
42+
namespace capture_page_helper_constants {
43+
44+
const char kFormatValueJpeg[] = "jpeg";
45+
const char kFormatValuePng[] = "png";
46+
const char kMimeTypeJpeg[] = "image/jpeg";
47+
const char kMimeTypePng[] = "image/png";
48+
49+
const int kDefaultQuality = 90;
50+
51+
}; // namespace capture_page_helper_constants
52+
53+
namespace keys = nw::capture_page_helper_constants;
54+
55+
// static
56+
scoped_refptr<CapturePageHelper> CapturePageHelper::Create(
57+
content::Shell* shell) {
58+
return make_scoped_refptr(new CapturePageHelper(shell));
59+
}
60+
61+
CapturePageHelper::CapturePageHelper(content::Shell *shell)
62+
: content::WebContentsObserver(shell->web_contents()),
63+
shell_(shell) {
64+
}
65+
66+
CapturePageHelper::~CapturePageHelper() {
67+
}
68+
69+
void CapturePageHelper::StartCapturePage(const std::string& image_format_str) {
70+
image_format_ = FORMAT_JPEG; // default image format.
71+
if (image_format_str == keys::kFormatValueJpeg) {
72+
image_format_ = FORMAT_JPEG;
73+
} else if (image_format_str == keys::kFormatValuePng) {
74+
image_format_ = FORMAT_PNG;
75+
} else {
76+
NOTREACHED() << "Invalid image format";
77+
}
78+
79+
content::WebContents* web_contents = shell_->web_contents();
80+
content::RenderViewHost* render_view_host =
81+
web_contents->GetRenderViewHost();
82+
content::RenderWidgetHostView* view = render_view_host->GetView();
83+
84+
if (!view) {
85+
VLOG(1) << "Get RenderViewWidgetHostView Failed.";
86+
return;
87+
}
88+
89+
skia::PlatformBitmap* temp_bitmap = new skia::PlatformBitmap;
90+
render_view_host->CopyFromBackingStore(
91+
gfx::Rect(),
92+
view->GetViewBounds().size(),
93+
base::Bind(&CapturePageHelper::CopyFromBackingStoreComplete,
94+
this,
95+
base::Owned(temp_bitmap)),
96+
temp_bitmap);
97+
}
98+
99+
void CapturePageHelper::CopyFromBackingStoreComplete(
100+
skia::PlatformBitmap* bitmap,
101+
bool succeeded) {
102+
if (succeeded) {
103+
// Get image from backing store.
104+
SendResultFromBitmap(bitmap->GetBitmap());
105+
return;
106+
}
107+
108+
// Ask the renderer for a snapshot.
109+
Send(new NwViewMsg_CaptureSnapshot(routing_id()));
110+
}
111+
112+
void CapturePageHelper::SendResultFromBitmap(const SkBitmap& screen_capture) {
113+
std::vector<unsigned char> data;
114+
SkAutoLockPixels screen_capture_lock(screen_capture);
115+
bool encoded = false;
116+
std::string mime_type;
117+
switch (image_format_) {
118+
case FORMAT_JPEG:
119+
encoded = gfx::JPEGCodec::Encode(
120+
reinterpret_cast<unsigned char*>(screen_capture.getAddr32(0, 0)),
121+
gfx::JPEGCodec::FORMAT_SkBitmap,
122+
screen_capture.width(),
123+
screen_capture.height(),
124+
static_cast<int>(screen_capture.rowBytes()),
125+
keys::kDefaultQuality,
126+
&data);
127+
mime_type = keys::kMimeTypeJpeg;
128+
break;
129+
case FORMAT_PNG:
130+
encoded = gfx::PNGCodec::EncodeBGRASkBitmap(
131+
screen_capture,
132+
true, // Discard transparency.
133+
&data);
134+
mime_type = keys::kMimeTypePng;
135+
break;
136+
default:
137+
NOTREACHED() << "Invalid image format.";
138+
}
139+
140+
if (!encoded) {
141+
VLOG(1) << "Encoding failed.";
142+
return;
143+
}
144+
145+
std::string base64_result;
146+
base::StringPiece stream_as_string(
147+
reinterpret_cast<const char*>(vector_as_array(&data)), data.size());
148+
149+
base::Base64Encode(stream_as_string, &base64_result);
150+
base64_result.insert(0, base::StringPrintf("data:%s;base64,",
151+
mime_type.c_str()));
152+
153+
shell_->SendEvent("capturepagedone", base64_result);
154+
}
155+
156+
void CapturePageHelper::OnSnapshot(const SkBitmap& bitmap) {
157+
SendResultFromBitmap(bitmap);
158+
}
159+
160+
////////////////////////////////////////////////////////////////////////////////
161+
// WebContentsObserver overrides
162+
bool CapturePageHelper::OnMessageReceived(const IPC::Message& message) {
163+
bool handled = true;
164+
IPC_BEGIN_MESSAGE_MAP(CapturePageHelper, message)
165+
IPC_MESSAGE_HANDLER(NwViewHostMsg_Snapshot, OnSnapshot)
166+
IPC_MESSAGE_UNHANDLED(handled = false)
167+
IPC_END_MESSAGE_MAP()
168+
return handled;
169+
}
170+
171+
} // namespace nw

src/browser/capture_page_helper.h

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
// Copyright (c) 2012 Intel Corp
2+
// Copyright (c) 2012 The Chromium Authors
3+
//
4+
// Permission is hereby granted, free of charge, to any person obtaining a copy
5+
// of this software and associated documentation files (the "Software"), to deal
6+
// in the Software without restriction, including without limitation the rights
7+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell co
8+
// pies of the Software, and to permit persons to whom the Software is furnished
9+
// to do so, subject to the following conditions:
10+
//
11+
// The above copyright notice and this permission notice shall be included in al
12+
// l copies or substantial portions of the Software.
13+
//
14+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IM
15+
// PLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNES
16+
// S FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
17+
// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WH
18+
// ETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19+
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20+
21+
#ifndef CONTENT_NW_SRC_BROWSER_CAPTURE_PAGE_HELPER_H_
22+
#define CONTENT_NW_SRC_BROWSER_CAPTURE_PAGE_HELPER_H_
23+
24+
#include "base/memory/ref_counted.h"
25+
#include "content/public/browser/web_contents_observer.h"
26+
27+
namespace content {
28+
class Shell;
29+
}
30+
31+
namespace skia {
32+
class PlatformBitmap;
33+
}
34+
35+
class SkBitmap;
36+
37+
namespace nw {
38+
39+
namespace capture_page_helper_constants {
40+
41+
extern const char kFormatValueJpeg[];
42+
extern const char kFormatValuePng[];
43+
extern const char kMimeTypeJpeg[];
44+
extern const char kMimeTypePng[];
45+
46+
// The default quality setting used when encoding jpegs.
47+
extern const int kDefaultQuality;
48+
49+
}; // namespace capture_page_helper_constants
50+
51+
class CapturePageHelper : public base::RefCountedThreadSafe<CapturePageHelper>,
52+
public content::WebContentsObserver {
53+
public:
54+
enum ImageFormat {
55+
FORMAT_JPEG,
56+
FORMAT_PNG
57+
};
58+
59+
static scoped_refptr<CapturePageHelper> Create(content::Shell *shell);
60+
61+
// Capture a snapshot of the page.
62+
void StartCapturePage(const std::string& image_format_str);
63+
64+
private:
65+
CapturePageHelper(content::Shell *shell);
66+
~CapturePageHelper();
67+
68+
// Internal helpers ----------------------------------------------------------
69+
70+
// Message handler.
71+
void OnSnapshot(const SkBitmap& bitmap);
72+
73+
void CopyFromBackingStoreComplete(skia::PlatformBitmap* bitmap,
74+
bool succeeded);
75+
void SendResultFromBitmap(const SkBitmap& screen_capture);
76+
77+
// content::WebContentsObserver overrides:
78+
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
79+
80+
content::Shell* shell_;
81+
82+
// The format (JPEG vs PNG) of the resulting image. Set in StartCapturePage().
83+
ImageFormat image_format_;
84+
friend class base::RefCountedThreadSafe<CapturePageHelper>;
85+
};
86+
87+
}; // namespace nw
88+
89+
#endif

src/browser/native_window.cc

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "content/nw/src/browser/native_window.h"
2222

2323
#include "base/values.h"
24+
#include "content/nw/src/browser/capture_page_helper.h"
2425
#include "content/nw/src/common/shell_switches.h"
2526
#include "content/nw/src/nw_package.h"
2627
#include "content/nw/src/nw_shell.h"
@@ -66,7 +67,8 @@ NativeWindow* NativeWindow::Create(content::Shell* shell,
6667
NativeWindow::NativeWindow(content::Shell* shell,
6768
base::DictionaryValue* manifest)
6869
: shell_(shell),
69-
has_frame_(true) {
70+
has_frame_(true),
71+
capture_page_helper_(NULL) {
7072
manifest->GetBoolean(switches::kmFrame, &has_frame_);
7173

7274
LoadAppIconFromPackage(manifest);
@@ -137,6 +139,14 @@ void NativeWindow::InitFromManifest(base::DictionaryValue* manifest) {
137139
Show();
138140
}
139141

142+
void NativeWindow::CapturePage(const std::string& image_format) {
143+
// Lazily instance CapturePageHelper.
144+
if (capture_page_helper_ == NULL)
145+
capture_page_helper_ = CapturePageHelper::Create(shell_);
146+
147+
capture_page_helper_->StartCapturePage(image_format);
148+
}
149+
140150
void NativeWindow::LoadAppIconFromPackage(base::DictionaryValue* manifest) {
141151
std::string path_string;
142152
if (manifest->GetString(switches::kmIcon, &path_string)) {

src/browser/native_window.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <vector>
2626

2727
#include "base/basictypes.h"
28+
#include "base/memory/ref_counted.h"
2829
#include "base/compiler_specific.h"
2930
#include "ui/gfx/image/image.h"
3031
#include "ui/gfx/native_widget_types.h"
@@ -55,6 +56,8 @@ class Rect;
5556

5657
namespace nw {
5758

59+
class CapturePageHelper;
60+
5861
class NativeWindow {
5962
public:
6063
virtual ~NativeWindow();
@@ -113,6 +116,7 @@ class NativeWindow {
113116
content::WebContents* web_contents() const;
114117
bool has_frame() const { return has_frame_; }
115118
const gfx::Image& app_icon() const { return app_icon_; }
119+
void CapturePage(const std::string& image_format);
116120

117121
protected:
118122
explicit NativeWindow(content::Shell* shell,
@@ -126,6 +130,8 @@ class NativeWindow {
126130
// Icon showed in the task bar.
127131
gfx::Image app_icon_;
128132

133+
scoped_refptr<CapturePageHelper> capture_page_helper_;
134+
129135
private:
130136
void LoadAppIconFromPackage(base::DictionaryValue* manifest);
131137

0 commit comments

Comments
 (0)