diff options
author | jbauman <jbauman@chromium.org> | 2015-11-11 15:57:15 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-11-11 23:58:12 +0000 |
commit | 5cfe1a93acf617071b769675b9e890cd4b31a843 (patch) | |
tree | 0e436baaeb5e70e2ca8118fdd38443863771ec83 | |
parent | e7fdcf97fbede6c5d99b2542e7643540f177dc8d (diff) | |
download | chromium_src-5cfe1a93acf617071b769675b9e890cd4b31a843.zip chromium_src-5cfe1a93acf617071b769675b9e890cd4b31a843.tar.gz chromium_src-5cfe1a93acf617071b769675b9e890cd4b31a843.tar.bz2 |
Don't attempt to create backing bitmap for extremely large windows.
It's possible in some circumstances that some renderer will attempt to create an extremely large window (e.g. for a very large dropdown). In that case don't crash the browser because of an inability to allocate the backing store for the window, but ignore it and don't attempt to draw to it.
BUG=553670
Review URL: https://codereview.chromium.org/1418993009
Cr-Commit-Position: refs/heads/master@{#359188}
-rw-r--r-- | content/browser/compositor/software_output_device_win.cc | 53 | ||||
-rw-r--r-- | content/browser/compositor/software_output_device_win.h | 2 |
2 files changed, 43 insertions, 12 deletions
diff --git a/content/browser/compositor/software_output_device_win.cc b/content/browser/compositor/software_output_device_win.cc index 7f3df87..b4a41ee 100644 --- a/content/browser/compositor/software_output_device_win.cc +++ b/content/browser/compositor/software_output_device_win.cc @@ -4,7 +4,9 @@ #include "content/browser/compositor/software_output_device_win.h" +#include "base/debug/alias.h" #include "base/memory/shared_memory.h" +#include "cc/resources/shared_bitmap.h" #include "content/public/browser/browser_thread.h" #include "skia/ext/platform_canvas.h" #include "third_party/skia/include/core/SkBitmap.h" @@ -15,6 +17,10 @@ namespace content { +// If a window is larger than this in bytes, don't even try to create a +// backing bitmap for it. +static const size_t kMaxBitmapSizeBytes = 4 * (16384 * 8192); + OutputDeviceBacking::OutputDeviceBacking() : created_byte_size_(0) { } @@ -46,12 +52,21 @@ void OutputDeviceBacking::UnregisterOutputDevice( Resized(); } -base::SharedMemory* OutputDeviceBacking::GetSharedMemory() { +base::SharedMemory* OutputDeviceBacking::GetSharedMemory( + const gfx::Size& size) { if (backing_) return backing_.get(); - created_byte_size_ = GetMaxByteSize(); + size_t expected_byte_size = GetMaxByteSize(); + size_t required_size; + if (!cc::SharedBitmap::SizeInBytes(size, &required_size)) + return nullptr; + if (required_size > expected_byte_size) + return nullptr; + + created_byte_size_ = expected_byte_size; backing_.reset(new base::SharedMemory); + base::debug::Alias(&expected_byte_size); CHECK(backing_->CreateAnonymous(created_byte_size_)); return backing_.get(); } @@ -60,9 +75,13 @@ size_t OutputDeviceBacking::GetMaxByteSize() { // Minimum byte size is 1 because creating a 0-byte-long SharedMemory fails. size_t max_size = 1; for (const SoftwareOutputDeviceWin* device : devices_) { - max_size = std::max( - max_size, - static_cast<size_t>(device->viewport_pixel_size().GetArea() * 4)); + size_t current_size; + if (!cc::SharedBitmap::SizeInBytes(device->viewport_pixel_size(), + ¤t_size)) + continue; + if (current_size > kMaxBitmapSizeBytes) + continue; + max_size = std::max(max_size, current_size); } return max_size; } @@ -113,11 +132,21 @@ SkCanvas* SoftwareOutputDeviceWin::BeginPaint(const gfx::Rect& damage_rect) { DCHECK(!in_paint_); if (!contents_) { HANDLE shared_section = NULL; - if (backing_) - shared_section = backing_->GetSharedMemory()->handle().GetHandle(); - contents_ = skia::AdoptRef(skia::CreatePlatformCanvas( - viewport_pixel_size_.width(), viewport_pixel_size_.height(), true, - shared_section, skia::CRASH_ON_FAILURE)); + bool can_create_contents = true; + if (backing_) { + base::SharedMemory* memory = + backing_->GetSharedMemory(viewport_pixel_size_); + if (memory) { + shared_section = memory->handle().GetHandle(); + } else { + can_create_contents = false; + } + } + if (can_create_contents) { + contents_ = skia::AdoptRef(skia::CreatePlatformCanvas( + viewport_pixel_size_.width(), viewport_pixel_size_.height(), true, + shared_section, skia::CRASH_ON_FAILURE)); + } } damage_rect_ = damage_rect; @@ -127,12 +156,14 @@ SkCanvas* SoftwareOutputDeviceWin::BeginPaint(const gfx::Rect& damage_rect) { void SoftwareOutputDeviceWin::EndPaint() { DCHECK_CURRENTLY_ON(BrowserThread::UI); - DCHECK(contents_); DCHECK(in_paint_); in_paint_ = false; SoftwareOutputDevice::EndPaint(); + if (!contents_) + return; + gfx::Rect rect = damage_rect_; rect.Intersect(gfx::Rect(viewport_pixel_size_)); if (rect.IsEmpty()) diff --git a/content/browser/compositor/software_output_device_win.h b/content/browser/compositor/software_output_device_win.h index 3f444ae..65de1c4 100644 --- a/content/browser/compositor/software_output_device_win.h +++ b/content/browser/compositor/software_output_device_win.h @@ -31,7 +31,7 @@ class OutputDeviceBacking { void Resized(); void RegisterOutputDevice(SoftwareOutputDeviceWin* device); void UnregisterOutputDevice(SoftwareOutputDeviceWin* device); - base::SharedMemory* GetSharedMemory(); + base::SharedMemory* GetSharedMemory(const gfx::Size& size); private: size_t GetMaxByteSize(); |