Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1495)

Unified Diff: app/surface/transport_dib.h

Issue 3834003: On Windows, create a new TransportDIB::Handle struct which includes the file (Closed) Base URL: http://src.chromium.org/git/chromium.git
Patch Set: Rebase Created 10 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | app/surface/transport_dib_linux.cc » ('j') | app/surface/transport_dib_mac.cc » ('J')
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: app/surface/transport_dib.h
diff --git a/app/surface/transport_dib.h b/app/surface/transport_dib.h
index 6606c2b675da22a87681d513ba76e8130ba5e9f2..37a391209054027197a9cd5c3f75ea9e641c91cf 100644
--- a/app/surface/transport_dib.h
+++ b/app/surface/transport_dib.h
@@ -7,6 +7,7 @@
#pragma once
#include "base/basictypes.h"
+#include "base/process.h"
#if defined(OS_WIN) || defined(OS_MACOSX)
#include "base/shared_memory.h"
@@ -31,13 +32,55 @@ class TransportDIB {
public:
~TransportDIB();
- // Two typedefs are defined. A Handle is the type which can be sent over
- // the wire so that the remote side can map the transport DIB. The Id typedef
- // is sufficient to identify the transport DIB when you know that the remote
- // side already may have it mapped.
+ // Two typedefs are defined. A |Handle| can be sent over the wire so that the
+ // remote side can map the |TransportDIB|. These handles may be reused from
+ // previous DIBs. An |Id| is unique and never reused, but it is not sufficient
+ // to map the DIB.
#if defined(OS_WIN)
- typedef HANDLE Handle;
- // On Windows, the Id type includes a sequence number (epoch) to solve an ABA
+ // On Windows, a |Handle| is a combination of the section (i.e., file mapping)
+ // handle and the ID of the corresponding process. When the DIB is mapped in
+ // a remote process, the section handle is duplicated for use in that process.
+ // However, if the remote process does not have permission to duplicate the
+ // handle, the first process must duplicate the handle before sending it.
+ // E.g., this is necessary if the DIB is created in the browser and will be
+ // mapped in the sandboxed renderer.
+ class TransferrableSectionHandle {
+ public:
+ TransferrableSectionHandle()
+ : section_(NULL), owner_id_(NULL), should_dup_on_map_(false) {
+ }
+
+ TransferrableSectionHandle(HANDLE section, base::ProcessId owner_id,
+ bool should_dup_on_map)
+ : section_(section),
+ owner_id_(owner_id),
+ should_dup_on_map_(should_dup_on_map) {
+ }
+
+ // Duplicates the handle for use in the given process.
+ TransferrableSectionHandle DupForProcess(
+ base::ProcessHandle new_owner) const;
+
+ // Closes this handle. This should be called if this handle was duplicated
+ // and is not owned by a TransportDIB.
+ void Close() const;
+
+ // Returns true if this handle refers to an actual file mapping.
+ bool is_valid() const { return section_ != NULL && owner_id_ != NULL; }
+
+ HANDLE section() const { return section_; }
+ base::ProcessId owner_id() const { return owner_id_; }
+ bool should_dup_on_map() const { return should_dup_on_map_; }
+
+ private:
+ HANDLE section_;
+ base::ProcessId owner_id_;
+ // Whether the handle should be duplicated when the DIB is mapped.
+ bool should_dup_on_map_;
+ };
+ typedef TransferrableSectionHandle Handle;
+
+ // On Windows, the Id type is a sequence number (epoch) to solve an ABA
// issue:
// 1) Process A creates a transport DIB with HANDLE=1 and sends to B.
// 2) Process B maps the transport DIB and caches 1 -> DIB.
@@ -45,38 +88,17 @@ class TransportDIB {
// is also assigned HANDLE=1.
// 4) Process A sends the Handle to B, but B incorrectly believes that it
// already has it cached.
- struct HandleAndSequenceNum {
- HandleAndSequenceNum()
- : handle(NULL),
- sequence_num(0) {
- }
-
- HandleAndSequenceNum(HANDLE h, uint32 seq_num)
- : handle(h),
- sequence_num(seq_num) {
- }
-
- bool operator< (const HandleAndSequenceNum& other) const {
- // Use the lexicographic order on the tuple <handle, sequence_num>.
- if (other.handle != handle)
- return other.handle < handle;
- return other.sequence_num < sequence_num;
- }
-
- HANDLE handle;
- uint32 sequence_num;
- };
- typedef HandleAndSequenceNum Id;
+ typedef uint32 Id;
// Returns a default, invalid handle, that is meant to indicate a missing
// Transport DIB.
- static Handle DefaultHandleValue() { return NULL; }
+ static Handle DefaultHandleValue() { return Handle(); }
// Returns a value that is ONLY USEFUL FOR TESTS WHERE IT WON'T BE
// ACTUALLY USED AS A REAL HANDLE.
static Handle GetFakeHandleForTest() {
static int fake_handle = 10;
- return reinterpret_cast<Handle>(fake_handle++);
+ return Handle(reinterpret_cast<HANDLE>(fake_handle++), 1, false);
}
#elif defined(OS_MACOSX)
typedef base::SharedMemoryHandle Handle;
@@ -109,7 +131,41 @@ class TransportDIB {
}
#endif
- // Create a new TransportDIB, returning NULL on failure.
+ // When passing a TransportDIB::Handle across processes, you must always close
+ // the handle, even if you return early, or the handle will be leaked. Typical
+ // usage will be:
+ //
+ // MyIPCHandler(TransportDIB::Handle dib_handle) {
+ // TransportDIB::ScopedHandle handle_scoper(dib_handle);
+ // ... do some stuff, possible returning early ...
+ //
+ // TransportDIB* dib = TransportDIB::Map(handle_scoper.release());
+ // // The handle lifetime is now managed by the TransportDIB.
+ class ScopedHandle {
+ public:
+ ScopedHandle() : handle_(DefaultHandleValue()) {}
+ explicit ScopedHandle(Handle handle) : handle_(handle) {}
+
+ ~ScopedHandle() {
+ Close();
+ }
+
+ Handle release() {
+ Handle temp = handle_;
+ handle_ = DefaultHandleValue();
+ return temp;
+ }
+
+ operator Handle() { return handle_; }
+
+ private:
+ void Close();
+
+ Handle handle_;
+ DISALLOW_COPY_AND_ASSIGN(ScopedHandle);
+ };
+
+ // Create a new |TransportDIB|, returning NULL on failure.
//
// The size is the minimum size in bytes of the memory backing the transport
// DIB (we may actually allocate more than that to give us better reuse when
@@ -118,12 +174,18 @@ class TransportDIB {
// The sequence number is used to uniquely identify the transport DIB. It
// should be unique for all transport DIBs ever created in the same
// renderer.
+ //
+ // On Linux, this will also map the DIB into the current process.
static TransportDIB* Create(size_t size, uint32 sequence_num);
- // Map the referenced transport DIB. The caller owns the returned object.
+ // Map the referenced transport DIB. The caller owns the returned object.
// Returns NULL on failure.
static TransportDIB* Map(Handle transport_dib);
+ // Create a new |TransportDIB| with a handle to the shared memory. This
+ // always returns a valid pointer. The DIB is not mapped.
+ static TransportDIB* CreateWithHandle(Handle handle);
+
// Returns true if the handle is valid.
static bool is_valid(Handle dib);
@@ -131,11 +193,31 @@ class TransportDIB {
// pointer will be owned by the caller. The bitmap will be of the given size,
// which should fit inside this memory.
//
+ // On POSIX, this |TransportDIB| will be mapped if not already. On Windows,
+ // this |TransportDIB| will NOT be mapped and should not be mapped prior,
+ // because PlatformCanvas will map the file internally.
+ //
// Will return NULL on allocation failure. This could be because the image
// is too large to map into the current process' address space.
skia::PlatformCanvas* GetPlatformCanvas(int w, int h);
- // Return a pointer to the shared memory
+ // Map the DIB into the current process if it is not already. This is used to
+ // map a DIB that has already been created. Returns true if the DIB is mapped.
+ bool Map();
+
+ // Return a handle for use in a specific process. On POSIX, this simply
+ // returns the handle as in the |handle| accessor below. On Windows, this
+ // returns a duplicate handle for use in the given process. This should be
+ // used instead of the |handle| accessor only if the process that will map
+ // this DIB does not have permission to duplicate the handle from the
+ // first process.
+ //
+ // Note: On Windows, if the duplicated handle is not closed by the other side
+ // (or this process fails to transmit the handle), the shared memory will be
+ // leaked.
+ Handle GetHandleForProcess(base::ProcessHandle process_handle) const;
+
+ // Return a pointer to the shared memory.
void* memory() const;
// Return the maximum size of the shared memory. This is not the amount of
« no previous file with comments | « no previous file | app/surface/transport_dib_linux.cc » ('j') | app/surface/transport_dib_mac.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698