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

Unified Diff: app/surface/transport_dib_win.cc

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
Index: app/surface/transport_dib_win.cc
diff --git a/app/surface/transport_dib_win.cc b/app/surface/transport_dib_win.cc
index f7746e34d875ad6354327e1ca1ee8115fd4b0653..f1707862a5a9b49921fad40e373f1fc8f75abb48 100644
--- a/app/surface/transport_dib_win.cc
+++ b/app/surface/transport_dib_win.cc
@@ -2,15 +2,74 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include <limits>
#include <windows.h>
+#include <limits>
+
#include "app/surface/transport_dib.h"
#include "base/logging.h"
+#include "base/scoped_handle_win.h"
#include "base/scoped_ptr.h"
#include "base/sys_info.h"
#include "skia/ext/platform_canvas.h"
+TransportDIB::Handle TransportDIB::Handle::DupForProcess(
+ base::ProcessHandle new_owner_process) const {
+ base::ProcessId new_owner_id = ::GetProcessId(new_owner_process);
+ if (!new_owner_id) {
+ LOG(WARNING) << "Could not get process id from handle"
+ << " handle:" << new_owner_process
+ << " error:" << ::GetLastError();
+ return Handle();
+ }
+ HANDLE owner_process = ::OpenProcess(PROCESS_DUP_HANDLE, FALSE, owner_id_);
+ if (!owner_process) {
+ LOG(WARNING) << "Could not open process"
+ << " id:" << owner_id_
+ << " error:" << ::GetLastError();
+ return Handle();
+ }
+ ::ScopedHandle scoped_owner_process(owner_process);
+ HANDLE new_section = NULL;
+ ::DuplicateHandle(owner_process, section_,
+ new_owner_process, &new_section,
+ STANDARD_RIGHTS_REQUIRED | FILE_MAP_ALL_ACCESS,
+ FALSE, 0);
+ if (!new_section) {
+ LOG(WARNING) << "Could not duplicate handle for process"
+ << " error:" << ::GetLastError();
+ return Handle();
+ }
+ return Handle(new_section, new_owner_id, false);
+}
+
+void TransportDIB::Handle::Close() const {
+ // Do not close this handle if it is invalid, or it has not been duped yet.
+ if (!is_valid() || should_dup_on_map_)
+ return;
+
+ // The handle was already duped for a target process, so we should close it.
+ // The target process may not have been us, so close using
+ // |::DuplicateHandle|.
+ HANDLE owner_process = ::OpenProcess(PROCESS_DUP_HANDLE, FALSE, owner_id_);
+ if (!owner_process) {
+ LOG(WARNING) << "Could not open process"
+ << " id:" << owner_id_
+ << " error:" << ::GetLastError();
+ return;
+ }
+ if (!::DuplicateHandle(owner_process, section_,
+ NULL, NULL,
+ DUPLICATE_CLOSE_SOURCE,
+ FALSE, 0)) {
+ NOTREACHED() << "Handle could not be closed: " << ::GetLastError();
+ }
+}
+
+void TransportDIB::ScopedHandle::Close() {
+ handle_.Close();
+}
+
TransportDIB::TransportDIB() {
}
@@ -42,44 +101,73 @@ TransportDIB* TransportDIB::Create(size_t size, uint32 sequence_num) {
}
// static
-TransportDIB* TransportDIB::Map(TransportDIB::Handle handle) {
- TransportDIB* dib = new TransportDIB(handle);
- if (!dib->shared_memory_.Map(0 /* map whole shared memory segment */)) {
- LOG(ERROR) << "Failed to map transport DIB"
- << " handle:" << handle
- << " error:" << GetLastError();
- delete dib;
+TransportDIB* TransportDIB::Map(Handle handle) {
+ scoped_ptr<TransportDIB> dib(CreateWithHandle(handle));
+ if (!dib->Map())
return NULL;
- }
-
- // There doesn't seem to be any way to find the size of the shared memory
- // region! GetFileSize indicates that the handle is invalid. Thus, we
- // conservatively set the size to the maximum and hope that the renderer
- // isn't about to ask us to read off the end of the array.
- dib->size_ = std::numeric_limits<size_t>::max();
+ return dib.release();
+}
- return dib;
+// static
+TransportDIB* TransportDIB::CreateWithHandle(Handle handle) {
+ // It is not sufficient to compare the current process ID and the ID in the
+ // handle here to see if a duplication is required because they will always
+ // be the same in single process mode.
+ if (handle.should_dup_on_map())
+ handle = handle.DupForProcess(::GetCurrentProcess());
+ return new TransportDIB(handle.section());
}
+// static
bool TransportDIB::is_valid(Handle dib) {
- return dib != NULL;
+ return dib.is_valid();
}
skia::PlatformCanvas* TransportDIB::GetPlatformCanvas(int w, int h) {
+ // This DIB already mapped the file into this process, but PlatformCanvas
+ // will map it again.
+ DCHECK(!memory()) << "Mapped file twice in the same process.";
+
scoped_ptr<skia::PlatformCanvas> canvas(new skia::PlatformCanvas);
- if (!canvas->initialize(w, h, true, handle()))
+ if (!canvas->initialize(w, h, true, shared_memory_.handle()))
return NULL;
return canvas.release();
}
+bool TransportDIB::Map() {
+ if (memory())
+ return true;
+
+ if (!shared_memory_.Map(0 /* map whole shared memory segment */)) {
+ LOG(ERROR) << "Failed to map transport DIB"
+ << " handle:" << shared_memory_.handle()
+ << " error:" << ::GetLastError();
+ return false;
+ }
+
+ // There doesn't seem to be any way to find the size of the shared memory
+ // region! GetFileSize indicates that the handle is invalid. Thus, we
+ // conservatively set the size to the maximum and hope that the renderer
+ // isn't about to ask us to read off the end of the array.
+ size_ = std::numeric_limits<size_t>::max();
+ return true;
+}
+
+TransportDIB::Handle TransportDIB::GetHandleForProcess(
+ base::ProcessHandle process_handle) const {
+ return handle().DupForProcess(process_handle);
+}
+
void* TransportDIB::memory() const {
return shared_memory_.memory();
}
TransportDIB::Handle TransportDIB::handle() const {
- return shared_memory_.handle();
+ return TransferrableSectionHandle(shared_memory_.handle(),
+ ::GetCurrentProcessId(),
+ true);
}
TransportDIB::Id TransportDIB::id() const {
- return Id(shared_memory_.handle(), sequence_num_);
+ return sequence_num_;
}

Powered by Google App Engine
This is Rietveld 408576698