summaryrefslogtreecommitdiffstats
path: root/chrome/browser/renderer_host
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/renderer_host')
-rw-r--r--chrome/browser/renderer_host/backing_store.cc4
-rw-r--r--chrome/browser/renderer_host/backing_store.h8
-rw-r--r--chrome/browser/renderer_host/backing_store_posix.cc25
-rw-r--r--chrome/browser/renderer_host/backing_store_win.cc19
-rw-r--r--chrome/browser/renderer_host/backing_store_xcb.cc40
-rw-r--r--chrome/browser/renderer_host/browser_render_process_host.cc66
-rw-r--r--chrome/browser/renderer_host/browser_render_process_host.h18
-rw-r--r--chrome/browser/renderer_host/mock_render_process_host.cc12
-rw-r--r--chrome/browser/renderer_host/mock_render_process_host.h1
-rw-r--r--chrome/browser/renderer_host/render_process_host.h10
-rw-r--r--chrome/browser/renderer_host/render_widget_helper.cc59
-rw-r--r--chrome/browser/renderer_host/render_widget_helper.h35
-rw-r--r--chrome/browser/renderer_host/render_widget_host.cc40
-rw-r--r--chrome/browser/renderer_host/render_widget_host.h8
-rw-r--r--chrome/browser/renderer_host/render_widget_host_unittest.cc28
-rw-r--r--chrome/browser/renderer_host/resource_message_filter.cc18
-rw-r--r--chrome/browser/renderer_host/resource_message_filter.h9
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.