summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjoshia@google.com <joshia@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-11-12 01:17:15 +0000
committerjoshia@google.com <joshia@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-11-12 01:17:15 +0000
commitb6e4beca3a071606c537af2d55eba21d99769cb0 (patch)
treefa20b394752eb03839814b409a31c01601c9ebb9
parent799edbdbd3aadc8044bccf4e10bf6a3ebfef1d6b (diff)
downloadchromium_src-b6e4beca3a071606c537af2d55eba21d99769cb0.zip
chromium_src-b6e4beca3a071606c537af2d55eba21d99769cb0.tar.gz
chromium_src-b6e4beca3a071606c537af2d55eba21d99769cb0.tar.bz2
Prevent crash due to DIB allocation failure
Change the way we capture tab thumbnail images so that the capturing code can deal with failure. BUG=3795 Review URL: http://codereview.chromium.org/9717 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@5244 0039d316-1c4b-4281-b951-d872f2087c98
-rwxr-xr-xbase/gfx/platform_canvas_mac.cc16
-rwxr-xr-xbase/gfx/platform_canvas_mac.h3
-rw-r--r--chrome/renderer/render_view.cc18
-rw-r--r--chrome/renderer/render_view.h2
-rw-r--r--chrome/renderer/webplugin_delegate_proxy.cc14
-rw-r--r--webkit/glue/webframe.h8
-rw-r--r--webkit/glue/webframe_impl.cc17
-rw-r--r--webkit/glue/webframe_impl.h3
-rw-r--r--webkit/tools/test_shell/test_shell_mac.mm9
-rw-r--r--webkit/tools/test_shell/test_shell_win.cc7
10 files changed, 66 insertions, 31 deletions
diff --git a/base/gfx/platform_canvas_mac.cc b/base/gfx/platform_canvas_mac.cc
index 102655c..2777dee 100755
--- a/base/gfx/platform_canvas_mac.cc
+++ b/base/gfx/platform_canvas_mac.cc
@@ -14,7 +14,7 @@ PlatformCanvasMac::PlatformCanvasMac() : SkCanvas() {
PlatformCanvasMac::PlatformCanvasMac(int width, int height, bool is_opaque)
: SkCanvas() {
- initialize(width, height, is_opaque, NULL);
+ initialize(width, height, is_opaque);
}
PlatformCanvasMac::PlatformCanvasMac(int width,
@@ -22,20 +22,22 @@ PlatformCanvasMac::PlatformCanvasMac(int width,
bool is_opaque,
CGContextRef context)
: SkCanvas() {
- initialize(width, height, is_opaque, context);
+ initialize(width, height, is_opaque);
}
PlatformCanvasMac::~PlatformCanvasMac() {
}
-void PlatformCanvasMac::initialize(int width,
+bool PlatformCanvasMac::initialize(int width,
int height,
- bool is_opaque,
- CGContextRef context) {
- SkDevice* device =
- createPlatformDevice(width, height, is_opaque, context);
+ bool is_opaque) {
+ SkDevice* device = createPlatformDevice(width, height, is_opaque, NULL);
+ if (!device)
+ return false;
+
setDevice(device);
device->unref(); // was created with refcount 1, and setDevice also refs
+ return true;
}
CGContextRef PlatformCanvasMac::beginPlatformPaint() {
diff --git a/base/gfx/platform_canvas_mac.h b/base/gfx/platform_canvas_mac.h
index 562b1a0..3f79fb3 100755
--- a/base/gfx/platform_canvas_mac.h
+++ b/base/gfx/platform_canvas_mac.h
@@ -28,8 +28,7 @@ class PlatformCanvasMac : public SkCanvas {
virtual ~PlatformCanvasMac();
// For two-part init, call if you use the no-argument constructor above
- void initialize(int width, int height, bool is_opaque, CGContextRef context);
-
+ bool initialize(int width, int height, bool is_opaque);
// These calls should surround calls to platform drawing routines. The CG
// context returned by beginPlatformPaint is the one that can be used to
diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc
index bac75d8..30cd633 100644
--- a/chrome/renderer/render_view.cc
+++ b/chrome/renderer/render_view.cc
@@ -422,8 +422,10 @@ void RenderView::SendThumbnail() {
ThumbnailScore score;
SkBitmap thumbnail;
- CaptureThumbnail(main_frame, kThumbnailWidth, kThumbnailHeight, &thumbnail,
- &score);
+ if (!CaptureThumbnail(main_frame, kThumbnailWidth, kThumbnailHeight,
+ &thumbnail, &score))
+ return;
+
// send the thumbnail message to the browser process
IPC::Message* thumbnail_msg = new IPC::Message(routing_id_,
ViewHostMsg_Thumbnail::ID, IPC::Message::PRIORITY_NORMAL);
@@ -739,7 +741,7 @@ void RenderView::CaptureText(WebFrame* frame, std::wstring* contents) {
}
}
-void RenderView::CaptureThumbnail(WebFrame* frame,
+bool RenderView::CaptureThumbnail(WebFrame* frame,
int w,
int h,
SkBitmap* thumbnail,
@@ -748,8 +750,11 @@ void RenderView::CaptureThumbnail(WebFrame* frame,
double begin = time_util::GetHighResolutionTimeNow();
#endif
- gfx::BitmapPlatformDeviceWin device(frame->CaptureImage(true));
- const SkBitmap& src_bmp = device.accessBitmap(false);
+ scoped_ptr<gfx::BitmapPlatformDevice> device;
+ if (!frame->CaptureImage(&device, true))
+ return false;
+
+ const SkBitmap& src_bmp = device->accessBitmap(false);
SkRect dest_rect;
dest_rect.set(0, 0, SkIntToScalar(w), SkIntToScalar(h));
@@ -785,7 +790,7 @@ void RenderView::CaptureThumbnail(WebFrame* frame,
score->at_top = (frame->ScrollOffset().height() == 0);
SkBitmap subset;
- device.accessBitmap(false).extractSubset(&subset, src_rect);
+ device->accessBitmap(false).extractSubset(&subset, src_rect);
// Resample the subset that we want to get it the right size.
*thumbnail = gfx::ImageOperations::Resize(
@@ -799,6 +804,7 @@ void RenderView::CaptureThumbnail(WebFrame* frame,
sprintf_s(buf, "thumbnail in %gms\n", (end - begin) * 1000);
OutputDebugStringA(buf);
#endif
+ return true;
}
double RenderView::CalculateBoringScore(SkBitmap* bitmap) {
diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h
index e73a564..a78df39 100644
--- a/chrome/renderer/render_view.h
+++ b/chrome/renderer/render_view.h
@@ -352,7 +352,7 @@ class RenderView : public RenderWidget, public WebViewDelegate,
// Creates a thumbnail of |frame|'s contents resized to (|w|, |h|)
// and puts that in |thumbnail|. Thumbnail metadata goes in |score|.
- void CaptureThumbnail(WebFrame* frame, int w, int h,
+ bool CaptureThumbnail(WebFrame* frame, int w, int h,
SkBitmap* thumbnail,
ThumbnailScore* score);
diff --git a/chrome/renderer/webplugin_delegate_proxy.cc b/chrome/renderer/webplugin_delegate_proxy.cc
index 67dcce2..efceffb 100644
--- a/chrome/renderer/webplugin_delegate_proxy.cc
+++ b/chrome/renderer/webplugin_delegate_proxy.cc
@@ -400,12 +400,18 @@ bool WebPluginDelegateProxy::CreateBitmap(
scoped_ptr<SharedMemory>* memory,
scoped_ptr<gfx::PlatformCanvasWin>* canvas) {
size_t size = GetPaintBufSize(plugin_rect_);
- memory->reset(new SharedMemory());
- if (!(*memory)->Create(L"", false, true, size))
+ scoped_ptr<SharedMemory> new_shared_memory(new SharedMemory());
+ if (!new_shared_memory->Create(L"", false, true, size))
return false;
- canvas->reset(new gfx::PlatformCanvasWin(
- plugin_rect_.width(), plugin_rect_.height(), true, (*memory)->handle()));
+ scoped_ptr<gfx::PlatformCanvasWin> new_canvas(new gfx::PlatformCanvasWin);
+ if (!new_canvas->initialize(plugin_rect_.width(), plugin_rect_.height(),
+ true, new_shared_memory->handle())) {
+ return false;
+ }
+
+ memory->swap(new_shared_memory);
+ canvas->swap(new_canvas);
return true;
}
diff --git a/webkit/glue/webframe.h b/webkit/glue/webframe.h
index 0557e35..9fd4daf 100644
--- a/webkit/glue/webframe.h
+++ b/webkit/glue/webframe.h
@@ -284,14 +284,18 @@ class WebFrame : public base::RefCounted<WebFrame> {
// Paints the contents of this web view in a bitmapped image. This image
// will not have plugins drawn. Devices are cheap to copy because the data is
- // internally refcounted, so we return by value.
+ // internally refcounted so we allocate and return a new copy
//
// Set scroll_to_zero to force all frames to be scrolled to 0,0 before
// being painted into the image. This will not send DOM events because it
// just draws the contents at a different place, but it does mean the
// scrollbars in the resulting image will appear to be wrong (they'll be
// painted as if the content was scrolled).
- virtual gfx::BitmapPlatformDevice CaptureImage(bool scroll_to_zero) = 0;
+ //
+ // Returns false on failure. CaptureImage can fail if 'image' argument
+ // is not valid or due to failure to allocate a canvas.
+ virtual bool CaptureImage(scoped_ptr<gfx::BitmapPlatformDevice>* image,
+ bool scroll_to_zero) = 0;
// This function sets a flag within WebKit to instruct it to render the page
// as View-Source (showing the HTML source for the page).
diff --git a/webkit/glue/webframe_impl.cc b/webkit/glue/webframe_impl.cc
index 5f1df1d..68deb43 100644
--- a/webkit/glue/webframe_impl.cc
+++ b/webkit/glue/webframe_impl.cc
@@ -1492,11 +1492,20 @@ void WebFrameImpl::Paint(gfx::PlatformCanvas* canvas, const gfx::Rect& rect) {
}
}
-gfx::BitmapPlatformDevice WebFrameImpl::CaptureImage(bool scroll_to_zero) {
+bool WebFrameImpl::CaptureImage(scoped_ptr<gfx::BitmapPlatformDevice>* image,
+ bool scroll_to_zero) {
+ if (!image) {
+ NOTREACHED();
+ return false;
+ }
+
// Must layout before painting.
Layout();
- gfx::PlatformCanvas canvas(frameview()->width(), frameview()->height(), true);
+ gfx::PlatformCanvas canvas;
+ if (!canvas.initialize(frameview()->width(), frameview()->height(), true))
+ return false;
+
#if defined(OS_WIN) || defined(OS_LINUX)
PlatformContextSkia context(&canvas);
GraphicsContext gc(reinterpret_cast<PlatformGraphicsContext*>(&context));
@@ -1516,7 +1525,9 @@ gfx::BitmapPlatformDevice WebFrameImpl::CaptureImage(bool scroll_to_zero) {
#if defined(OS_WIN)
device.fixupAlphaBeforeCompositing();
#endif
- return device;
+
+ image->reset(new gfx::BitmapPlatformDevice(device));
+ return true;
}
bool WebFrameImpl::IsLoading() {
diff --git a/webkit/glue/webframe_impl.h b/webkit/glue/webframe_impl.h
index af92cd2..ce2521a 100644
--- a/webkit/glue/webframe_impl.h
+++ b/webkit/glue/webframe_impl.h
@@ -111,7 +111,8 @@ class WebFrameImpl : public WebFrame {
virtual WebFrame* GetParent() const;
virtual WebFrame* GetChildFrame(const std::wstring& xpath) const;
virtual WebView* GetView() const;
- virtual gfx::BitmapPlatformDevice CaptureImage(bool scroll_to_zero);
+ virtual bool CaptureImage(scoped_ptr<gfx::BitmapPlatformDevice>* image,
+ bool scroll_to_zero);
// This method calls createRuntimeObject (in KJS::Bindings::Instance), which
// increments the refcount of the NPObject passed in.
diff --git a/webkit/tools/test_shell/test_shell_mac.mm b/webkit/tools/test_shell/test_shell_mac.mm
index 1d2f152..dafb530 100644
--- a/webkit/tools/test_shell/test_shell_mac.mm
+++ b/webkit/tools/test_shell/test_shell_mac.mm
@@ -499,9 +499,12 @@ void TestShell::ResizeSubViews() {
/* static */ std::string TestShell::DumpImage(
WebFrame* web_frame,
const std::wstring& file_name) {
- gfx::BitmapPlatformDevice device(web_frame->CaptureImage(true));
- const SkBitmap& src_bmp = device.accessBitmap(false);
-
+ scoped_ptr<gfx::BitmapPlatformDevice> device;
+ if (!web_frame->CaptureImage(&device, true))
+ return std::string();
+
+ const SkBitmap& src_bmp = device->accessBitmap(false);
+
// Encode image.
std::vector<unsigned char> png;
SkAutoLockPixels src_bmp_lock(src_bmp);
diff --git a/webkit/tools/test_shell/test_shell_win.cc b/webkit/tools/test_shell/test_shell_win.cc
index 0ca297ab..bd0d557 100644
--- a/webkit/tools/test_shell/test_shell_win.cc
+++ b/webkit/tools/test_shell/test_shell_win.cc
@@ -116,8 +116,11 @@ ATOM TestShell::RegisterWindowClass() {
// static
std::string TestShell::DumpImage(WebFrame* web_frame,
const std::wstring& file_name) {
- gfx::BitmapPlatformDevice device(web_frame->CaptureImage(true));
- const SkBitmap& src_bmp = device.accessBitmap(false);
+ scoped_ptr<gfx::BitmapPlatformDevice> device;
+ if (!web_frame->CaptureImage(&device, true))
+ return std::string();
+
+ const SkBitmap& src_bmp = device->accessBitmap(false);
// Encode image.
std::vector<unsigned char> png;