diff options
author | joshia@google.com <joshia@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-11-12 01:17:15 +0000 |
---|---|---|
committer | joshia@google.com <joshia@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-11-12 01:17:15 +0000 |
commit | b6e4beca3a071606c537af2d55eba21d99769cb0 (patch) | |
tree | fa20b394752eb03839814b409a31c01601c9ebb9 | |
parent | 799edbdbd3aadc8044bccf4e10bf6a3ebfef1d6b (diff) | |
download | chromium_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-x | base/gfx/platform_canvas_mac.cc | 16 | ||||
-rwxr-xr-x | base/gfx/platform_canvas_mac.h | 3 | ||||
-rw-r--r-- | chrome/renderer/render_view.cc | 18 | ||||
-rw-r--r-- | chrome/renderer/render_view.h | 2 | ||||
-rw-r--r-- | chrome/renderer/webplugin_delegate_proxy.cc | 14 | ||||
-rw-r--r-- | webkit/glue/webframe.h | 8 | ||||
-rw-r--r-- | webkit/glue/webframe_impl.cc | 17 | ||||
-rw-r--r-- | webkit/glue/webframe_impl.h | 3 | ||||
-rw-r--r-- | webkit/tools/test_shell/test_shell_mac.mm | 9 | ||||
-rw-r--r-- | webkit/tools/test_shell/test_shell_win.cc | 7 |
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; |