diff options
Diffstat (limited to 'chrome/browser/renderer_host')
17 files changed, 324 insertions, 76 deletions
diff --git a/chrome/browser/renderer_host/backing_store.cc b/chrome/browser/renderer_host/backing_store.cc index da988768..a68e785 100644 --- a/chrome/browser/renderer_host/backing_store.cc +++ b/chrome/browser/renderer_host/backing_store.cc @@ -60,7 +60,7 @@ BackingStore* BackingStoreManager::PrepareBackingStore( RenderWidgetHost* host, const gfx::Rect& backing_store_rect, base::ProcessHandle process_handle, - BitmapWireData bitmap_section, + TransportDIB* bitmap, const gfx::Rect& bitmap_rect, bool* needs_full_paint) { BackingStore* backing_store = GetBackingStore(host, @@ -76,7 +76,7 @@ BackingStore* BackingStoreManager::PrepareBackingStore( } DCHECK(backing_store != NULL); - backing_store->PaintRect(process_handle, bitmap_section, bitmap_rect); + backing_store->PaintRect(process_handle, bitmap, bitmap_rect); return backing_store; } diff --git a/chrome/browser/renderer_host/backing_store.h b/chrome/browser/renderer_host/backing_store.h index 29415a8..e6113f5 100644 --- a/chrome/browser/renderer_host/backing_store.h +++ b/chrome/browser/renderer_host/backing_store.h @@ -10,7 +10,6 @@ #include "base/gfx/size.h" #include "base/process.h" #include "build/build_config.h" -#include "chrome/common/bitmap_wire_data.h" #include "chrome/common/mru_cache.h" #if defined(OS_WIN) @@ -20,6 +19,7 @@ #endif class RenderWidgetHost; +class TransportDIB; // BackingStore ---------------------------------------------------------------- @@ -39,14 +39,14 @@ class BackingStore { // Paints the bitmap from the renderer onto the backing store. bool PaintRect(base::ProcessHandle process, - BitmapWireData bitmap_section, + TransportDIB* bitmap, const gfx::Rect& bitmap_rect); // Scrolls the given rect in the backing store, replacing the given region // identified by |bitmap_rect| by the bitmap in the file identified by the // given file handle. void ScrollRect(base::ProcessHandle process, - BitmapWireData bitmap, const gfx::Rect& bitmap_rect, + TransportDIB* bitmap, const gfx::Rect& bitmap_rect, int dx, int dy, const gfx::Rect& clip_rect, const gfx::Size& view_size); @@ -113,7 +113,7 @@ class BackingStoreManager { static BackingStore* PrepareBackingStore(RenderWidgetHost* host, const gfx::Rect& backing_store_rect, base::ProcessHandle process_handle, - BitmapWireData bitmap_section, + TransportDIB* bitmap, const gfx::Rect& bitmap_rect, bool* needs_full_paint); diff --git a/chrome/browser/renderer_host/backing_store_posix.cc b/chrome/browser/renderer_host/backing_store_posix.cc index f925ef9..1d195fb 100644 --- a/chrome/browser/renderer_host/backing_store_posix.cc +++ b/chrome/browser/renderer_host/backing_store_posix.cc @@ -5,6 +5,7 @@ #include "chrome/browser/renderer_host/backing_store.h" #include "base/logging.h" +#include "chrome/common/transport_dib.h" #include "skia/ext/platform_canvas.h" #include "skia/include/SkBitmap.h" #include "skia/include/SkCanvas.h" @@ -19,20 +20,20 @@ BackingStore::~BackingStore() { } bool BackingStore::PaintRect(base::ProcessHandle process, - BitmapWireData bitmap, + TransportDIB* bitmap, const gfx::Rect& bitmap_rect) { - if (bitmap.width() != bitmap_rect.width() || - bitmap.height() != bitmap_rect.height() || - bitmap.config() != SkBitmap::kARGB_8888_Config) { - return false; - } + SkBitmap skbitmap; + skbitmap.setConfig(SkBitmap::kARGB_8888_Config, bitmap_rect.width(), + bitmap_rect.height(), 4 * bitmap_rect.width()); + + skbitmap.setPixels(bitmap->memory()); - canvas_.drawBitmap(bitmap, bitmap_rect.x(), bitmap_rect.y()); + canvas_.drawBitmap(skbitmap, bitmap_rect.x(), bitmap_rect.y()); return true; } void BackingStore::ScrollRect(base::ProcessHandle process, - BitmapWireData bitmap, + TransportDIB* bitmap, const gfx::Rect& bitmap_rect, int dx, int dy, const gfx::Rect& clip_rect, @@ -59,12 +60,6 @@ void BackingStore::ScrollRect(base::ProcessHandle process, DCHECK(clip_rect.bottom() <= canvas_.getDevice()->height()); DCHECK(clip_rect.right() <= canvas_.getDevice()->width()); - if (bitmap.width() != bitmap_rect.width() || - bitmap.height() != bitmap_rect.height() || - bitmap.config() != SkBitmap::kARGB_8888_Config) { - return; - } - const SkBitmap &backing_bitmap = canvas_.getDevice()->accessBitmap(true); const int stride = backing_bitmap.rowBytes(); uint8_t* x = static_cast<uint8_t*>(backing_bitmap.getPixels()); @@ -123,6 +118,6 @@ void BackingStore::ScrollRect(base::ProcessHandle process, } // Now paint the new bitmap data. - canvas_.drawBitmap(bitmap, bitmap_rect.x(), bitmap_rect.y()); + PaintRect(process, bitmap, bitmap_rect); return; } diff --git a/chrome/browser/renderer_host/backing_store_win.cc b/chrome/browser/renderer_host/backing_store_win.cc index 2ca9396..dcc1ad4 100644 --- a/chrome/browser/renderer_host/backing_store_win.cc +++ b/chrome/browser/renderer_host/backing_store_win.cc @@ -6,7 +6,7 @@ #include "base/gfx/gdi_util.h" #include "chrome/browser/renderer_host/render_widget_host.h" -#include "chrome/common/win_util.h" +#include "chrome/common/transport_dib.h" // BackingStore (Windows) ------------------------------------------------------ @@ -31,14 +31,8 @@ BackingStore::~BackingStore() { } bool BackingStore::PaintRect(base::ProcessHandle process, - BitmapWireData bitmap_section, + TransportDIB* bitmap, const gfx::Rect& bitmap_rect) { - // The bitmap received is valid only in the renderer process. - HANDLE valid_bitmap = - win_util::GetSectionFromProcess(bitmap_section, process, false); - if (!valid_bitmap) - return false; - if (!backing_store_dib_) { backing_store_dib_ = CreateDIB(hdc_, size_.width(), size_.height(), true, NULL); @@ -48,8 +42,7 @@ bool BackingStore::PaintRect(base::ProcessHandle process, // TODO(darin): protect against integer overflow DWORD size = 4 * bitmap_rect.width() * bitmap_rect.height(); - void* backing_store_data = MapViewOfFile(valid_bitmap, FILE_MAP_READ, 0, 0, - size); + // These values are shared with gfx::PlatformDevice BITMAPINFOHEADER hdr; gfx::CreateBitmapHeader(bitmap_rect.width(), bitmap_rect.height(), &hdr); @@ -65,18 +58,16 @@ bool BackingStore::PaintRect(base::ProcessHandle process, 0, 0, // source x,y paint_rect.width(), paint_rect.height(), - backing_store_data, + bitmap->memory(), reinterpret_cast<BITMAPINFO*>(&hdr), DIB_RGB_COLORS, SRCCOPY); - UnmapViewOfFile(backing_store_data); - CloseHandle(valid_bitmap); return true; } void BackingStore::ScrollRect(base::ProcessHandle process, - BitmapWireData bitmap, + TransportDIB* bitmap, const gfx::Rect& bitmap_rect, int dx, int dy, const gfx::Rect& clip_rect, diff --git a/chrome/browser/renderer_host/backing_store_xcb.cc b/chrome/browser/renderer_host/backing_store_xcb.cc new file mode 100644 index 0000000..ba6a12b --- /dev/null +++ b/chrome/browser/renderer_host/backing_store_xcb.cc @@ -0,0 +1,40 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/renderer_host/backing_store.h" + +#include <xcb/xcb.h> + +#include "base/logging.h" +#include "chrome/common/transport_dib.h" + +#ifdef NDEBUG +#define XCB_CALL(func, ...) func(__VA_ARGS__) +#else +#define XCB_CALL(func, ...) do { \ + xcb_void_cookie_t cookie = func##_checked(__VA_ARGS__); \ + xcb_generic_error_t* error = xcb_request_check(connection_, cookie); \ + if (error) { \ + CHECK(false) << "XCB error" \ + << " code:" << error->error_code \ + << " type:" << error->response_type \ + << " sequence:" << error->sequence; \ + } \ +} while(false); +#endif + +BackingStore::BackingStore(const gfx::Size& size, + xcb_connection_t* connection, + xcb_window_t window, + bool use_shared_memory) + : connection_(connection), + use_shared_memory_(use_shared_memory), + pixmap_(xcb_generate_id(connection)) { + XCB_CALL(xcb_create_pixmap, connection_, 32, pixmap, window, size.width(), + size.height()); +} + +BackingStore::~BackingStore() { + XCB_CALL(xcb_free_pixmap, pixmap_); +} diff --git a/chrome/browser/renderer_host/browser_render_process_host.cc b/chrome/browser/renderer_host/browser_render_process_host.cc index eda2f1a..d17ab83 100644 --- a/chrome/browser/renderer_host/browser_render_process_host.cc +++ b/chrome/browser/renderer_host/browser_render_process_host.cc @@ -128,7 +128,10 @@ void BrowserRenderProcessHost::RegisterPrefs(PrefService* prefs) { BrowserRenderProcessHost::BrowserRenderProcessHost(Profile* profile) : RenderProcessHost(profile), visible_widgets_(0), - backgrounded_(true) { + backgrounded_(true), + ALLOW_THIS_IN_INITIALIZER_LIST(cached_dibs_cleaner_( + base::TimeDelta::FromSeconds(5), + this, &BrowserRenderProcessHost::ClearTransportDIBCache)) { DCHECK(host_id() >= 0); // We use a negative host_id_ in destruction. widget_helper_ = new RenderWidgetHelper(host_id()); @@ -170,6 +173,8 @@ BrowserRenderProcessHost::~BrowserRenderProcessHost() { NotificationService::current()->RemoveObserver(this, NotificationType::USER_SCRIPTS_LOADED, NotificationService::AllSources()); + + ClearTransportDIBCache(); } // When we're started with the --start-renderers-manually flag, we pop up a @@ -605,6 +610,65 @@ bool BrowserRenderProcessHost::FastShutdownIfPossible() { return true; } +// This is a platform specific function for mapping a transport DIB given its id +TransportDIB* BrowserRenderProcessHost::MapTransportDIB( + TransportDIB::Id dib_id) { +#if defined(OS_WIN) + // On Windows we need to duplicate the handle from the remote process + HANDLE section = win_util::GetSectionFromProcess( + dib_id.handle, GetRendererProcessHandle(), false /* read write */); + return TransportDIB::Map(section); +#elif defined(OS_MACOSX) + // On OSX, the browser allocates all DIBs and keeps a file descriptor around + // for each. + return widget_helper_->MapTransportDIB(dib_id); +#elif defined(OS_LINUX) + return TransportDIB::Map(dib_id); +#endif // defined(OS_LINUX) +} + +TransportDIB* BrowserRenderProcessHost::GetTransportDIB( + TransportDIB::Id dib_id) { + const std::map<TransportDIB::Id, TransportDIB*>::iterator + i = cached_dibs_.find(dib_id); + if (i != cached_dibs_.end()) { + cached_dibs_cleaner_.Reset(); + return i->second; + } + + TransportDIB* dib = MapTransportDIB(dib_id); + if (!dib) + return NULL; + + if (cached_dibs_.size() >= MAX_MAPPED_TRANSPORT_DIBS) { + // Clean a single entry from the cache + std::map<TransportDIB::Id, TransportDIB*>::iterator smallest_iterator; + size_t smallest_size = std::numeric_limits<size_t>::max(); + + for (std::map<TransportDIB::Id, TransportDIB*>::iterator + i = cached_dibs_.begin(); i != cached_dibs_.end(); ++i) { + if (i->second->size() <= smallest_size) + smallest_iterator = i; + } + + delete smallest_iterator->second; + cached_dibs_.erase(smallest_iterator); + } + + cached_dibs_[dib_id] = dib; + cached_dibs_cleaner_.Reset(); + return dib; +} + +void BrowserRenderProcessHost::ClearTransportDIBCache() { + for (std::map<TransportDIB::Id, TransportDIB*>::iterator + i = cached_dibs_.begin(); i != cached_dibs_.end(); ++i) { + delete i->second; + } + + cached_dibs_.clear(); +} + bool BrowserRenderProcessHost::Send(IPC::Message* msg) { if (!channel_.get()) { delete msg; diff --git a/chrome/browser/renderer_host/browser_render_process_host.h b/chrome/browser/renderer_host/browser_render_process_host.h index be7e225..dad06b5 100644 --- a/chrome/browser/renderer_host/browser_render_process_host.h +++ b/chrome/browser/renderer_host/browser_render_process_host.h @@ -13,6 +13,8 @@ #include "base/ref_counted.h" #include "base/scoped_ptr.h" #include "base/shared_memory.h" +#include "base/timer.h" +#include "chrome/common/transport_dib.h" #include "chrome/browser/renderer_host/audio_renderer_host.h" #include "chrome/browser/renderer_host/render_process_host.h" #include "chrome/common/notification_observer.h" @@ -62,6 +64,7 @@ class BrowserRenderProcessHost : public RenderProcessHost, virtual void WidgetHidden(); virtual void AddWord(const std::wstring& word); virtual bool FastShutdownIfPossible(); + virtual TransportDIB* GetTransportDIB(TransportDIB::Id dib_id); // IPC::Channel::Sender via RenderProcessHost. virtual bool Send(IPC::Message* msg); @@ -99,6 +102,7 @@ class BrowserRenderProcessHost : public RenderProcessHost, void OnClipboardReadText(std::wstring* result); void OnClipboardReadAsciiText(std::string* result); void OnClipboardReadHTML(std::wstring* markup, GURL* src_url); + void OnUpdatedCacheStats(const CacheManager::UsageStats& stats); // Initialize support for visited links. Send the renderer process its initial @@ -140,6 +144,20 @@ class BrowserRenderProcessHost : public RenderProcessHost, // The host of audio renderers in the renderer process. scoped_refptr<AudioRendererHost> audio_renderer_host_; + // A map of transport DIB ids to cached TransportDIBs + std::map<TransportDIB::Id, TransportDIB*> cached_dibs_; + enum { + // This is the maximum size of |cached_dibs_| + MAX_MAPPED_TRANSPORT_DIBS = 3, + }; + + // Map a transport DIB from its Id and return it. Returns NULL on error. + TransportDIB* MapTransportDIB(TransportDIB::Id dib_id); + + void ClearTransportDIBCache(); + // This is used to clear our cache five seconds after the last use. + base::DelayTimer<BrowserRenderProcessHost> cached_dibs_cleaner_; + DISALLOW_COPY_AND_ASSIGN(BrowserRenderProcessHost); }; diff --git a/chrome/browser/renderer_host/mock_render_process_host.cc b/chrome/browser/renderer_host/mock_render_process_host.cc index c345b59..dc33bc1 100644 --- a/chrome/browser/renderer_host/mock_render_process_host.cc +++ b/chrome/browser/renderer_host/mock_render_process_host.cc @@ -57,6 +57,18 @@ bool MockRenderProcessHost::Send(IPC::Message* msg) { return true; } +TransportDIB* MockRenderProcessHost::GetTransportDIB(TransportDIB::Id dib_id) { +#if defined(OS_WIN) + return TransportDIB::Map(dib_id.handle); +#elif defined(OS_MACOSX) + // On Mac, TransportDIBs are always created in the browser, so we cannot map + // one from a dib_id. + return TransportDIB::Create(100 * 100 * 4, 0); +#elif defined(OS_LINUX) + return TransportDIB::Map(dib_id); +#endif +} + void MockRenderProcessHost::OnMessageReceived(const IPC::Message& msg) { } diff --git a/chrome/browser/renderer_host/mock_render_process_host.h b/chrome/browser/renderer_host/mock_render_process_host.h index d1ed58d..bfe49ee 100644 --- a/chrome/browser/renderer_host/mock_render_process_host.h +++ b/chrome/browser/renderer_host/mock_render_process_host.h @@ -35,6 +35,7 @@ class MockRenderProcessHost : public RenderProcessHost { virtual void WidgetHidden(); virtual void AddWord(const std::wstring& word); virtual bool FastShutdownIfPossible(); + virtual TransportDIB* GetTransportDIB(TransportDIB::Id dib_id); // IPC::Channel::Sender via RenderProcessHost. virtual bool Send(IPC::Message* msg); diff --git a/chrome/browser/renderer_host/render_process_host.h b/chrome/browser/renderer_host/render_process_host.h index 8b90b3d..4f8179c 100644 --- a/chrome/browser/renderer_host/render_process_host.h +++ b/chrome/browser/renderer_host/render_process_host.h @@ -11,6 +11,7 @@ #include "base/process.h" #include "base/scoped_ptr.h" #include "chrome/common/ipc_sync_channel.h" +#include "chrome/common/transport_dib.h" class Profile; @@ -124,6 +125,15 @@ class RenderProcessHost : public IPC::Channel::Sender, // Returns True if it was able to do fast shutdown. virtual bool FastShutdownIfPossible() = 0; + // Transport DIB functions --------------------------------------------------- + + // Return the TransportDIB for the given id. On Linux, this can involve + // mapping shared memory. On Mac, the shared memory is created in the browser + // process and the cached metadata is returned. On Windows, this involves + // duplicating the handle from the remote process. The RenderProcessHost + // still owns the returned DIB. + virtual TransportDIB* GetTransportDIB(TransportDIB::Id dib_id) = 0; + // Static management functions ----------------------------------------------- // Flag to run the renderer in process. This is primarily diff --git a/chrome/browser/renderer_host/render_widget_helper.cc b/chrome/browser/renderer_host/render_widget_helper.cc index a03bb1b..715a85b 100644 --- a/chrome/browser/renderer_host/render_widget_helper.cc +++ b/chrome/browser/renderer_host/render_widget_helper.cc @@ -56,6 +56,10 @@ RenderWidgetHelper::~RenderWidgetHelper() { // The elements of pending_paints_ each hold an owning reference back to this // object, so we should not be destroyed unless pending_paints_ is empty! DCHECK(pending_paints_.empty()); + +#if defined(OS_MACOSX) + ClearAllocatedDIBs(); +#endif } int RenderWidgetHelper::GetNextRoutingID() { @@ -244,3 +248,58 @@ void RenderWidgetHelper::OnSimulateReceivedMessage( if (host) host->OnMessageReceived(message); } + +#if defined(OS_MACOSX) +TransportDIB* RenderWidgetHelper::MapTransportDIB(TransportDIB::Id dib_id) { + AutoLock locked(allocated_dibs_lock_); + + const std::map<TransportDIB::Id, int>::iterator + i = allocated_dibs_.find(dib_id); + if (i == allocated_dibs_.end()) + return NULL; + + base::FileDescriptor fd(dup(i->second), true); + return TransportDIB::Map(fd); +} + +void RenderWidgetHelper::AllocTransportDIB( + size_t size, IPC::Maybe<TransportDIB::Handle>* result) { + base::SharedMemory* shared_memory = new base::SharedMemory(); + if (!shared_memory->Create(L"", false /* read write */, + false /* do not open existing */, size)) { + result->valid = false; + delete shared_memory; + return; + } + + result->valid = true; + shared_memory->GiveToProcess(0 /* pid, not needed */, &result->value); + + // Keep a copy of the file descriptor around + AutoLock locked(allocated_dibs_lock_); + allocated_dibs_[shared_memory->id()] = dup(result->value.fd); +} + +void RenderWidgetHelper::FreeTransportDIB(TransportDIB::Id dib_id) { + AutoLock locked(allocated_dibs_lock_); + + const std::map<TransportDIB::Id, int>::iterator + i = allocated_dibs_.find(dib_id); + + if (i != allocated_dibs_.end()) { + close(i->second); + allocated_dibs_.erase(i); + } else { + DLOG(WARNING) << "Renderer asked us to free unknown transport DIB"; + } +} + +void RenderWidgetHelper::ClearAllocatedDIBs() { + for (std::map<TransportDIB::Id, int>::iterator + i = allocated_dibs_.begin(); i != allocated_dibs_.end(); ++i) { + close(i->second); + } + + allocated_dibs_.clear(); +} +#endif diff --git a/chrome/browser/renderer_host/render_widget_helper.h b/chrome/browser/renderer_host/render_widget_helper.h index 83cedb0..eb13ff0 100644 --- a/chrome/browser/renderer_host/render_widget_helper.h +++ b/chrome/browser/renderer_host/render_widget_helper.h @@ -1,4 +1,3 @@ - // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -12,7 +11,9 @@ #include "base/ref_counted.h" #include "base/lock.h" #include "base/waitable_event.h" +#include "chrome/common/ipc_maybe.h" #include "chrome/common/modal_dialog_event.h" +#include "chrome/common/transport_dib.h" namespace IPC { class Message; @@ -74,6 +75,15 @@ class ResourceDispatcherHost; // GetBackingStore method is called, it will call WaitForPaintMsg if it has // no backingstore. // +// TRANSPORT DIB CREATION +// +// On some platforms (currently the Mac) the renderer cannot create transport +// DIBs because of sandbox limitations. Thus, it has to make synchronous IPCs +// to the browser for them. Since these requests are synchronous, they cannot +// terminate on the UI thread. Thus, in this case, this object performs the +// allocation and maintains the set of allocated transport DIBs which the +// renderers can refer to. +// class RenderWidgetHelper : public base::RefCountedThreadSafe<RenderWidgetHelper> { public: @@ -99,6 +109,11 @@ class RenderWidgetHelper : const base::TimeDelta& max_delay, IPC::Message* msg); +#if defined(OS_MACOSX) + // Given the id of a transport DIB, return a mapping to it or NULL on error. + TransportDIB* MapTransportDIB(TransportDIB::Id dib_id); +#endif + // IO THREAD ONLY ----------------------------------------------------------- @@ -114,6 +129,14 @@ class RenderWidgetHelper : ModalDialogEvent* modal_dialog_event); void CreateNewWidget(int opener_id, bool activatable, int* route_id); +#if defined(OS_MACOSX) + // Called on the IO thread to handle the allocation of a transport DIB + void AllocTransportDIB(size_t size, IPC::Maybe<TransportDIB::Handle>* result); + + // Called on the IO thread to handle the freeing of a transport DIB + void FreeTransportDIB(TransportDIB::Id dib_id); +#endif + private: // A class used to proxy a paint message. PaintMsgProxy objects are created // on the IO thread and destroyed on the UI thread. @@ -141,6 +164,16 @@ class RenderWidgetHelper : int new_render_process_host_id, int new_request_id); +#if defined(OS_MACOSX) + // Called on destruction to release all allocated transport DIBs + void ClearAllocatedDIBs(); + + // On OSX we keep file descriptors to all the allocated DIBs around until + // the renderer frees them. + Lock allocated_dibs_lock_; + std::map<TransportDIB::Id, int> allocated_dibs_; +#endif + // A map of live paint messages. Must hold pending_paints_lock_ to access. // The PaintMsgProxy objects are not owned by this map. (See PaintMsgProxy // for details about how the lifetime of instances are managed.) diff --git a/chrome/browser/renderer_host/render_widget_host.cc b/chrome/browser/renderer_host/render_widget_host.cc index a3c3018..1bd81cd 100644 --- a/chrome/browser/renderer_host/render_widget_host.cc +++ b/chrome/browser/renderer_host/render_widget_host.cc @@ -424,10 +424,20 @@ void RenderWidgetHost::OnMsgPaintRect( DCHECK(!params.bitmap_rect.IsEmpty()); DCHECK(!params.view_size.IsEmpty()); - // Paint the backing store. This will update it with the renderer-supplied - // bits. The view will read out of the backing store later to actually draw - // to the screen. - PaintBackingStoreRect(params.bitmap, params.bitmap_rect, params.view_size); + const size_t size = params.bitmap_rect.height() * + params.bitmap_rect.width() * 4; + TransportDIB* dib = process_->GetTransportDIB(params.bitmap); + if (dib) { + if (dib->size() < size) { + DLOG(WARNING) << "Transport DIB too small for given rectangle"; + process()->ReceivedBadMessage(ViewHostMsg_PaintRect__ID); + } else { + // Paint the backing store. This will update it with the renderer-supplied + // bits. The view will read out of the backing store later to actually draw + // to the screen. + PaintBackingStoreRect(dib, params.bitmap_rect, params.view_size); + } + } // ACK early so we can prefetch the next PaintRect if there is a next one. // This must be done AFTER we're done painting with the bitmap supplied by the @@ -474,10 +484,20 @@ void RenderWidgetHost::OnMsgScrollRect( DCHECK(!params.view_size.IsEmpty()); - // Scroll the backing store. - ScrollBackingStoreRect(params.bitmap, params.bitmap_rect, - params.dx, params.dy, - params.clip_rect, params.view_size); + const size_t size = params.bitmap_rect.height() * + params.bitmap_rect.width() * 4; + TransportDIB* dib = process_->GetTransportDIB(params.bitmap); + if (dib) { + if (dib->size() < size) { + LOG(WARNING) << "Transport DIB too small for given rectangle"; + process()->ReceivedBadMessage(ViewHostMsg_PaintRect__ID); + } else { + // Scroll the backing store. + ScrollBackingStoreRect(dib, params.bitmap_rect, + params.dx, params.dy, + params.clip_rect, params.view_size); + } + } // ACK early so we can prefetch the next ScrollRect if there is a next one. // This must be done AFTER we're done painting with the bitmap supplied by the @@ -561,7 +581,7 @@ void RenderWidgetHost::OnMsgImeUpdateStatus(int control, } } -void RenderWidgetHost::PaintBackingStoreRect(BitmapWireData bitmap, +void RenderWidgetHost::PaintBackingStoreRect(TransportDIB* bitmap, const gfx::Rect& bitmap_rect, const gfx::Size& view_size) { if (is_hidden_) { @@ -590,7 +610,7 @@ void RenderWidgetHost::PaintBackingStoreRect(BitmapWireData bitmap, } } -void RenderWidgetHost::ScrollBackingStoreRect(BitmapWireData bitmap, +void RenderWidgetHost::ScrollBackingStoreRect(TransportDIB* bitmap, const gfx::Rect& bitmap_rect, int dx, int dy, const gfx::Rect& clip_rect, diff --git a/chrome/browser/renderer_host/render_widget_host.h b/chrome/browser/renderer_host/render_widget_host.h index 48fc912..8c8f007 100644 --- a/chrome/browser/renderer_host/render_widget_host.h +++ b/chrome/browser/renderer_host/render_widget_host.h @@ -9,7 +9,6 @@ #include "base/gfx/size.h" #include "base/timer.h" -#include "chrome/common/bitmap_wire_data.h" #include "chrome/common/ipc_channel.h" #include "testing/gtest/include/gtest/gtest_prod.h" @@ -21,6 +20,7 @@ class BackingStore; class PaintObserver; class RenderProcessHost; class RenderWidgetHostView; +class TransportDIB; class WebInputEvent; class WebKeyboardEvent; class WebMouseEvent; @@ -262,14 +262,14 @@ class RenderWidgetHost : public IPC::Channel::Listener { void OnMsgImeUpdateStatus(int control, const gfx::Rect& caret_rect); // Paints the given bitmap to the current backing store at the given location. - void PaintBackingStoreRect(BitmapWireData bitmap, + void PaintBackingStoreRect(TransportDIB* dib, const gfx::Rect& bitmap_rect, const gfx::Size& view_size); // Scrolls the given |clip_rect| in the backing by the given dx/dy amount. The - // |bitmap| and its corresponding location |bitmap_rect| in the backing store + // |dib| and its corresponding location |bitmap_rect| in the backing store // is the newly painted pixels by the renderer. - void ScrollBackingStoreRect(BitmapWireData bitmap, + void ScrollBackingStoreRect(TransportDIB* dib, const gfx::Rect& bitmap_rect, int dx, int dy, const gfx::Rect& clip_rect, diff --git a/chrome/browser/renderer_host/render_widget_host_unittest.cc b/chrome/browser/renderer_host/render_widget_host_unittest.cc index 4f0bfb6..8a31ec91 100644 --- a/chrome/browser/renderer_host/render_widget_host_unittest.cc +++ b/chrome/browser/renderer_host/render_widget_host_unittest.cc @@ -10,10 +10,6 @@ #include "chrome/common/render_messages.h" #include "testing/gtest/include/gtest/gtest.h" -#if defined(OS_POSIX) -#include "skia/ext/platform_canvas.h" -#endif - namespace { // RenderWidgetHostProcess ----------------------------------------------------- @@ -22,9 +18,7 @@ class RenderWidgetHostProcess : public MockRenderProcessHost { public: explicit RenderWidgetHostProcess(Profile* profile) : MockRenderProcessHost(profile), -#if defined(OS_WIN) current_paint_buf_(NULL), -#endif paint_msg_should_reply_(false), paint_msg_reply_flags_(0) { // DANGER! This is a hack. The RenderWidgetHost checks the channel to see @@ -54,11 +48,7 @@ class RenderWidgetHostProcess : public MockRenderProcessHost { const base::TimeDelta& max_delay, IPC::Message* msg); -#if defined(OS_WIN) - scoped_ptr<base::SharedMemory> current_paint_buf_; -#elif defined(OS_POSIX) - skia::PlatformCanvas canvas; -#endif + TransportDIB* current_paint_buf_; // Set to true when WaitForPaintMsg should return a successful paint messaage // reply. False implies timeout. @@ -75,20 +65,10 @@ void RenderWidgetHostProcess::InitPaintRectParams( ViewHostMsg_PaintRect_Params* params) { // Create the shared backing store. const int w = 100, h = 100; + const size_t pixel_size = w * h * 4; -#if defined(OS_WIN) - int pixel_size = w * h * 4; - - current_paint_buf_.reset(new base::SharedMemory()); - ASSERT_TRUE(current_paint_buf_->Create(std::wstring(), false, true, - pixel_size)); - - params->bitmap = current_paint_buf_->handle(); -#elif defined(OS_POSIX) - ASSERT_TRUE(canvas.initialize(w, h, true)); - params->bitmap = canvas.getDevice()->accessBitmap(false); -#endif - + current_paint_buf_ = TransportDIB::Create(pixel_size, 0); + params->bitmap = current_paint_buf_->id(); params->bitmap_rect = gfx::Rect(0, 0, w, h); params->view_size = gfx::Size(w, h); params->flags = paint_msg_reply_flags_; diff --git a/chrome/browser/renderer_host/resource_message_filter.cc b/chrome/browser/renderer_host/resource_message_filter.cc index 8616e29..2215257 100644 --- a/chrome/browser/renderer_host/resource_message_filter.cc +++ b/chrome/browser/renderer_host/resource_message_filter.cc @@ -234,6 +234,12 @@ bool ResourceMessageFilter::OnMessageReceived(const IPC::Message& message) { OnNotifyAudioPacketReady) IPC_MESSAGE_HANDLER(ViewHostMsg_GetAudioVolume, OnGetAudioVolume) IPC_MESSAGE_HANDLER(ViewHostMsg_SetAudioVolume, OnSetAudioVolume) +#if defined(OS_MACOSX) + IPC_MESSAGE_HANDLER(ViewHostMsg_AllocTransportDIB, + OnAllocTransportDIB) + IPC_MESSAGE_HANDLER(ViewHostMsg_FreeTransportDIB, + OnFreeTransportDIB) +#endif IPC_MESSAGE_UNHANDLED( handled = false) IPC_END_MESSAGE_MAP_EX() @@ -794,3 +800,15 @@ void ResourceMessageFilter::OnSetAudioVolume( double left_channel, double right_channel) { // TODO(hclam): delegate to AudioRendererHost and handle this message. } + +#if defined(OS_MACOSX) +void ResourceMessageFilter::OnAllocTransportDIB( + size_t size, IPC::Maybe<TransportDIB::Handle>* handle) { + render_widget_helper_->AllocTransportDIB(size, handle); +} + +void ResourceMessageFilter::OnFreeTransportDIB( + TransportDIB::Id dib_id) { + render_widget_helper_->FreeTransportDIB(dib_id); +} +#endif diff --git a/chrome/browser/renderer_host/resource_message_filter.h b/chrome/browser/renderer_host/resource_message_filter.h index 85ad101..ef389a8 100644 --- a/chrome/browser/renderer_host/resource_message_filter.h +++ b/chrome/browser/renderer_host/resource_message_filter.h @@ -15,8 +15,10 @@ #include "chrome/browser/net/resolve_proxy_msg_helper.h" #include "chrome/browser/renderer_host/resource_dispatcher_host.h" #include "chrome/common/ipc_channel_proxy.h" +#include "chrome/common/ipc_maybe.h" #include "chrome/common/modal_dialog_event.h" #include "chrome/common/notification_observer.h" +#include "chrome/common/transport_dib.h" #include "webkit/glue/cache_manager.h" #if defined(OS_WIN) @@ -167,7 +169,7 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter, void OnResourceTypeStats(const CacheManager::ResourceTypeStats& stats); void OnResolveProxy(const GURL& url, IPC::Message* reply_msg); - + // ResolveProxyMsgHelper::Delegate implementation: virtual void OnResolveProxyCompleted(IPC::Message* reply_msg, int result, @@ -203,6 +205,11 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter, void OnSetAudioVolume(const IPC::Message& msg, int stream_id, double left_channel, double right_channel); + // Browser side transport DIB allocation + void OnAllocTransportDIB(size_t size, + IPC::Maybe<TransportDIB::Handle>* result); + void OnFreeTransportDIB(TransportDIB::Id dib_id); + // We have our own clipboard service because we want to access the clipboard // on the IO thread instead of forwarding (possibly synchronous) messages to // the UI thread. |