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 "use strict";
7 const Cu = Components.utils;
8 const Cc = Components.classes;
9 const Ci = Components.interfaces;
11 this.EXPORTED_SYMBOLS = ["OperatorAppsRegistry"];
13 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
14 Cu.import("resource://gre/modules/FileUtils.jsm");
15 Cu.import("resource://gre/modules/Webapps.jsm");
16 Cu.import("resource://gre/modules/Services.jsm");
17 Cu.import("resource://gre/modules/osfile.jsm");
18 Cu.import("resource://gre/modules/AppsUtils.jsm");
19 Cu.import("resource://gre/modules/Task.jsm");
21 let Path = OS.Path;
23 #ifdef MOZ_B2G_RIL
24 XPCOMUtils.defineLazyServiceGetter(this, "iccProvider",
25 "@mozilla.org/ril/content-helper;1",
26 "nsIIccProvider");
27 #endif
29 function debug(aMsg) {
30 //dump("-*-*- OperatorApps.jsm : " + aMsg + "\n");
31 }
33 // Single Variant source dir will be set in PREF_SINGLE_VARIANT_DIR
34 // preference.
35 // if PREF_SINGLE_VARIANT_DIR does not exist or has not value, it will use (as
36 // single variant source) the value of
37 // DIRECTORY_NAME + "/" + SINGLE_VARIANT_SOURCE_DIR value instead.
38 // SINGLE_VARIANT_CONF_FILE will be stored on Single Variant Source.
39 // Apps will be stored on an app per directory basis, hanging from
40 // SINGLE_VARIANT_SOURCE_DIR
41 const DIRECTORY_NAME = "webappsDir";
42 const SINGLE_VARIANT_SOURCE_DIR = "svoperapps";
43 const SINGLE_VARIANT_CONF_FILE = "singlevariantconf.json";
44 const PREF_FIRST_RUN_WITH_SIM = "dom.webapps.firstRunWithSIM";
45 const PREF_SINGLE_VARIANT_DIR = "dom.mozApps.single_variant_sourcedir";
46 const METADATA = "metadata.json";
47 const UPDATEMANIFEST = "update.webapp";
48 const MANIFEST = "manifest.webapp";
49 const APPLICATION_ZIP = "application.zip";
51 function isFirstRunWithSIM() {
52 try {
53 if (Services.prefs.prefHasUserValue(PREF_FIRST_RUN_WITH_SIM)) {
54 return Services.prefs.getBoolPref(PREF_FIRST_RUN_WITH_SIM);
55 }
56 } catch(e) {
57 debug ("Error getting pref. " + e);
58 }
59 return true;
60 }
62 #ifdef MOZ_B2G_RIL
63 let iccListener = {
64 notifyStkCommand: function() {},
66 notifyStkSessionEnd: function() {},
68 notifyCardStateChanged: function() {},
70 notifyIccInfoChanged: function() {
71 // TODO: Bug 927709 - OperatorApps for multi-sim
72 // In Multi-sim, there is more than one client in iccProvider. Each
73 // client represents a icc service. To maintain the backward compatibility
74 // with single sim, we always use client 0 for now. Adding support for
75 // multiple sim will be addressed in bug 927709, if needed.
76 let clientId = 0;
77 let iccInfo = iccProvider.getIccInfo(clientId);
78 if (iccInfo && iccInfo.mcc && iccInfo.mnc) {
79 let mcc = iccInfo.mcc;
80 let mnc = iccInfo.mnc;
81 debug("******* iccListener cardIccInfo MCC-MNC: " + mcc + "-" + mnc);
82 iccProvider.unregisterIccMsg(clientId, this);
83 OperatorAppsRegistry._installOperatorApps(mcc, mnc);
85 debug("Broadcast message first-run-with-sim");
86 let messenger = Cc["@mozilla.org/system-message-internal;1"]
87 .getService(Ci.nsISystemMessagesInternal);
88 messenger.broadcastMessage("first-run-with-sim", { mcc: mcc,
89 mnc: mnc });
90 }
91 }
92 };
93 #endif
95 this.OperatorAppsRegistry = {
97 _baseDirectory: null,
99 init: function() {
100 debug("init");
101 #ifdef MOZ_B2G_RIL
102 if (isFirstRunWithSIM()) {
103 debug("First Run with SIM");
104 Task.spawn(function() {
105 try {
106 yield this._initializeSourceDir();
107 // TODO: Bug 927709 - OperatorApps for multi-sim
108 // In Multi-sim, there is more than one client in iccProvider. Each
109 // client represents a icc service. To maintain the backward
110 // compatibility with single sim, we always use client 0 for now.
111 // Adding support for multiple sim will be addressed in bug 927709, if
112 // needed.
113 let clientId = 0;
114 let iccInfo = iccProvider.getIccInfo(clientId);
115 let mcc = 0;
116 let mnc = 0;
117 if (iccInfo && iccInfo.mcc) {
118 mcc = iccInfo.mcc;
119 }
120 if (iccInfo && iccInfo.mnc) {
121 mnc = iccInfo.mnc;
122 }
123 if (mcc && mnc) {
124 this._installOperatorApps(mcc, mnc);
125 } else {
126 iccProvider.registerIccMsg(clientId, iccListener);
127 }
128 } catch (e) {
129 debug("Error Initializing OperatorApps. " + e);
130 }
131 }.bind(this));
132 } else {
133 debug("No First Run with SIM");
134 }
135 #endif
136 },
138 _copyDirectory: function(aOrg, aDst) {
139 debug("copying " + aOrg + " to " + aDst);
140 return aDst && Task.spawn(function() {
141 try {
142 let orgDir = Cc["@mozilla.org/file/local;1"]
143 .createInstance(Ci.nsIFile);
144 orgDir.initWithPath(aOrg);
145 if (!orgDir.exists() || !orgDir.isDirectory()) {
146 debug(aOrg + " does not exist or is not a directory");
147 return;
148 }
150 let dstDir = Cc["@mozilla.org/file/local;1"]
151 .createInstance(Ci.nsIFile);
152 dstDir.initWithPath(aDst);
153 if (!dstDir.exists()) {
154 dstDir.create(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
155 }
157 let entries = orgDir.directoryEntries;
158 while (entries.hasMoreElements()) {
159 let entry = entries.getNext().QueryInterface(Ci.nsIFile);
161 if (!entry.isDirectory()) {
162 // Remove the file, because copyTo doesn't overwrite files.
163 let dstFile = dstDir.clone();
164 dstFile.append(entry.leafName);
165 if(dstFile.exists()) {
166 dstFile.remove(false);
167 }
169 entry.copyTo(dstDir, entry.leafName);
170 } else {
171 yield this._copyDirectory(entry.path,
172 Path.join(aDst, entry.leafName));
173 }
174 }
175 } catch (e) {
176 debug("Error copying " + aOrg + " to " + aDst + ". " + e);
177 }
178 }.bind(this));
179 },
181 _initializeSourceDir: function() {
182 return Task.spawn(function() {
183 let svFinalDirName;
184 try {
185 svFinalDirName = Services.prefs.getCharPref(PREF_SINGLE_VARIANT_DIR);
186 } catch(e) {
187 debug ("Error getting pref. " + e);
188 this.appsDir = FileUtils.getFile(DIRECTORY_NAME,
189 [SINGLE_VARIANT_SOURCE_DIR]).path;
190 return;
191 }
192 // If SINGLE_VARIANT_CONF_FILE is in PREF_SINGLE_VARIANT_DIR return
193 // PREF_SINGLE_VARIANT_DIR as sourceDir, else go to
194 // DIRECTORY_NAME + SINGLE_VARIANT_SOURCE_DIR and move all apps (and
195 // configuration file) to PREF_SINGLE_VARIANT_DIR and return
196 // PREF_SINGLE_VARIANT_DIR as sourceDir.
197 let svFinalDir = Cc["@mozilla.org/file/local;1"]
198 .createInstance(Ci.nsIFile);
199 svFinalDir.initWithPath(svFinalDirName);
200 if (!svFinalDir.exists()) {
201 svFinalDir.create(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
202 }
204 let svIndex = svFinalDir.clone();
205 svIndex.append(SINGLE_VARIANT_CONF_FILE);
206 if (!svIndex.exists()) {
207 let svSourceDir = FileUtils.getFile(DIRECTORY_NAME,
208 [SINGLE_VARIANT_SOURCE_DIR]);
210 yield this._copyDirectory(svSourceDir.path, svFinalDirName);
212 debug("removing directory:" + svSourceDir.path);
213 try {
214 svSourceDir.remove(true);
215 } catch(ex) { }
216 }
218 this.appsDir = svFinalDirName;
219 }.bind(this));
220 },
222 set appsDir(aDir) {
223 debug("appsDir SET: " + aDir);
224 if (aDir) {
225 this._baseDirectory = Cc["@mozilla.org/file/local;1"]
226 .createInstance(Ci.nsILocalFile);
227 this._baseDirectory.initWithPath(aDir);
228 } else {
229 this._baseDirectory = null;
230 }
231 },
233 get appsDir() {
234 return this._baseDirectory;
235 },
237 eraseVariantAppsNotInList: function(aIdsApp) {
238 if (!aIdsApp || !Array.isArray(aIdsApp)) {
239 aIdsApp = [ ];
240 }
242 let svDir;
243 try {
244 svDir = this.appsDir.clone();
245 } catch (e) {
246 debug("eraseVariantAppsNotInList --> Error getting Dir "+
247 svDir.path + ". " + e);
248 return;
249 }
251 if (!svDir || !svDir.exists()) {
252 return;
253 }
255 let entries = svDir.directoryEntries;
256 while (entries.hasMoreElements()) {
257 let entry = entries.getNext().QueryInterface(Ci.nsIFile);
258 if (entry.isDirectory() && aIdsApp.indexOf(entry.leafName) < 0) {
259 try{
260 entry.remove(true);
261 } catch(e) {
262 debug("Error removing [" + entry.path + "]." + e);
263 }
264 }
265 }
266 },
268 _launchInstall: function(isPackage, aId, aMetadata, aManifest) {
269 if (!aManifest) {
270 debug("Error: The application " + aId + " does not have a manifest");
271 return;
272 }
274 let appData = {
275 app: {
276 installOrigin: aMetadata.installOrigin,
277 origin: aMetadata.origin,
278 manifestURL: aMetadata.manifestURL,
279 manifestHash: AppsUtils.computeHash(JSON.stringify(aManifest))
280 },
281 appId: undefined,
282 isBrowser: false,
283 isPackage: isPackage,
284 forceSuccessAck: true
285 };
287 if (isPackage) {
288 debug("aId:" + aId + ". Installing as packaged app.");
289 let installPack = this.appsDir.clone();
290 installPack.append(aId);
291 installPack.append(APPLICATION_ZIP);
293 if (!installPack.exists()) {
294 debug("SV " + installPack.path + " file do not exists for app " + aId);
295 return;
296 }
298 appData.app.localInstallPath = installPack.path;
299 appData.app.updateManifest = aManifest;
300 DOMApplicationRegistry.confirmInstall(appData);
301 } else {
302 debug("aId:" + aId + ". Installing as hosted app.");
303 appData.app.manifest = aManifest;
304 DOMApplicationRegistry.confirmInstall(appData);
305 }
306 },
308 _installOperatorApps: function(aMcc, aMnc) {
309 Task.spawn(function() {
310 debug("Install operator apps ---> mcc:"+ aMcc + ", mnc:" + aMnc);
311 if (!isFirstRunWithSIM()) {
312 debug("Operator apps already installed.");
313 return;
314 }
316 let aIdsApp = yield this._getSingleVariantApps(aMcc, aMnc);
317 debug("installOperatorApps --> aIdsApp:" + JSON.stringify(aIdsApp));
318 for (let i = 0; i < aIdsApp.length; i++) {
319 let aId = aIdsApp[i];
320 let aMetadata = yield AppsUtils.loadJSONAsync(
321 Path.join(this.appsDir.path, aId, METADATA));
322 if (!aMetadata) {
323 debug("Error reading metadata file");
324 return;
325 }
327 debug("metadata:" + JSON.stringify(aMetadata));
328 let isPackage = true;
329 let manifest;
330 let manifests = [UPDATEMANIFEST, MANIFEST];
331 for (let j = 0; j < manifests.length; j++) {
332 manifest = yield AppsUtils.loadJSONAsync(
333 Path.join(this.appsDir.path, aId, manifests[j]));
335 if (!manifest) {
336 isPackage = false;
337 } else {
338 break;
339 }
340 }
341 if (manifest) {
342 this._launchInstall(isPackage, aId, aMetadata, manifest);
343 } else {
344 debug ("Error. Neither " + UPDATEMANIFEST + " file nor " + MANIFEST +
345 " file for " + aId + " app.");
346 }
347 }
348 this.eraseVariantAppsNotInList(aIdsApp);
349 Services.prefs.setBoolPref(PREF_FIRST_RUN_WITH_SIM, false);
350 Services.prefs.savePrefFile(null);
351 }.bind(this)).then(null, function(aError) {
352 debug("Error: " + aError);
353 });
354 },
356 _getSingleVariantApps: function(aMcc, aMnc) {
358 function normalizeCode(aCode) {
359 let ncode = "" + aCode;
360 while (ncode.length < 3) {
361 ncode = "0" + ncode;
362 }
363 return ncode;
364 }
366 return Task.spawn(function*() {
367 let key = normalizeCode(aMcc) + "-" + normalizeCode(aMnc);
368 let file = Path.join(this.appsDir.path, SINGLE_VARIANT_CONF_FILE);
369 let aData = yield AppsUtils.loadJSONAsync(file);
371 if (!aData || !(key in aData)) {
372 return [];
373 }
375 return aData[key];
376 }.bind(this));
377 }
378 };
380 OperatorAppsRegistry.init();