Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 const {Cc,Ci,Cu} = require("chrome");
2 const ObservableObject = require("devtools/shared/observable-object");
3 const promise = require("devtools/toolkit/deprecated-sync-thenables");
5 const {EventEmitter} = Cu.import("resource://gre/modules/devtools/event-emitter.js");
6 const {generateUUID} = Cc['@mozilla.org/uuid-generator;1'].getService(Ci.nsIUUIDGenerator);
8 /**
9 * IndexedDB wrapper that just save project objects
10 *
11 * The only constraint is that project objects have to have
12 * a unique `location` object.
13 */
15 const global = this;
16 const IDB = {
17 _db: null,
19 open: function () {
20 let deferred = promise.defer();
22 var idbManager = Cc["@mozilla.org/dom/indexeddb/manager;1"]
23 .getService(Ci.nsIIndexedDatabaseManager);
24 idbManager.initWindowless(global);
26 let request = global.indexedDB.open("AppProjects", 5);
27 request.onerror = function(event) {
28 deferred.reject("Unable to open AppProjects indexedDB. " +
29 "Error code: " + event.target.errorCode);
30 };
31 request.onupgradeneeded = function(event) {
32 let db = event.target.result;
33 db.createObjectStore("projects", { keyPath: "location" });
34 };
36 request.onsuccess = function() {
37 let db = IDB._db = request.result;
38 let objectStore = db.transaction("projects").objectStore("projects");
39 let projects = []
40 objectStore.openCursor().onsuccess = function(event) {
41 let cursor = event.target.result;
42 if (cursor) {
43 if (cursor.value.location) {
44 // We need to make sure this object has a `.location` property.
45 // The UI depends on this property.
46 // This should not be needed as we make sure to register valid
47 // projects, but in the past (before bug 924568), we might have
48 // registered invalid objects.
49 projects.push(cursor.value);
50 }
51 cursor.continue();
52 } else {
53 deferred.resolve(projects);
54 }
55 };
56 };
58 return deferred.promise;
59 },
61 add: function(project) {
62 let deferred = promise.defer();
64 if (!project.location) {
65 // We need to make sure this object has a `.location` property.
66 deferred.reject("Missing location property on project object.");
67 } else {
68 let transaction = IDB._db.transaction(["projects"], "readwrite");
69 let objectStore = transaction.objectStore("projects");
70 let request = objectStore.add(project);
71 request.onerror = function(event) {
72 deferred.reject("Unable to add project to the AppProjects indexedDB: " +
73 this.error.name + " - " + this.error.message );
74 };
75 request.onsuccess = function() {
76 deferred.resolve();
77 };
78 }
80 return deferred.promise;
81 },
83 update: function(project) {
84 let deferred = promise.defer();
86 var transaction = IDB._db.transaction(["projects"], "readwrite");
87 var objectStore = transaction.objectStore("projects");
88 var request = objectStore.put(project);
89 request.onerror = function(event) {
90 deferred.reject("Unable to update project to the AppProjects indexedDB: " +
91 this.error.name + " - " + this.error.message );
92 };
93 request.onsuccess = function() {
94 deferred.resolve();
95 };
97 return deferred.promise;
98 },
100 remove: function(location) {
101 let deferred = promise.defer();
103 let request = IDB._db.transaction(["projects"], "readwrite")
104 .objectStore("projects")
105 .delete(location);
106 request.onsuccess = function(event) {
107 deferred.resolve();
108 };
109 request.onerror = function() {
110 deferred.reject("Unable to delete project to the AppProjects indexedDB: " +
111 this.error.name + " - " + this.error.message );
112 };
114 return deferred.promise;
115 }
116 };
118 const store = new ObservableObject({ projects:[] });
120 let loadDeferred = promise.defer();
122 IDB.open().then(function (projects) {
123 store.object.projects = projects;
124 AppProjects.emit("ready", store.object.projects);
125 loadDeferred.resolve();
126 });
128 const AppProjects = {
129 load: function() {
130 return loadDeferred.promise;
131 },
133 addPackaged: function(folder) {
134 let project = {
135 type: "packaged",
136 location: folder.path,
137 // We need a unique id, that is the app origin,
138 // in order to identify the app when being installed on the device.
139 // The packaged app local path is a valid id, but only on the client.
140 // This origin will be used to generate the true id of an app:
141 // its manifest URL.
142 // If the app ends up specifying an explicit origin in its manifest,
143 // we will override this random UUID on app install.
144 packagedAppOrigin: generateUUID().toString().slice(1, -1)
145 };
146 return IDB.add(project).then(function () {
147 store.object.projects.push(project);
148 // return the added objects (proxified)
149 return store.object.projects[store.object.projects.length - 1];
150 });
151 },
153 addHosted: function(manifestURL) {
154 let project = {
155 type: "hosted",
156 location: manifestURL
157 };
158 return IDB.add(project).then(function () {
159 store.object.projects.push(project);
160 // return the added objects (proxified)
161 return store.object.projects[store.object.projects.length - 1];
162 });
163 },
165 update: function (project) {
166 return IDB.update({
167 type: project.type,
168 location: project.location,
169 packagedAppOrigin: project.packagedAppOrigin
170 }).then(() => project);
171 },
173 remove: function(location) {
174 return IDB.remove(location).then(function () {
175 let projects = store.object.projects;
176 for (let i = 0; i < projects.length; i++) {
177 if (projects[i].location == location) {
178 projects.splice(i, 1);
179 return;
180 }
181 }
182 throw new Error("Unable to find project in AppProjects store");
183 });
184 },
186 get: function(location) {
187 let projects = store.object.projects;
188 for (let i = 0; i < projects.length; i++) {
189 if (projects[i].location == location) {
190 return projects[i];
191 }
192 }
193 return null;
194 },
196 store: store
197 };
199 EventEmitter.decorate(AppProjects);
201 exports.AppProjects = AppProjects;