toolkit/components/osfile/modules/osfile_win_allthreads.jsm

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

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

mercurial