OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
| 5 #include <windows.h> |
| 6 |
5 #include <limits> | 7 #include <limits> |
6 #include <windows.h> | |
7 | 8 |
8 #include "app/surface/transport_dib.h" | 9 #include "app/surface/transport_dib.h" |
9 #include "base/logging.h" | 10 #include "base/logging.h" |
| 11 #include "base/scoped_handle_win.h" |
10 #include "base/scoped_ptr.h" | 12 #include "base/scoped_ptr.h" |
11 #include "base/sys_info.h" | 13 #include "base/sys_info.h" |
12 #include "skia/ext/platform_canvas.h" | 14 #include "skia/ext/platform_canvas.h" |
13 | 15 |
| 16 TransportDIB::Handle TransportDIB::Handle::DupForProcess( |
| 17 base::ProcessHandle new_owner_process) const { |
| 18 base::ProcessId new_owner_id = ::GetProcessId(new_owner_process); |
| 19 if (!new_owner_id) { |
| 20 LOG(WARNING) << "Could not get process id from handle" |
| 21 << " handle:" << new_owner_process |
| 22 << " error:" << ::GetLastError(); |
| 23 return Handle(); |
| 24 } |
| 25 HANDLE owner_process = ::OpenProcess(PROCESS_DUP_HANDLE, FALSE, owner_id_); |
| 26 if (!owner_process) { |
| 27 LOG(WARNING) << "Could not open process" |
| 28 << " id:" << owner_id_ |
| 29 << " error:" << ::GetLastError(); |
| 30 return Handle(); |
| 31 } |
| 32 ::ScopedHandle scoped_owner_process(owner_process); |
| 33 HANDLE new_section = NULL; |
| 34 ::DuplicateHandle(owner_process, section_, |
| 35 new_owner_process, &new_section, |
| 36 STANDARD_RIGHTS_REQUIRED | FILE_MAP_ALL_ACCESS, |
| 37 FALSE, 0); |
| 38 if (!new_section) { |
| 39 LOG(WARNING) << "Could not duplicate handle for process" |
| 40 << " error:" << ::GetLastError(); |
| 41 return Handle(); |
| 42 } |
| 43 return Handle(new_section, new_owner_id, false); |
| 44 } |
| 45 |
| 46 void TransportDIB::Handle::Close() const { |
| 47 // Do not close this handle if it is invalid, or it has not been duped yet. |
| 48 if (!is_valid() || should_dup_on_map_) |
| 49 return; |
| 50 |
| 51 // The handle was already duped for a target process, so we should close it. |
| 52 // The target process may not have been us, so close using |
| 53 // |::DuplicateHandle|. |
| 54 HANDLE owner_process = ::OpenProcess(PROCESS_DUP_HANDLE, FALSE, owner_id_); |
| 55 if (!owner_process) { |
| 56 LOG(WARNING) << "Could not open process" |
| 57 << " id:" << owner_id_ |
| 58 << " error:" << ::GetLastError(); |
| 59 return; |
| 60 } |
| 61 if (!::DuplicateHandle(owner_process, section_, |
| 62 NULL, NULL, |
| 63 DUPLICATE_CLOSE_SOURCE, |
| 64 FALSE, 0)) { |
| 65 NOTREACHED() << "Handle could not be closed: " << ::GetLastError(); |
| 66 } |
| 67 } |
| 68 |
| 69 void TransportDIB::ScopedHandle::Close() { |
| 70 handle_.Close(); |
| 71 } |
| 72 |
14 TransportDIB::TransportDIB() { | 73 TransportDIB::TransportDIB() { |
15 } | 74 } |
16 | 75 |
17 TransportDIB::~TransportDIB() { | 76 TransportDIB::~TransportDIB() { |
18 } | 77 } |
19 | 78 |
20 TransportDIB::TransportDIB(HANDLE handle) | 79 TransportDIB::TransportDIB(HANDLE handle) |
21 : shared_memory_(handle, false /* read write */) { | 80 : shared_memory_(handle, false /* read write */) { |
22 } | 81 } |
23 | 82 |
(...skipping 11 matching lines...) Expand all Loading... |
35 return NULL; | 94 return NULL; |
36 } | 95 } |
37 | 96 |
38 dib->size_ = size; | 97 dib->size_ = size; |
39 dib->sequence_num_ = sequence_num; | 98 dib->sequence_num_ = sequence_num; |
40 | 99 |
41 return dib; | 100 return dib; |
42 } | 101 } |
43 | 102 |
44 // static | 103 // static |
45 TransportDIB* TransportDIB::Map(TransportDIB::Handle handle) { | 104 TransportDIB* TransportDIB::Map(Handle handle) { |
46 TransportDIB* dib = new TransportDIB(handle); | 105 scoped_ptr<TransportDIB> dib(CreateWithHandle(handle)); |
47 if (!dib->shared_memory_.Map(0 /* map whole shared memory segment */)) { | 106 if (!dib->Map()) |
| 107 return NULL; |
| 108 return dib.release(); |
| 109 } |
| 110 |
| 111 // static |
| 112 TransportDIB* TransportDIB::CreateWithHandle(Handle handle) { |
| 113 // It is not sufficient to compare the current process ID and the ID in the |
| 114 // handle here to see if a duplication is required because they will always |
| 115 // be the same in single process mode. |
| 116 if (handle.should_dup_on_map()) |
| 117 handle = handle.DupForProcess(::GetCurrentProcess()); |
| 118 return new TransportDIB(handle.section()); |
| 119 } |
| 120 |
| 121 // static |
| 122 bool TransportDIB::is_valid(Handle dib) { |
| 123 return dib.is_valid(); |
| 124 } |
| 125 |
| 126 skia::PlatformCanvas* TransportDIB::GetPlatformCanvas(int w, int h) { |
| 127 // This DIB already mapped the file into this process, but PlatformCanvas |
| 128 // will map it again. |
| 129 DCHECK(!memory()) << "Mapped file twice in the same process."; |
| 130 |
| 131 scoped_ptr<skia::PlatformCanvas> canvas(new skia::PlatformCanvas); |
| 132 if (!canvas->initialize(w, h, true, shared_memory_.handle())) |
| 133 return NULL; |
| 134 return canvas.release(); |
| 135 } |
| 136 |
| 137 bool TransportDIB::Map() { |
| 138 if (memory()) |
| 139 return true; |
| 140 |
| 141 if (!shared_memory_.Map(0 /* map whole shared memory segment */)) { |
48 LOG(ERROR) << "Failed to map transport DIB" | 142 LOG(ERROR) << "Failed to map transport DIB" |
49 << " handle:" << handle | 143 << " handle:" << shared_memory_.handle() |
50 << " error:" << GetLastError(); | 144 << " error:" << ::GetLastError(); |
51 delete dib; | 145 return false; |
52 return NULL; | |
53 } | 146 } |
54 | 147 |
55 // There doesn't seem to be any way to find the size of the shared memory | 148 // There doesn't seem to be any way to find the size of the shared memory |
56 // region! GetFileSize indicates that the handle is invalid. Thus, we | 149 // region! GetFileSize indicates that the handle is invalid. Thus, we |
57 // conservatively set the size to the maximum and hope that the renderer | 150 // conservatively set the size to the maximum and hope that the renderer |
58 // isn't about to ask us to read off the end of the array. | 151 // isn't about to ask us to read off the end of the array. |
59 dib->size_ = std::numeric_limits<size_t>::max(); | 152 size_ = std::numeric_limits<size_t>::max(); |
60 | 153 return true; |
61 return dib; | |
62 } | 154 } |
63 | 155 |
64 bool TransportDIB::is_valid(Handle dib) { | 156 TransportDIB::Handle TransportDIB::GetHandleForProcess( |
65 return dib != NULL; | 157 base::ProcessHandle process_handle) const { |
66 } | 158 return handle().DupForProcess(process_handle); |
67 | |
68 skia::PlatformCanvas* TransportDIB::GetPlatformCanvas(int w, int h) { | |
69 scoped_ptr<skia::PlatformCanvas> canvas(new skia::PlatformCanvas); | |
70 if (!canvas->initialize(w, h, true, handle())) | |
71 return NULL; | |
72 return canvas.release(); | |
73 } | 159 } |
74 | 160 |
75 void* TransportDIB::memory() const { | 161 void* TransportDIB::memory() const { |
76 return shared_memory_.memory(); | 162 return shared_memory_.memory(); |
77 } | 163 } |
78 | 164 |
79 TransportDIB::Handle TransportDIB::handle() const { | 165 TransportDIB::Handle TransportDIB::handle() const { |
80 return shared_memory_.handle(); | 166 return TransferrableSectionHandle(shared_memory_.handle(), |
| 167 ::GetCurrentProcessId(), |
| 168 true); |
81 } | 169 } |
82 | 170 |
83 TransportDIB::Id TransportDIB::id() const { | 171 TransportDIB::Id TransportDIB::id() const { |
84 return Id(shared_memory_.handle(), sequence_num_); | 172 return sequence_num_; |
85 } | 173 } |
OLD | NEW |