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.
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
5 /**
6 * This module defines the thread-agnostic components of the Win version
7 * of OS.File. It depends on the thread-agnostic cross-platform components
8 * of OS.File.
9 *
10 * It serves the following purposes:
11 * - open kernel32;
12 * - define OS.Shared.Win.Error;
13 * - define a few constants and types that need to be defined on all platforms.
14 *
15 * This module can be:
16 * - opened from the main thread as a jsm module;
17 * - opened from a chrome worker through require().
18 */
20 "use strict";
22 let SharedAll;
23 if (typeof Components != "undefined") {
24 let Cu = Components.utils;
25 // Module is opened as a jsm module
26 Cu.import("resource://gre/modules/ctypes.jsm", this);
28 SharedAll = {};
29 Cu.import("resource://gre/modules/osfile/osfile_shared_allthreads.jsm", SharedAll);
30 this.exports = {};
31 } else if (typeof "module" != "undefined" && typeof "require" != "undefined") {
32 // Module is loaded with require()
33 SharedAll = require("resource://gre/modules/osfile/osfile_shared_allthreads.jsm");
34 } else {
35 throw new Error("Please open this module with Component.utils.import or with require()");
36 }
38 let LOG = SharedAll.LOG.bind(SharedAll, "Win", "allthreads");
39 let Const = SharedAll.Constants.Win;
41 // Open libc
42 let libc = new SharedAll.Library("libc", "kernel32.dll");
43 exports.libc = libc;
45 // Define declareFFI
46 let declareFFI = SharedAll.declareFFI.bind(null, libc);
47 exports.declareFFI = declareFFI;
49 let Scope = {};
51 // Define Error
52 libc.declareLazy(Scope, "FormatMessage",
53 "FormatMessageW", ctypes.winapi_abi,
54 /*return*/ ctypes.uint32_t,
55 /*flags*/ ctypes.uint32_t,
56 /*source*/ ctypes.voidptr_t,
57 /*msgid*/ ctypes.uint32_t,
58 /*langid*/ ctypes.uint32_t,
59 /*buf*/ ctypes.jschar.ptr,
60 /*size*/ ctypes.uint32_t,
61 /*Arguments*/ctypes.voidptr_t);
63 /**
64 * A File-related error.
65 *
66 * To obtain a human-readable error message, use method |toString|.
67 * To determine the cause of the error, use the various |becauseX|
68 * getters. To determine the operation that failed, use field
69 * |operation|.
70 *
71 * Additionally, this implementation offers a field
72 * |winLastError|, which holds the OS-specific error
73 * constant. If you need this level of detail, you may match the value
74 * of this field against the error constants of |OS.Constants.Win|.
75 *
76 * @param {string=} operation The operation that failed. If unspecified,
77 * the name of the calling function is taken to be the operation that
78 * failed.
79 * @param {number=} lastError The OS-specific constant detailing the
80 * reason of the error. If unspecified, this is fetched from the system
81 * status.
82 * @param {string=} path The file path that manipulated. If unspecified,
83 * assign the empty string.
84 *
85 * @constructor
86 * @extends {OS.Shared.Error}
87 */
88 let OSError = function OSError(operation = "unknown operation",
89 lastError = ctypes.winLastError, path = "") {
90 operation = operation;
91 SharedAll.OSError.call(this, operation, path);
92 this.winLastError = lastError;
93 };
94 OSError.prototype = Object.create(SharedAll.OSError.prototype);
95 OSError.prototype.toString = function toString() {
96 let buf = new (ctypes.ArrayType(ctypes.jschar, 1024))();
97 let result = Scope.FormatMessage(
98 Const.FORMAT_MESSAGE_FROM_SYSTEM |
99 Const.FORMAT_MESSAGE_IGNORE_INSERTS,
100 null,
101 /* The error number */ this.winLastError,
102 /* Default language */ 0,
103 /* Output buffer*/ buf,
104 /* Minimum size of buffer */ 1024,
105 /* Format args*/ null
106 );
107 if (!result) {
108 buf = "additional error " +
109 ctypes.winLastError +
110 " while fetching system error message";
111 }
112 return "Win error " + this.winLastError + " during operation "
113 + this.operation + (this.path? " on file " + this.path : "") +
114 " (" + buf.readString() + ")";
115 };
117 /**
118 * |true| if the error was raised because a file or directory
119 * already exists, |false| otherwise.
120 */
121 Object.defineProperty(OSError.prototype, "becauseExists", {
122 get: function becauseExists() {
123 return this.winLastError == Const.ERROR_FILE_EXISTS ||
124 this.winLastError == Const.ERROR_ALREADY_EXISTS;
125 }
126 });
127 /**
128 * |true| if the error was raised because a file or directory
129 * does not exist, |false| otherwise.
130 */
131 Object.defineProperty(OSError.prototype, "becauseNoSuchFile", {
132 get: function becauseNoSuchFile() {
133 return this.winLastError == Const.ERROR_FILE_NOT_FOUND ||
134 this.winLastError == Const.ERROR_PATH_NOT_FOUND;
135 }
136 });
137 /**
138 * |true| if the error was raised because a directory is not empty
139 * does not exist, |false| otherwise.
140 */
141 Object.defineProperty(OSError.prototype, "becauseNotEmpty", {
142 get: function becauseNotEmpty() {
143 return this.winLastError == Const.ERROR_DIR_NOT_EMPTY;
144 }
145 });
146 /**
147 * |true| if the error was raised because a file or directory
148 * is closed, |false| otherwise.
149 */
150 Object.defineProperty(OSError.prototype, "becauseClosed", {
151 get: function becauseClosed() {
152 return this.winLastError == Const.ERROR_INVALID_HANDLE;
153 }
154 });
155 /**
156 * |true| if the error was raised because permission is denied to
157 * access a file or directory, |false| otherwise.
158 */
159 Object.defineProperty(OSError.prototype, "becauseAccessDenied", {
160 get: function becauseAccessDenied() {
161 return this.winLastError == Const.ERROR_ACCESS_DENIED;
162 }
163 });
164 /**
165 * |true| if the error was raised because some invalid argument was passed,
166 * |false| otherwise.
167 */
168 Object.defineProperty(OSError.prototype, "becauseInvalidArgument", {
169 get: function becauseInvalidArgument() {
170 return this.winLastError == Const.ERROR_NOT_SUPPORTED ||
171 this.winLastError == Const.ERROR_BAD_ARGUMENTS;
172 }
173 });
175 /**
176 * Serialize an instance of OSError to something that can be
177 * transmitted across threads (not necessarily a string).
178 */
179 OSError.toMsg = function toMsg(error) {
180 return {
181 operation: error.operation,
182 winLastError: error.winLastError,
183 path: error.path
184 };
185 };
187 /**
188 * Deserialize a message back to an instance of OSError
189 */
190 OSError.fromMsg = function fromMsg(msg) {
191 return new OSError(msg.operation, msg.winLastError, msg.path);
192 };
193 exports.Error = OSError;
195 /**
196 * Code shared by implementation of File.Info on Windows
197 *
198 * @constructor
199 */
200 let AbstractInfo = function AbstractInfo(path, isDir, isSymLink, size,
201 winBirthDate,
202 lastAccessDate, lastWriteDate) {
203 this._path = path;
204 this._isDir = isDir;
205 this._isSymLink = isSymLink;
206 this._size = size;
207 this._winBirthDate = winBirthDate;
208 this._lastAccessDate = lastAccessDate;
209 this._lastModificationDate = lastWriteDate;
210 };
212 AbstractInfo.prototype = {
213 /**
214 * The path of the file, used for error-reporting.
215 *
216 * @type {string}
217 */
218 get path() {
219 return this._path;
220 },
221 /**
222 * |true| if this file is a directory, |false| otherwise
223 */
224 get isDir() {
225 return this._isDir;
226 },
227 /**
228 * |true| if this file is a symbolic link, |false| otherwise
229 */
230 get isSymLink() {
231 return this._isSymLink;
232 },
233 /**
234 * The size of the file, in bytes.
235 *
236 * Note that the result may be |NaN| if the size of the file cannot be
237 * represented in JavaScript.
238 *
239 * @type {number}
240 */
241 get size() {
242 return this._size;
243 },
244 // Deprecated
245 get creationDate() {
246 return this._winBirthDate;
247 },
248 /**
249 * The date of creation of this file.
250 *
251 * @type {Date}
252 */
253 get winBirthDate() {
254 return this._winBirthDate;
255 },
256 /**
257 * The date of last access to this file.
258 *
259 * Note that the definition of last access may depend on the underlying
260 * operating system and file system.
261 *
262 * @type {Date}
263 */
264 get lastAccessDate() {
265 return this._lastAccessDate;
266 },
267 /**
268 * The date of last modification of this file.
269 *
270 * Note that the definition of last access may depend on the underlying
271 * operating system and file system.
272 *
273 * @type {Date}
274 */
275 get lastModificationDate() {
276 return this._lastModificationDate;
277 }
278 };
279 exports.AbstractInfo = AbstractInfo;
281 /**
282 * Code shared by implementation of File.DirectoryIterator.Entry on Windows
283 *
284 * @constructor
285 */
286 let AbstractEntry = function AbstractEntry(isDir, isSymLink, name,
287 winCreationDate, winLastWriteDate,
288 winLastAccessDate, path) {
289 this._isDir = isDir;
290 this._isSymLink = isSymLink;
291 this._name = name;
292 this._winCreationDate = winCreationDate;
293 this._winLastWriteDate = winLastWriteDate;
294 this._winLastAccessDate = winLastAccessDate;
295 this._path = path;
296 };
298 AbstractEntry.prototype = {
299 /**
300 * |true| if the entry is a directory, |false| otherwise
301 */
302 get isDir() {
303 return this._isDir;
304 },
305 /**
306 * |true| if the entry is a symbolic link, |false| otherwise
307 */
308 get isSymLink() {
309 return this._isSymLink;
310 },
311 /**
312 * The name of the entry.
313 * @type {string}
314 */
315 get name() {
316 return this._name;
317 },
318 /**
319 * The creation time of this file.
320 * @type {Date}
321 */
322 get winCreationDate() {
323 return this._winCreationDate;
324 },
325 /**
326 * The last modification time of this file.
327 * @type {Date}
328 */
329 get winLastWriteDate() {
330 return this._winLastWriteDate;
331 },
332 /**
333 * The last access time of this file.
334 * @type {Date}
335 */
336 get winLastAccessDate() {
337 return this._winLastAccessDate;
338 },
339 /**
340 * The full path of the entry
341 * @type {string}
342 */
343 get path() {
344 return this._path;
345 }
346 };
347 exports.AbstractEntry = AbstractEntry;
349 // Special constants that need to be defined on all platforms
351 exports.POS_START = Const.FILE_BEGIN;
352 exports.POS_CURRENT = Const.FILE_CURRENT;
353 exports.POS_END = Const.FILE_END;
355 // Special types that need to be defined for communication
356 // between threads
357 let Type = Object.create(SharedAll.Type);
358 exports.Type = Type;
360 /**
361 * Native paths
362 *
363 * Under Windows, expressed as wide strings
364 */
365 Type.path = Type.wstring.withName("[in] path");
366 Type.out_path = Type.out_wstring.withName("[out] path");
368 // Special constructors that need to be defined on all threads
369 OSError.closed = function closed(operation, path) {
370 return new OSError(operation, Const.ERROR_INVALID_HANDLE, path);
371 };
373 OSError.exists = function exists(operation, path) {
374 return new OSError(operation, Const.ERROR_FILE_EXISTS, path);
375 };
377 OSError.noSuchFile = function noSuchFile(operation, path) {
378 return new OSError(operation, Const.ERROR_FILE_NOT_FOUND, path);
379 };
381 OSError.invalidArgument = function invalidArgument(operation) {
382 return new OSError(operation, Const.ERROR_NOT_SUPPORTED);
383 };
385 let EXPORTED_SYMBOLS = [
386 "declareFFI",
387 "libc",
388 "Error",
389 "AbstractInfo",
390 "AbstractEntry",
391 "Type",
392 "POS_START",
393 "POS_CURRENT",
394 "POS_END"
395 ];
397 //////////// Boilerplate
398 if (typeof Components != "undefined") {
399 this.EXPORTED_SYMBOLS = EXPORTED_SYMBOLS;
400 for (let symbol of EXPORTED_SYMBOLS) {
401 this[symbol] = exports[symbol];
402 }
403 }