Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
michael@0 | 1 | // Copyright (c) 2007, Google Inc. |
michael@0 | 2 | // All rights reserved. |
michael@0 | 3 | // |
michael@0 | 4 | // Redistribution and use in source and binary forms, with or without |
michael@0 | 5 | // modification, are permitted provided that the following conditions are |
michael@0 | 6 | // met: |
michael@0 | 7 | // |
michael@0 | 8 | // * Redistributions of source code must retain the above copyright |
michael@0 | 9 | // notice, this list of conditions and the following disclaimer. |
michael@0 | 10 | // * Redistributions in binary form must reproduce the above |
michael@0 | 11 | // copyright notice, this list of conditions and the following disclaimer |
michael@0 | 12 | // in the documentation and/or other materials provided with the |
michael@0 | 13 | // distribution. |
michael@0 | 14 | // * Neither the name of Google Inc. nor the names of its |
michael@0 | 15 | // contributors may be used to endorse or promote products derived from |
michael@0 | 16 | // this software without specific prior written permission. |
michael@0 | 17 | // |
michael@0 | 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
michael@0 | 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
michael@0 | 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
michael@0 | 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
michael@0 | 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
michael@0 | 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
michael@0 | 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
michael@0 | 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
michael@0 | 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
michael@0 | 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
michael@0 | 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
michael@0 | 29 | // |
michael@0 | 30 | // MachIPC.mm |
michael@0 | 31 | // Wrapper for mach IPC calls |
michael@0 | 32 | |
michael@0 | 33 | #import <stdio.h> |
michael@0 | 34 | #import "MachIPC.h" |
michael@0 | 35 | #include "common/mac/bootstrap_compat.h" |
michael@0 | 36 | |
michael@0 | 37 | namespace google_breakpad { |
michael@0 | 38 | //============================================================================== |
michael@0 | 39 | MachSendMessage::MachSendMessage(int32_t message_id) : MachMessage() { |
michael@0 | 40 | head.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0); |
michael@0 | 41 | |
michael@0 | 42 | // head.msgh_remote_port = ...; // filled out in MachPortSender::SendMessage() |
michael@0 | 43 | head.msgh_local_port = MACH_PORT_NULL; |
michael@0 | 44 | head.msgh_reserved = 0; |
michael@0 | 45 | head.msgh_id = 0; |
michael@0 | 46 | |
michael@0 | 47 | SetDescriptorCount(0); // start out with no descriptors |
michael@0 | 48 | |
michael@0 | 49 | SetMessageID(message_id); |
michael@0 | 50 | SetData(NULL, 0); // client may add data later |
michael@0 | 51 | } |
michael@0 | 52 | |
michael@0 | 53 | //============================================================================== |
michael@0 | 54 | // returns true if successful |
michael@0 | 55 | bool MachMessage::SetData(void *data, |
michael@0 | 56 | int32_t data_length) { |
michael@0 | 57 | // first check to make sure we have enough space |
michael@0 | 58 | size_t size = CalculateSize(); |
michael@0 | 59 | size_t new_size = size + data_length; |
michael@0 | 60 | |
michael@0 | 61 | if (new_size > sizeof(MachMessage)) { |
michael@0 | 62 | return false; // not enough space |
michael@0 | 63 | } |
michael@0 | 64 | |
michael@0 | 65 | GetDataPacket()->data_length = EndianU32_NtoL(data_length); |
michael@0 | 66 | if (data) memcpy(GetDataPacket()->data, data, data_length); |
michael@0 | 67 | |
michael@0 | 68 | CalculateSize(); |
michael@0 | 69 | |
michael@0 | 70 | return true; |
michael@0 | 71 | } |
michael@0 | 72 | |
michael@0 | 73 | //============================================================================== |
michael@0 | 74 | // calculates and returns the total size of the message |
michael@0 | 75 | // Currently, the entire message MUST fit inside of the MachMessage |
michael@0 | 76 | // messsage size <= sizeof(MachMessage) |
michael@0 | 77 | mach_msg_size_t MachMessage::CalculateSize() { |
michael@0 | 78 | size_t size = sizeof(mach_msg_header_t) + sizeof(mach_msg_body_t); |
michael@0 | 79 | |
michael@0 | 80 | // add space for MessageDataPacket |
michael@0 | 81 | int32_t alignedDataLength = (GetDataLength() + 3) & ~0x3; |
michael@0 | 82 | size += 2*sizeof(int32_t) + alignedDataLength; |
michael@0 | 83 | |
michael@0 | 84 | // add space for descriptors |
michael@0 | 85 | size += GetDescriptorCount() * sizeof(MachMsgPortDescriptor); |
michael@0 | 86 | |
michael@0 | 87 | head.msgh_size = static_cast<mach_msg_size_t>(size); |
michael@0 | 88 | |
michael@0 | 89 | return head.msgh_size; |
michael@0 | 90 | } |
michael@0 | 91 | |
michael@0 | 92 | //============================================================================== |
michael@0 | 93 | MachMessage::MessageDataPacket *MachMessage::GetDataPacket() { |
michael@0 | 94 | size_t desc_size = sizeof(MachMsgPortDescriptor)*GetDescriptorCount(); |
michael@0 | 95 | MessageDataPacket *packet = |
michael@0 | 96 | reinterpret_cast<MessageDataPacket*>(padding + desc_size); |
michael@0 | 97 | |
michael@0 | 98 | return packet; |
michael@0 | 99 | } |
michael@0 | 100 | |
michael@0 | 101 | //============================================================================== |
michael@0 | 102 | void MachMessage::SetDescriptor(int n, |
michael@0 | 103 | const MachMsgPortDescriptor &desc) { |
michael@0 | 104 | MachMsgPortDescriptor *desc_array = |
michael@0 | 105 | reinterpret_cast<MachMsgPortDescriptor*>(padding); |
michael@0 | 106 | desc_array[n] = desc; |
michael@0 | 107 | } |
michael@0 | 108 | |
michael@0 | 109 | //============================================================================== |
michael@0 | 110 | // returns true if successful otherwise there was not enough space |
michael@0 | 111 | bool MachMessage::AddDescriptor(const MachMsgPortDescriptor &desc) { |
michael@0 | 112 | // first check to make sure we have enough space |
michael@0 | 113 | int size = CalculateSize(); |
michael@0 | 114 | size_t new_size = size + sizeof(MachMsgPortDescriptor); |
michael@0 | 115 | |
michael@0 | 116 | if (new_size > sizeof(MachMessage)) { |
michael@0 | 117 | return false; // not enough space |
michael@0 | 118 | } |
michael@0 | 119 | |
michael@0 | 120 | // unfortunately, we need to move the data to allow space for the |
michael@0 | 121 | // new descriptor |
michael@0 | 122 | u_int8_t *p = reinterpret_cast<u_int8_t*>(GetDataPacket()); |
michael@0 | 123 | bcopy(p, p+sizeof(MachMsgPortDescriptor), GetDataLength()+2*sizeof(int32_t)); |
michael@0 | 124 | |
michael@0 | 125 | SetDescriptor(GetDescriptorCount(), desc); |
michael@0 | 126 | SetDescriptorCount(GetDescriptorCount() + 1); |
michael@0 | 127 | |
michael@0 | 128 | CalculateSize(); |
michael@0 | 129 | |
michael@0 | 130 | return true; |
michael@0 | 131 | } |
michael@0 | 132 | |
michael@0 | 133 | //============================================================================== |
michael@0 | 134 | void MachMessage::SetDescriptorCount(int n) { |
michael@0 | 135 | body.msgh_descriptor_count = n; |
michael@0 | 136 | |
michael@0 | 137 | if (n > 0) { |
michael@0 | 138 | head.msgh_bits |= MACH_MSGH_BITS_COMPLEX; |
michael@0 | 139 | } else { |
michael@0 | 140 | head.msgh_bits &= ~MACH_MSGH_BITS_COMPLEX; |
michael@0 | 141 | } |
michael@0 | 142 | } |
michael@0 | 143 | |
michael@0 | 144 | //============================================================================== |
michael@0 | 145 | MachMsgPortDescriptor *MachMessage::GetDescriptor(int n) { |
michael@0 | 146 | if (n < GetDescriptorCount()) { |
michael@0 | 147 | MachMsgPortDescriptor *desc = |
michael@0 | 148 | reinterpret_cast<MachMsgPortDescriptor*>(padding); |
michael@0 | 149 | return desc + n; |
michael@0 | 150 | } |
michael@0 | 151 | |
michael@0 | 152 | return nil; |
michael@0 | 153 | } |
michael@0 | 154 | |
michael@0 | 155 | //============================================================================== |
michael@0 | 156 | mach_port_t MachMessage::GetTranslatedPort(int n) { |
michael@0 | 157 | if (n < GetDescriptorCount()) { |
michael@0 | 158 | return GetDescriptor(n)->GetMachPort(); |
michael@0 | 159 | } |
michael@0 | 160 | return MACH_PORT_NULL; |
michael@0 | 161 | } |
michael@0 | 162 | |
michael@0 | 163 | #pragma mark - |
michael@0 | 164 | |
michael@0 | 165 | //============================================================================== |
michael@0 | 166 | // create a new mach port for receiving messages and register a name for it |
michael@0 | 167 | ReceivePort::ReceivePort(const char *receive_port_name) { |
michael@0 | 168 | mach_port_t current_task = mach_task_self(); |
michael@0 | 169 | |
michael@0 | 170 | init_result_ = mach_port_allocate(current_task, |
michael@0 | 171 | MACH_PORT_RIGHT_RECEIVE, |
michael@0 | 172 | &port_); |
michael@0 | 173 | |
michael@0 | 174 | if (init_result_ != KERN_SUCCESS) |
michael@0 | 175 | return; |
michael@0 | 176 | |
michael@0 | 177 | init_result_ = mach_port_insert_right(current_task, |
michael@0 | 178 | port_, |
michael@0 | 179 | port_, |
michael@0 | 180 | MACH_MSG_TYPE_MAKE_SEND); |
michael@0 | 181 | |
michael@0 | 182 | if (init_result_ != KERN_SUCCESS) |
michael@0 | 183 | return; |
michael@0 | 184 | |
michael@0 | 185 | mach_port_t task_bootstrap_port = 0; |
michael@0 | 186 | init_result_ = task_get_bootstrap_port(current_task, &task_bootstrap_port); |
michael@0 | 187 | |
michael@0 | 188 | if (init_result_ != KERN_SUCCESS) |
michael@0 | 189 | return; |
michael@0 | 190 | |
michael@0 | 191 | init_result_ = breakpad::BootstrapRegister( |
michael@0 | 192 | bootstrap_port, |
michael@0 | 193 | const_cast<char*>(receive_port_name), |
michael@0 | 194 | port_); |
michael@0 | 195 | } |
michael@0 | 196 | |
michael@0 | 197 | //============================================================================== |
michael@0 | 198 | // create a new mach port for receiving messages |
michael@0 | 199 | ReceivePort::ReceivePort() { |
michael@0 | 200 | mach_port_t current_task = mach_task_self(); |
michael@0 | 201 | |
michael@0 | 202 | init_result_ = mach_port_allocate(current_task, |
michael@0 | 203 | MACH_PORT_RIGHT_RECEIVE, |
michael@0 | 204 | &port_); |
michael@0 | 205 | |
michael@0 | 206 | if (init_result_ != KERN_SUCCESS) |
michael@0 | 207 | return; |
michael@0 | 208 | |
michael@0 | 209 | init_result_ = mach_port_insert_right(current_task, |
michael@0 | 210 | port_, |
michael@0 | 211 | port_, |
michael@0 | 212 | MACH_MSG_TYPE_MAKE_SEND); |
michael@0 | 213 | } |
michael@0 | 214 | |
michael@0 | 215 | //============================================================================== |
michael@0 | 216 | // Given an already existing mach port, use it. We take ownership of the |
michael@0 | 217 | // port and deallocate it in our destructor. |
michael@0 | 218 | ReceivePort::ReceivePort(mach_port_t receive_port) |
michael@0 | 219 | : port_(receive_port), |
michael@0 | 220 | init_result_(KERN_SUCCESS) { |
michael@0 | 221 | } |
michael@0 | 222 | |
michael@0 | 223 | //============================================================================== |
michael@0 | 224 | ReceivePort::~ReceivePort() { |
michael@0 | 225 | if (init_result_ == KERN_SUCCESS) |
michael@0 | 226 | mach_port_deallocate(mach_task_self(), port_); |
michael@0 | 227 | } |
michael@0 | 228 | |
michael@0 | 229 | //============================================================================== |
michael@0 | 230 | kern_return_t ReceivePort::WaitForMessage(MachReceiveMessage *out_message, |
michael@0 | 231 | mach_msg_timeout_t timeout) { |
michael@0 | 232 | if (!out_message) { |
michael@0 | 233 | return KERN_INVALID_ARGUMENT; |
michael@0 | 234 | } |
michael@0 | 235 | |
michael@0 | 236 | // return any error condition encountered in constructor |
michael@0 | 237 | if (init_result_ != KERN_SUCCESS) |
michael@0 | 238 | return init_result_; |
michael@0 | 239 | |
michael@0 | 240 | out_message->head.msgh_bits = 0; |
michael@0 | 241 | out_message->head.msgh_local_port = port_; |
michael@0 | 242 | out_message->head.msgh_remote_port = MACH_PORT_NULL; |
michael@0 | 243 | out_message->head.msgh_reserved = 0; |
michael@0 | 244 | out_message->head.msgh_id = 0; |
michael@0 | 245 | |
michael@0 | 246 | mach_msg_option_t options = MACH_RCV_MSG; |
michael@0 | 247 | if (timeout != MACH_MSG_TIMEOUT_NONE) |
michael@0 | 248 | options |= MACH_RCV_TIMEOUT; |
michael@0 | 249 | kern_return_t result = mach_msg(&out_message->head, |
michael@0 | 250 | options, |
michael@0 | 251 | 0, |
michael@0 | 252 | sizeof(MachMessage), |
michael@0 | 253 | port_, |
michael@0 | 254 | timeout, // timeout in ms |
michael@0 | 255 | MACH_PORT_NULL); |
michael@0 | 256 | |
michael@0 | 257 | return result; |
michael@0 | 258 | } |
michael@0 | 259 | |
michael@0 | 260 | #pragma mark - |
michael@0 | 261 | |
michael@0 | 262 | //============================================================================== |
michael@0 | 263 | // get a port with send rights corresponding to a named registered service |
michael@0 | 264 | MachPortSender::MachPortSender(const char *receive_port_name) { |
michael@0 | 265 | mach_port_t task_bootstrap_port = 0; |
michael@0 | 266 | init_result_ = task_get_bootstrap_port(mach_task_self(), |
michael@0 | 267 | &task_bootstrap_port); |
michael@0 | 268 | |
michael@0 | 269 | if (init_result_ != KERN_SUCCESS) |
michael@0 | 270 | return; |
michael@0 | 271 | |
michael@0 | 272 | init_result_ = bootstrap_look_up(task_bootstrap_port, |
michael@0 | 273 | const_cast<char*>(receive_port_name), |
michael@0 | 274 | &send_port_); |
michael@0 | 275 | } |
michael@0 | 276 | |
michael@0 | 277 | //============================================================================== |
michael@0 | 278 | MachPortSender::MachPortSender(mach_port_t send_port) |
michael@0 | 279 | : send_port_(send_port), |
michael@0 | 280 | init_result_(KERN_SUCCESS) { |
michael@0 | 281 | } |
michael@0 | 282 | |
michael@0 | 283 | //============================================================================== |
michael@0 | 284 | kern_return_t MachPortSender::SendMessage(MachSendMessage &message, |
michael@0 | 285 | mach_msg_timeout_t timeout) { |
michael@0 | 286 | if (message.head.msgh_size == 0) { |
michael@0 | 287 | return KERN_INVALID_VALUE; // just for safety -- never should occur |
michael@0 | 288 | }; |
michael@0 | 289 | |
michael@0 | 290 | if (init_result_ != KERN_SUCCESS) |
michael@0 | 291 | return init_result_; |
michael@0 | 292 | |
michael@0 | 293 | message.head.msgh_remote_port = send_port_; |
michael@0 | 294 | |
michael@0 | 295 | kern_return_t result = mach_msg(&message.head, |
michael@0 | 296 | MACH_SEND_MSG | MACH_SEND_TIMEOUT, |
michael@0 | 297 | message.head.msgh_size, |
michael@0 | 298 | 0, |
michael@0 | 299 | MACH_PORT_NULL, |
michael@0 | 300 | timeout, // timeout in ms |
michael@0 | 301 | MACH_PORT_NULL); |
michael@0 | 302 | |
michael@0 | 303 | return result; |
michael@0 | 304 | } |
michael@0 | 305 | |
michael@0 | 306 | } // namespace google_breakpad |