Merge lp:~sil/bindwood/design-view into lp:~urbanape/bindwood/trunk
- design-view
- Merge into trunk
Proposed by
Stuart Langridge
Status: | Merged |
---|---|
Merge reported by: | Zachery Bir |
Merged at revision: | not available |
Proposed branch: | lp:~sil/bindwood/design-view |
Merge into: | lp:~urbanape/bindwood/trunk |
Diff against target: | None lines |
To merge this branch: | bzr merge lp:~sil/bindwood/design-view |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Zachery Bir | Approve | ||
Review via email: mp+8267@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
Revision history for this message
Stuart Langridge (sil) wrote : | # |
lp:~sil/bindwood/design-view
updated
- 13. By Stuart Langridge
-
Add more debug messages
Revision history for this message
Zachery Bir (urbanape) wrote : | # |
Looks good and has been merged into lp:~urbanape/bindwood/dbus-and-local-uuids
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'chrome.manifest' | |||
2 | --- chrome.manifest 2009-06-30 13:47:50 +0000 | |||
3 | +++ chrome.manifest 2009-07-02 13:41:07 +0000 | |||
4 | @@ -1,2 +1,3 @@ | |||
7 | 1 | content ubuntuone-firefox-bookmark-sync chrome/content/ | 1 | content bindwood chrome/content/ |
8 | 2 | overlay chrome://browser/content/browser.xul chrome://ubuntuone-firefox-bookmark-sync/content/browserOverlay.xul | 2 | locale bindwood en chrome/locale/en/ |
9 | 3 | overlay chrome://browser/content/browser.xul chrome://bindwood/content/browserOverlay.xul | ||
10 | 3 | 4 | ||
11 | === modified file 'chrome/content/browserOverlay.xul' | |||
12 | --- chrome/content/browserOverlay.xul 2009-06-30 13:47:50 +0000 | |||
13 | +++ chrome/content/browserOverlay.xul 2009-07-03 02:22:26 +0000 | |||
14 | @@ -1,15 +1,27 @@ | |||
15 | 1 | <?xml version="1.0"?> | 1 | <?xml version="1.0"?> |
16 | 2 | 2 | ||
18 | 3 | <!DOCTYPE overlay SYSTEM "chrome://ubuntuone-firefox-bookmark-sync/locale/ubuntuone-firefox-bookmark-sync.dtd"> | 3 | <!DOCTYPE overlay SYSTEM "chrome://bindwood/locale/en/bindwood.dtd"> |
19 | 4 | 4 | ||
21 | 5 | <overlay id="ubuntuone-firefox-bookmark-sync" | 5 | <overlay id="bindwood" |
22 | 6 | xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> | 6 | xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> |
23 | 7 | 7 | ||
26 | 8 | <menupopup id="menu_ToolsPopup"> | 8 | <script type="application/x-javascript" src="chrome://bindwood/content/couch.js" /> |
27 | 9 | <menuitem id="UbuntuOneFirefoxBookmarkSync" | 9 | <script type="application/x-javascript" src="chrome://bindwood/content/sync.js" /> |
28 | 10 | |||
29 | 11 | <window id="main-window"> | ||
30 | 12 | <script type="application/x-javascript"> | ||
31 | 13 | window.addEventListener("load", Bindwood.init, true); | ||
32 | 14 | |||
33 | 15 | var bmsvc = Components.classes["@mozilla.org/browser/nav-bookmarks-service;1"].getService(Components.interfaces.nsINavBookmarksService); | ||
34 | 16 | window.addEventListener("load", function() { bmsvc.addObserver(Bindwood.Observer, false); }, false); | ||
35 | 17 | </script> | ||
36 | 18 | </window> | ||
37 | 19 | |||
38 | 20 | <menupopup id="bookmarksMenuPopup"> | ||
39 | 21 | <menuitem id="BindwoodSync" | ||
40 | 10 | label="Sync Bookmarks (well, alert)" | 22 | label="Sync Bookmarks (well, alert)" |
43 | 11 | insertbefore="javascriptConsole" | 23 | oncommand="pullBookmarks(false);" |
44 | 12 | oncommand="alert('syncing...');" /> | 24 | insertafter="bookmarksShowAll" /> |
45 | 13 | </menupopup> | 25 | </menupopup> |
46 | 14 | 26 | ||
47 | 15 | </overlay> | 27 | </overlay> |
48 | 16 | 28 | ||
49 | === added file 'chrome/content/couch.js' | |||
50 | --- chrome/content/couch.js 1970-01-01 00:00:00 +0000 | |||
51 | +++ chrome/content/couch.js 2009-07-06 10:49:17 +0000 | |||
52 | @@ -0,0 +1,396 @@ | |||
53 | 1 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not | ||
54 | 2 | // use this file except in compliance with the License. You may obtain a copy | ||
55 | 3 | // of the License at | ||
56 | 4 | // | ||
57 | 5 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
58 | 6 | // | ||
59 | 7 | // Unless required by applicable law or agreed to in writing, software | ||
60 | 8 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
61 | 9 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
62 | 10 | // License for the specific language governing permissions and limitations under | ||
63 | 11 | // the License. | ||
64 | 12 | |||
65 | 13 | // A simple class to represent a database. Uses XMLHttpRequest to interface with | ||
66 | 14 | // the CouchDB server. | ||
67 | 15 | |||
68 | 16 | function CouchDB(name, httpHeaders) { | ||
69 | 17 | this.name = name; | ||
70 | 18 | this.uri = "/" + encodeURIComponent(name) + "/"; | ||
71 | 19 | |||
72 | 20 | // The XMLHttpRequest object from the most recent request. Callers can | ||
73 | 21 | // use this to check result http status and headers. | ||
74 | 22 | this.last_req = null; | ||
75 | 23 | |||
76 | 24 | this.request = function(method, uri, requestOptions) { | ||
77 | 25 | requestOptions = requestOptions || {} | ||
78 | 26 | requestOptions.headers = combine(requestOptions.headers, httpHeaders) | ||
79 | 27 | return CouchDB.request(method, uri, requestOptions); | ||
80 | 28 | } | ||
81 | 29 | |||
82 | 30 | // Creates the database on the server | ||
83 | 31 | this.createDb = function() { | ||
84 | 32 | this.last_req = this.request("PUT", this.uri); | ||
85 | 33 | CouchDB.maybeThrowError(this.last_req); | ||
86 | 34 | return JSON.parse(this.last_req.responseText); | ||
87 | 35 | } | ||
88 | 36 | |||
89 | 37 | // Deletes the database on the server | ||
90 | 38 | this.deleteDb = function() { | ||
91 | 39 | this.last_req = this.request("DELETE", this.uri); | ||
92 | 40 | if (this.last_req.status == 404) | ||
93 | 41 | return false; | ||
94 | 42 | CouchDB.maybeThrowError(this.last_req); | ||
95 | 43 | return JSON.parse(this.last_req.responseText); | ||
96 | 44 | } | ||
97 | 45 | |||
98 | 46 | // Save a document to the database | ||
99 | 47 | this.save = function(doc, options) { | ||
100 | 48 | if (doc._id == undefined) | ||
101 | 49 | doc._id = CouchDB.newUuids(1)[0]; | ||
102 | 50 | |||
103 | 51 | this.last_req = this.request("PUT", this.uri + | ||
104 | 52 | encodeURIComponent(doc._id) + encodeOptions(options), | ||
105 | 53 | {body: JSON.stringify(doc)}); | ||
106 | 54 | CouchDB.maybeThrowError(this.last_req); | ||
107 | 55 | var result = JSON.parse(this.last_req.responseText); | ||
108 | 56 | doc._rev = result.rev; | ||
109 | 57 | return result; | ||
110 | 58 | } | ||
111 | 59 | |||
112 | 60 | // Open a document from the database | ||
113 | 61 | this.open = function(docId, options) { | ||
114 | 62 | this.last_req = this.request("GET", this.uri + encodeURIComponent(docId) + encodeOptions(options)); | ||
115 | 63 | if (this.last_req.status == 404) | ||
116 | 64 | return null; | ||
117 | 65 | CouchDB.maybeThrowError(this.last_req); | ||
118 | 66 | return JSON.parse(this.last_req.responseText); | ||
119 | 67 | } | ||
120 | 68 | |||
121 | 69 | // Deletes a document from the database | ||
122 | 70 | this.deleteDoc = function(doc) { | ||
123 | 71 | this.last_req = this.request("DELETE", this.uri + encodeURIComponent(doc._id) + "?rev=" + doc._rev); | ||
124 | 72 | CouchDB.maybeThrowError(this.last_req); | ||
125 | 73 | var result = JSON.parse(this.last_req.responseText); | ||
126 | 74 | doc._rev = result.rev; //record rev in input document | ||
127 | 75 | doc._deleted = true; | ||
128 | 76 | return result; | ||
129 | 77 | } | ||
130 | 78 | |||
131 | 79 | // Deletes an attachment from a document | ||
132 | 80 | this.deleteDocAttachment = function(doc, attachment_name) { | ||
133 | 81 | this.last_req = this.request("DELETE", this.uri + encodeURIComponent(doc._id) + "/" + attachment_name + "?rev=" + doc._rev); | ||
134 | 82 | CouchDB.maybeThrowError(this.last_req); | ||
135 | 83 | var result = JSON.parse(this.last_req.responseText); | ||
136 | 84 | doc._rev = result.rev; //record rev in input document | ||
137 | 85 | return result; | ||
138 | 86 | } | ||
139 | 87 | |||
140 | 88 | this.bulkSave = function(docs, options) { | ||
141 | 89 | // first prepoulate the UUIDs for new documents | ||
142 | 90 | var newCount = 0 | ||
143 | 91 | for (var i=0; i<docs.length; i++) { | ||
144 | 92 | if (docs[i]._id == undefined) | ||
145 | 93 | newCount++; | ||
146 | 94 | } | ||
147 | 95 | var newUuids = CouchDB.newUuids(docs.length); | ||
148 | 96 | var newCount = 0 | ||
149 | 97 | for (var i=0; i<docs.length; i++) { | ||
150 | 98 | if (docs[i]._id == undefined) | ||
151 | 99 | docs[i]._id = newUuids.pop(); | ||
152 | 100 | } | ||
153 | 101 | var json = {"docs": docs}; | ||
154 | 102 | // put any options in the json | ||
155 | 103 | for (var option in options) { | ||
156 | 104 | json[option] = options[option]; | ||
157 | 105 | } | ||
158 | 106 | this.last_req = this.request("POST", this.uri + "_bulk_docs", { | ||
159 | 107 | body: JSON.stringify(json) | ||
160 | 108 | }); | ||
161 | 109 | if (this.last_req.status == 417) { | ||
162 | 110 | return {errors: JSON.parse(this.last_req.responseText)}; | ||
163 | 111 | } | ||
164 | 112 | else { | ||
165 | 113 | CouchDB.maybeThrowError(this.last_req); | ||
166 | 114 | var results = JSON.parse(this.last_req.responseText); | ||
167 | 115 | for (var i = 0; i < docs.length; i++) { | ||
168 | 116 | if(results[i].rev) | ||
169 | 117 | docs[i]._rev = results[i].rev; | ||
170 | 118 | } | ||
171 | 119 | return results; | ||
172 | 120 | } | ||
173 | 121 | } | ||
174 | 122 | |||
175 | 123 | this.ensureFullCommit = function() { | ||
176 | 124 | this.last_req = this.request("POST", this.uri + "_ensure_full_commit"); | ||
177 | 125 | CouchDB.maybeThrowError(this.last_req); | ||
178 | 126 | return JSON.parse(this.last_req.responseText); | ||
179 | 127 | } | ||
180 | 128 | |||
181 | 129 | // Applies the map function to the contents of database and returns the results. | ||
182 | 130 | this.query = function(mapFun, reduceFun, options, keys) { | ||
183 | 131 | var body = {language: "javascript"}; | ||
184 | 132 | if(keys) { | ||
185 | 133 | body.keys = keys ; | ||
186 | 134 | } | ||
187 | 135 | if (typeof(mapFun) != "string") | ||
188 | 136 | mapFun = mapFun.toSource ? mapFun.toSource() : "(" + mapFun.toString() + ")"; | ||
189 | 137 | body.map = mapFun; | ||
190 | 138 | if (reduceFun != null) { | ||
191 | 139 | if (typeof(reduceFun) != "string") | ||
192 | 140 | reduceFun = reduceFun.toSource ? reduceFun.toSource() : "(" + reduceFun.toString() + ")"; | ||
193 | 141 | body.reduce = reduceFun; | ||
194 | 142 | } | ||
195 | 143 | if (options && options.options != undefined) { | ||
196 | 144 | body.options = options.options; | ||
197 | 145 | delete options.options; | ||
198 | 146 | } | ||
199 | 147 | this.last_req = this.request("POST", this.uri + "_temp_view" + encodeOptions(options), { | ||
200 | 148 | headers: {"Content-Type": "application/json"}, | ||
201 | 149 | body: JSON.stringify(body) | ||
202 | 150 | }); | ||
203 | 151 | CouchDB.maybeThrowError(this.last_req); | ||
204 | 152 | return JSON.parse(this.last_req.responseText); | ||
205 | 153 | } | ||
206 | 154 | |||
207 | 155 | this.view = function(viewname, options, keys) { | ||
208 | 156 | var viewParts = viewname.split('/'); | ||
209 | 157 | var viewPath = this.uri + "_design/" + viewParts[0] + "/_view/" | ||
210 | 158 | + viewParts[1] + encodeOptions(options); | ||
211 | 159 | if(!keys) { | ||
212 | 160 | this.last_req = this.request("GET", viewPath); | ||
213 | 161 | } else { | ||
214 | 162 | this.last_req = this.request("POST", viewPath, { | ||
215 | 163 | headers: {"Content-Type": "application/json"}, | ||
216 | 164 | body: JSON.stringify({keys:keys}) | ||
217 | 165 | }); | ||
218 | 166 | } | ||
219 | 167 | if (this.last_req.status == 404) | ||
220 | 168 | return null; | ||
221 | 169 | CouchDB.maybeThrowError(this.last_req); | ||
222 | 170 | return JSON.parse(this.last_req.responseText); | ||
223 | 171 | } | ||
224 | 172 | |||
225 | 173 | // gets information about the database | ||
226 | 174 | this.info = function() { | ||
227 | 175 | this.last_req = this.request("GET", this.uri); | ||
228 | 176 | CouchDB.maybeThrowError(this.last_req); | ||
229 | 177 | return JSON.parse(this.last_req.responseText); | ||
230 | 178 | } | ||
231 | 179 | |||
232 | 180 | this.allDocs = function(options,keys) { | ||
233 | 181 | if(!keys) { | ||
234 | 182 | this.last_req = this.request("GET", this.uri + "_all_docs" + encodeOptions(options)); | ||
235 | 183 | } else { | ||
236 | 184 | this.last_req = this.request("POST", this.uri + "_all_docs" + encodeOptions(options), { | ||
237 | 185 | headers: {"Content-Type": "application/json"}, | ||
238 | 186 | body: JSON.stringify({keys:keys}) | ||
239 | 187 | }); | ||
240 | 188 | } | ||
241 | 189 | CouchDB.maybeThrowError(this.last_req); | ||
242 | 190 | return JSON.parse(this.last_req.responseText); | ||
243 | 191 | } | ||
244 | 192 | |||
245 | 193 | this.designDocs = function() { | ||
246 | 194 | return this.allDocs({startkey:"_design", endkey:"_design0"}); | ||
247 | 195 | }; | ||
248 | 196 | |||
249 | 197 | this.allDocsBySeq = function(options,keys) { | ||
250 | 198 | var req = null; | ||
251 | 199 | if(!keys) { | ||
252 | 200 | req = this.request("GET", this.uri + "_all_docs_by_seq" + encodeOptions(options)); | ||
253 | 201 | } else { | ||
254 | 202 | req = this.request("POST", this.uri + "_all_docs_by_seq" + encodeOptions(options), { | ||
255 | 203 | headers: {"Content-Type": "application/json"}, | ||
256 | 204 | body: JSON.stringify({keys:keys}) | ||
257 | 205 | }); | ||
258 | 206 | } | ||
259 | 207 | CouchDB.maybeThrowError(req); | ||
260 | 208 | return JSON.parse(req.responseText); | ||
261 | 209 | } | ||
262 | 210 | |||
263 | 211 | this.compact = function() { | ||
264 | 212 | this.last_req = this.request("POST", this.uri + "_compact"); | ||
265 | 213 | CouchDB.maybeThrowError(this.last_req); | ||
266 | 214 | return JSON.parse(this.last_req.responseText); | ||
267 | 215 | } | ||
268 | 216 | |||
269 | 217 | this.setDbProperty = function(propId, propValue) { | ||
270 | 218 | this.last_req = this.request("PUT", this.uri + propId,{ | ||
271 | 219 | body:JSON.stringify(propValue) | ||
272 | 220 | }); | ||
273 | 221 | CouchDB.maybeThrowError(this.last_req); | ||
274 | 222 | return JSON.parse(this.last_req.responseText); | ||
275 | 223 | } | ||
276 | 224 | |||
277 | 225 | this.getDbProperty = function(propId) { | ||
278 | 226 | this.last_req = this.request("GET", this.uri + propId); | ||
279 | 227 | CouchDB.maybeThrowError(this.last_req); | ||
280 | 228 | return JSON.parse(this.last_req.responseText); | ||
281 | 229 | } | ||
282 | 230 | |||
283 | 231 | this.setAdmins = function(adminsArray) { | ||
284 | 232 | this.last_req = this.request("PUT", this.uri + "_admins",{ | ||
285 | 233 | body:JSON.stringify(adminsArray) | ||
286 | 234 | }); | ||
287 | 235 | CouchDB.maybeThrowError(this.last_req); | ||
288 | 236 | return JSON.parse(this.last_req.responseText); | ||
289 | 237 | } | ||
290 | 238 | |||
291 | 239 | this.getAdmins = function() { | ||
292 | 240 | this.last_req = this.request("GET", this.uri + "_admins"); | ||
293 | 241 | CouchDB.maybeThrowError(this.last_req); | ||
294 | 242 | return JSON.parse(this.last_req.responseText); | ||
295 | 243 | } | ||
296 | 244 | |||
297 | 245 | // Convert a options object to an url query string. | ||
298 | 246 | // ex: {key:'value',key2:'value2'} becomes '?key="value"&key2="value2"' | ||
299 | 247 | function encodeOptions(options) { | ||
300 | 248 | var buf = [] | ||
301 | 249 | if (typeof(options) == "object" && options !== null) { | ||
302 | 250 | for (var name in options) { | ||
303 | 251 | if (!options.hasOwnProperty(name)) continue; | ||
304 | 252 | var value = options[name]; | ||
305 | 253 | if (name == "key" || name == "startkey" || name == "endkey") { | ||
306 | 254 | value = toJSON(value); | ||
307 | 255 | } | ||
308 | 256 | buf.push(encodeURIComponent(name) + "=" + encodeURIComponent(value)); | ||
309 | 257 | } | ||
310 | 258 | } | ||
311 | 259 | if (!buf.length) { | ||
312 | 260 | return ""; | ||
313 | 261 | } | ||
314 | 262 | return "?" + buf.join("&"); | ||
315 | 263 | } | ||
316 | 264 | |||
317 | 265 | function toJSON(obj) { | ||
318 | 266 | return obj !== null ? JSON.stringify(obj) : null; | ||
319 | 267 | } | ||
320 | 268 | |||
321 | 269 | function combine(object1, object2) { | ||
322 | 270 | if (!object2) | ||
323 | 271 | return object1; | ||
324 | 272 | if (!object1) | ||
325 | 273 | return object2; | ||
326 | 274 | |||
327 | 275 | for (var name in object2) | ||
328 | 276 | object1[name] = object2[name]; | ||
329 | 277 | |||
330 | 278 | return object1; | ||
331 | 279 | } | ||
332 | 280 | |||
333 | 281 | |||
334 | 282 | } | ||
335 | 283 | |||
336 | 284 | // this is the XMLHttpRequest object from last request made by the following | ||
337 | 285 | // CouchDB.* functions (except for calls to request itself). | ||
338 | 286 | // Use this from callers to check HTTP status or header values of requests. | ||
339 | 287 | CouchDB.last_req = null; | ||
340 | 288 | |||
341 | 289 | |||
342 | 290 | CouchDB.allDbs = function() { | ||
343 | 291 | CouchDB.last_req = CouchDB.request("GET", "/_all_dbs"); | ||
344 | 292 | CouchDB.maybeThrowError(CouchDB.last_req); | ||
345 | 293 | return JSON.parse(CouchDB.last_req.responseText); | ||
346 | 294 | } | ||
347 | 295 | |||
348 | 296 | CouchDB.allDesignDocs = function() { | ||
349 | 297 | var ddocs = {}, dbs = CouchDB.allDbs(); | ||
350 | 298 | for (var i=0; i < dbs.length; i++) { | ||
351 | 299 | var db = new CouchDB(dbs[i]); | ||
352 | 300 | ddocs[dbs[i]] = db.designDocs(); | ||
353 | 301 | }; | ||
354 | 302 | return ddocs; | ||
355 | 303 | }; | ||
356 | 304 | |||
357 | 305 | CouchDB.getVersion = function() { | ||
358 | 306 | CouchDB.last_req = CouchDB.request("GET", "/"); | ||
359 | 307 | CouchDB.maybeThrowError(CouchDB.last_req); | ||
360 | 308 | return JSON.parse(CouchDB.last_req.responseText).version; | ||
361 | 309 | } | ||
362 | 310 | |||
363 | 311 | CouchDB.replicate = function(source, target, rep_options) { | ||
364 | 312 | rep_options = rep_options || {}; | ||
365 | 313 | var headers = rep_options.headers || {}; | ||
366 | 314 | CouchDB.last_req = CouchDB.request("POST", "/_replicate", { | ||
367 | 315 | headers: headers, | ||
368 | 316 | body: JSON.stringify({source: source, target: target}) | ||
369 | 317 | }); | ||
370 | 318 | CouchDB.maybeThrowError(CouchDB.last_req); | ||
371 | 319 | return JSON.parse(CouchDB.last_req.responseText); | ||
372 | 320 | } | ||
373 | 321 | |||
374 | 322 | CouchDB.request = function(method, uri, options) { | ||
375 | 323 | Bindwood.writeMessage("CouchDB.request connecting to " + uri); | ||
376 | 324 | options = options || {}; | ||
377 | 325 | var req = null; | ||
378 | 326 | if (typeof(XMLHttpRequest) != "undefined") { | ||
379 | 327 | req = new XMLHttpRequest(); | ||
380 | 328 | } else if (typeof(ActiveXObject) != "undefined") { | ||
381 | 329 | req = new ActiveXObject("Microsoft.XMLHTTP"); | ||
382 | 330 | } else { | ||
383 | 331 | throw new Error("No XMLHTTPRequest support detected"); | ||
384 | 332 | } | ||
385 | 333 | req.open(method, "http://localhost:5984" + uri, false); | ||
386 | 334 | if (options.headers) { | ||
387 | 335 | var headers = options.headers; | ||
388 | 336 | for (var headerName in headers) { | ||
389 | 337 | if (!headers.hasOwnProperty(headerName)) continue; | ||
390 | 338 | req.setRequestHeader(headerName, headers[headerName]); | ||
391 | 339 | } | ||
392 | 340 | } | ||
393 | 341 | req.send(options.body || ""); | ||
394 | 342 | return req; | ||
395 | 343 | } | ||
396 | 344 | |||
397 | 345 | CouchDB.requestStats = function(module, key, test) { | ||
398 | 346 | var query_arg = ""; | ||
399 | 347 | if(test !== null) { | ||
400 | 348 | query_arg = "?flush=true"; | ||
401 | 349 | } | ||
402 | 350 | |||
403 | 351 | var stat = CouchDB.request("GET", "/_stats/" + module + "/" + key + query_arg).responseText; | ||
404 | 352 | return JSON.parse(stat)[module][key]; | ||
405 | 353 | } | ||
406 | 354 | |||
407 | 355 | CouchDB.uuids_cache = []; | ||
408 | 356 | |||
409 | 357 | CouchDB.newUuids = function(n) { | ||
410 | 358 | if (CouchDB.uuids_cache.length >= n) { | ||
411 | 359 | var uuids = CouchDB.uuids_cache.slice(CouchDB.uuids_cache.length - n); | ||
412 | 360 | if(CouchDB.uuids_cache.length - n == 0) { | ||
413 | 361 | CouchDB.uuids_cache = []; | ||
414 | 362 | } else { | ||
415 | 363 | CouchDB.uuids_cache = | ||
416 | 364 | CouchDB.uuids_cache.slice(0, CouchDB.uuids_cache.length - n); | ||
417 | 365 | } | ||
418 | 366 | return uuids; | ||
419 | 367 | } else { | ||
420 | 368 | CouchDB.last_req = CouchDB.request("GET", "/_uuids?count=" + (100 + n)); | ||
421 | 369 | CouchDB.maybeThrowError(CouchDB.last_req); | ||
422 | 370 | var result = JSON.parse(CouchDB.last_req.responseText); | ||
423 | 371 | CouchDB.uuids_cache = | ||
424 | 372 | CouchDB.uuids_cache.concat(result.uuids.slice(0, 100)); | ||
425 | 373 | return result.uuids.slice(100); | ||
426 | 374 | } | ||
427 | 375 | } | ||
428 | 376 | |||
429 | 377 | CouchDB.maybeThrowError = function(req) { | ||
430 | 378 | if (req.status >= 400) { | ||
431 | 379 | try { | ||
432 | 380 | var result = JSON.parse(req.responseText); | ||
433 | 381 | } catch (ParseError) { | ||
434 | 382 | var result = {error:"unknown", reason:req.responseText}; | ||
435 | 383 | } | ||
436 | 384 | throw result; | ||
437 | 385 | } | ||
438 | 386 | } | ||
439 | 387 | |||
440 | 388 | CouchDB.params = function(options) { | ||
441 | 389 | options = options || {}; | ||
442 | 390 | var returnArray = []; | ||
443 | 391 | for(var key in options) { | ||
444 | 392 | var value = options[key]; | ||
445 | 393 | returnArray.push(key + "=" + value); | ||
446 | 394 | } | ||
447 | 395 | return returnArray.join("&"); | ||
448 | 396 | } | ||
449 | 0 | 397 | ||
450 | === added file 'chrome/content/sync.js' | |||
451 | --- chrome/content/sync.js 1970-01-01 00:00:00 +0000 | |||
452 | +++ chrome/content/sync.js 2009-07-06 16:00:58 +0000 | |||
453 | @@ -0,0 +1,358 @@ | |||
454 | 1 | /* Lots and lots of debugging information */ | ||
455 | 2 | var Bindwood = { | ||
456 | 3 | bookmarksService: Components.classes["@mozilla.org/browser/nav-bookmarks-service;1"] | ||
457 | 4 | .getService(Components.interfaces.nsINavBookmarksService), | ||
458 | 5 | |||
459 | 6 | writeMessage: function(aMessage) { | ||
460 | 7 | // convenience method for logging. Way better than alert()s. | ||
461 | 8 | var consoleService = Components.classes["@mozilla.org/consoleservice;1"] | ||
462 | 9 | .getService(Components.interfaces.nsIConsoleService); | ||
463 | 10 | consoleService.logStringMessage("Bindwood: " + aMessage); | ||
464 | 11 | }, | ||
465 | 12 | |||
466 | 13 | writeError: function(aMessage, e) { | ||
467 | 14 | Bindwood.writeMessage(aMessage + "message: '" + e.message + "', reason: '" + e.reason + "', description: '" + e.description + "', error: '" + e.error + "'"); | ||
468 | 15 | }, | ||
469 | 16 | |||
470 | 17 | init: function() { | ||
471 | 18 | // Start the process and de-register ourself | ||
472 | 19 | // http://forums.mozillazine.org/viewtopic.php?f=19&t=657911&start=0 | ||
473 | 20 | // It ensures that we're only running that code on the first window. | ||
474 | 21 | if(Components.classes["@mozilla.org/appshell/window-mediator;1"] | ||
475 | 22 | .getService(Components.interfaces.nsIWindowMediator) | ||
476 | 23 | .getEnumerator("").getNext() == window) { | ||
477 | 24 | try { | ||
478 | 25 | Bindwood.writeMessage("About to push bookmarks (startup)"); | ||
479 | 26 | Bindwood.pushBookmarks(); | ||
480 | 27 | } catch(e) { | ||
481 | 28 | Bindwood.writeError("Error when calling pushBookmarks: ", e); | ||
482 | 29 | } | ||
483 | 30 | Bindwood.writeMessage("Creating view"); | ||
484 | 31 | Bindwood.createView(); | ||
485 | 32 | Bindwood.writeMessage("About to pull bookmarks (startup)"); | ||
486 | 33 | Bindwood.pullBookmarks(); | ||
487 | 34 | } | ||
488 | 35 | }, | ||
489 | 36 | |||
490 | 37 | createView: function() { | ||
491 | 38 | var DDID = "_design/views"; | ||
492 | 39 | var couch = new CouchDB('bookmarks'); | ||
493 | 40 | var current_doc; | ||
494 | 41 | try { | ||
495 | 42 | current_doc = couch.open(DDID); | ||
496 | 43 | if (current_doc !== null) { | ||
497 | 44 | Bindwood.writeMessage("View already exists; leaving it alone"); | ||
498 | 45 | } else { | ||
499 | 46 | new_doc = { | ||
500 | 47 | _id: DDID, | ||
501 | 48 | views: { | ||
502 | 49 | display: { | ||
503 | 50 | map: "function(doc) { " + | ||
504 | 51 | "var scheme = doc.uri.split(':',1)[0]; " + | ||
505 | 52 | "var uri; " + | ||
506 | 53 | "if (scheme == 'http' || scheme == 'https') {" + | ||
507 | 54 | "uri = doc.uri.split('/')[2];" + | ||
508 | 55 | "if (uri.length < 30) {" + | ||
509 | 56 | " uri += '/' + " + | ||
510 | 57 | "doc.uri.split('/',4)[3].substr(0,30-uri.length) + '...';" + | ||
511 | 58 | "}" + | ||
512 | 59 | "} else {" + | ||
513 | 60 | "uri = scheme + ' URL';" + | ||
514 | 61 | "}" + | ||
515 | 62 | "emit(doc.title, uri);" + | ||
516 | 63 | "}" | ||
517 | 64 | } | ||
518 | 65 | } | ||
519 | 66 | }; | ||
520 | 67 | try { | ||
521 | 68 | couch.save(new_doc); | ||
522 | 69 | Bindwood.writeMessage("Added view"); | ||
523 | 70 | } catch(e) { | ||
524 | 71 | Bindwood.writeError("Problem saving view: ", e); | ||
525 | 72 | } | ||
526 | 73 | } | ||
527 | 74 | } catch(e) { | ||
528 | 75 | // some kind of error fetching the existing design doc | ||
529 | 76 | Bindwood.writeError("Problem checking for view: ", e); | ||
530 | 77 | } | ||
531 | 78 | }, | ||
532 | 79 | |||
533 | 80 | pushBookmarks: function() { | ||
534 | 81 | // Prime the pump, so to speak, by uploading all our local | ||
535 | 82 | // bookmarks to CouchDB (if they're not there already). | ||
536 | 83 | Bindwood.writeMessage("in pushBookmarks"); | ||
537 | 84 | var couch = new CouchDB('bookmarks'); | ||
538 | 85 | // Create the DB if it doesn't already exist | ||
539 | 86 | try { | ||
540 | 87 | Bindwood.writeMessage("creating database"); | ||
541 | 88 | couch.createDb(); | ||
542 | 89 | } catch (e) { | ||
543 | 90 | Bindwood.writeError("Error when creating database in pushBookmarks (file_exists is OK here): ", e); | ||
544 | 91 | } | ||
545 | 92 | |||
546 | 93 | Bindwood.writeMessage("about to push toolbar bookmarks"); | ||
547 | 94 | Bindwood.pushBookmarksFromList(Bindwood.bookmarksService.toolbarFolder, | ||
548 | 95 | "toolbarFolder", couch); | ||
549 | 96 | Bindwood.writeMessage("about to push menu bookmarks"); | ||
550 | 97 | Bindwood.pushBookmarksFromList(Bindwood.bookmarksService.bookmarksMenuFolder, | ||
551 | 98 | "bookmarksMenuFolder", couch); | ||
552 | 99 | }, | ||
553 | 100 | |||
554 | 101 | getBookmarksFromList: function(bookmarksList) { | ||
555 | 102 | Bindwood.writeMessage("in getBookmarksFromList with list " + bookmarksList); | ||
556 | 103 | var retval = []; | ||
557 | 104 | var historyService = Components.classes["@mozilla.org/browser/nav-history-service;1"] | ||
558 | 105 | .getService(Components.interfaces.nsINavHistoryService); | ||
559 | 106 | var options = historyService.getNewQueryOptions(); | ||
560 | 107 | var query = historyService.getNewQuery(); | ||
561 | 108 | query.setFolders([bookmarksList], 1); | ||
562 | 109 | var result = historyService.executeQuery(query, options); | ||
563 | 110 | var rootNode = result.root; | ||
564 | 111 | rootNode.containerOpen = true; | ||
565 | 112 | for (var i=0; i<rootNode.childCount; i++) { | ||
566 | 113 | var node = rootNode.getChild(i); | ||
567 | 114 | if (Bindwood.bookmarksService.getItemType(node.itemId) != | ||
568 | 115 | Components.interfaces.nsINavBookmarksService.TYPE_BOOKMARK) { | ||
569 | 116 | continue; | ||
570 | 117 | } | ||
571 | 118 | |||
572 | 119 | var title = Bindwood.bookmarksService.getItemTitle(node.itemId); | ||
573 | 120 | Bindwood.writeMessage("got bookmark '" + title + "'"); | ||
574 | 121 | try { | ||
575 | 122 | var metadata = Bindwood.bookmarksService.getBookmarkURI(node.itemId); | ||
576 | 123 | } catch(e) { | ||
577 | 124 | Bindwood.writeError("problem fetching metadata for bookmark '" + title + "': ", e); | ||
578 | 125 | continue; | ||
579 | 126 | } | ||
580 | 127 | var guid = Bindwood.bookmarksService.getItemGUID(node.itemId); | ||
581 | 128 | Bindwood.writeMessage("got GUID"); | ||
582 | 129 | retval.push({title: title, metadata:metadata,guid:guid, id:node.itemId}); | ||
583 | 130 | } | ||
584 | 131 | rootNode.containerOpen = false; | ||
585 | 132 | return retval; | ||
586 | 133 | }, | ||
587 | 134 | |||
588 | 135 | pushBookmarksFromList: function(bookmarksList, bookmarksListName, db) { | ||
589 | 136 | Bindwood.writeMessage("in pushBookmarksFromList"); | ||
590 | 137 | var bookmarkData = Bindwood.getBookmarksFromList(bookmarksList); | ||
591 | 138 | for (i=0; i<bookmarkData.length; i++) { | ||
592 | 139 | // find this bookmark in CouchDB | ||
593 | 140 | Bindwood.writeMessage("searching for bookmark '" + bookmarkData[i].title + "' in Couch"); | ||
594 | 141 | var results = db.query(function(doc) { | ||
595 | 142 | if (doc.application_annotations && | ||
596 | 143 | doc.application_annotations.Firefox && | ||
597 | 144 | doc.application_annotations.Firefox.guid) { | ||
598 | 145 | emit(doc.application_annotations.Firefox.guid, doc); | ||
599 | 146 | } | ||
600 | 147 | }, null, { | ||
601 | 148 | startkey: bookmarkData[i].guid, endkey: bookmarkData[i].guid | ||
602 | 149 | }); | ||
603 | 150 | |||
604 | 151 | if (results.rows.length === 0) { | ||
605 | 152 | // this bookmark is not in CouchDB, so write it | ||
606 | 153 | Bindwood.writeMessage("Didn't find it, so creating it"); | ||
607 | 154 | var record = { | ||
608 | 155 | record_type: "http://example.com/bookmark", | ||
609 | 156 | uri: bookmarkData[i].metadata.spec, | ||
610 | 157 | title: bookmarkData[i].title, | ||
611 | 158 | application_annotations: { | ||
612 | 159 | Firefox: { | ||
613 | 160 | guid: bookmarkData[i].guid, | ||
614 | 161 | list: bookmarksListName | ||
615 | 162 | } | ||
616 | 163 | } | ||
617 | 164 | }; | ||
618 | 165 | try { | ||
619 | 166 | db.save(record); | ||
620 | 167 | } catch(e) { | ||
621 | 168 | Bindwood.writeError("Problem saving bookmark to CouchDB; bookmark is " + JSON.stringify(record) + ": ", e); | ||
622 | 169 | } | ||
623 | 170 | } else { | ||
624 | 171 | // bookmark is already in CouchDB, so do nothing | ||
625 | 172 | Bindwood.writeMessage("Did find it, so don't need to do anything"); | ||
626 | 173 | } | ||
627 | 174 | } | ||
628 | 175 | }, | ||
629 | 176 | |||
630 | 177 | pullBookmarks: function() { | ||
631 | 178 | Bindwood.writeMessage("in pullBookmarks"); | ||
632 | 179 | var couch = new CouchDB('bookmarks'); | ||
633 | 180 | // Fetch all bookmark documents from the database | ||
634 | 181 | // the query function is evaluated by Couch, which doesn't know | ||
635 | 182 | // what Bindwood.RECORD_TYPE is, so we string-encode it first to | ||
636 | 183 | // include the literal value | ||
637 | 184 | try { | ||
638 | 185 | var rows = couch.query(function (doc) { | ||
639 | 186 | if (doc.record_type == "http://example.com/bookmark") { | ||
640 | 187 | emit(doc._id,doc); | ||
641 | 188 | } | ||
642 | 189 | }); | ||
643 | 190 | } catch(e) { | ||
644 | 191 | Bindwood.writeError("Problem fetching all bookmarks from Couch:", e); | ||
645 | 192 | } | ||
646 | 193 | for (var i=0; i<rows.rows.length; i++) { | ||
647 | 194 | var recordid = rows.rows[i].id; | ||
648 | 195 | var bm = rows.rows[i].value; | ||
649 | 196 | if (bm.application_annotations && bm.application_annotations.Firefox && | ||
650 | 197 | bm.application_annotations.Firefox.guid) { | ||
651 | 198 | // this bookmark has a guid, so check its values haven't changed | ||
652 | 199 | // find the bookmark with this guid | ||
653 | 200 | var itemId = Bindwood.bookmarksService.getItemIdForGUID( | ||
654 | 201 | bm.application_annotations.Firefox.guid); | ||
655 | 202 | if (itemId == -1) { | ||
656 | 203 | // This bookmark has a guid, but it's not one of ours. | ||
657 | 204 | // We need to work out whether (a) it's the same as one | ||
658 | 205 | // of ours but with a different guid (so we need to | ||
659 | 206 | // make the guids the same), or (b) it's a new one | ||
660 | 207 | // that happens to have been created on a different | ||
661 | 208 | // machine. | ||
662 | 209 | // For the moment, punt on this. | ||
663 | 210 | } else { | ||
664 | 211 | var title = Bindwood.bookmarksService.getItemTitle(itemId); | ||
665 | 212 | var metadata = Bindwood.bookmarksService.getBookmarkURI(itemId); | ||
666 | 213 | if (title != bm.title) { | ||
667 | 214 | Bindwood.bookmarksService.setItemTitle(itemId, bm.title); | ||
668 | 215 | } | ||
669 | 216 | if (metadata.spec != bm.uri) { | ||
670 | 217 | metadata.spec = bm.uri; | ||
671 | 218 | Bindwood.bookmarksService.changeBookmarkURI(itemId, metadata); | ||
672 | 219 | } | ||
673 | 220 | } | ||
674 | 221 | } else { | ||
675 | 222 | // this bookmark has no guid, so create it from fresh in Firefox | ||
676 | 223 | var list; | ||
677 | 224 | if (bm.application_annotations && bm.application_annotations.Firefox && | ||
678 | 225 | bm.application_annotations.Firefox.list) { | ||
679 | 226 | switch (bm.application_annotations.Firefox.list) { | ||
680 | 227 | case "toolbarFolder": | ||
681 | 228 | list = Bindwood.bookmarksService.toolbarFolder; | ||
682 | 229 | break; | ||
683 | 230 | case "bookmarksMenuFolder": | ||
684 | 231 | list = Bindwood.bookmarksService.bookmarksMenuFolder; | ||
685 | 232 | break; | ||
686 | 233 | default: | ||
687 | 234 | list = Bindwood.bookmarksService.toolbarFolder; | ||
688 | 235 | break; | ||
689 | 236 | } | ||
690 | 237 | } else { | ||
691 | 238 | list = Bindwood.bookmarksService.toolbarFolder; | ||
692 | 239 | } | ||
693 | 240 | var metadata = Components.classes["@mozilla.org/network/io-service;1"] | ||
694 | 241 | .getService(Components.interfaces.nsIIOService) | ||
695 | 242 | .newURI(bm.uri, null, null); | ||
696 | 243 | |||
697 | 244 | var itemId = Bindwood.bookmarksService.insertBookmark(list, | ||
698 | 245 | metadata, -1, bm.title); | ||
699 | 246 | // and then write the new guid back to the record | ||
700 | 247 | var guid = Bindwood.bookmarksService.getItemGUID(itemId); | ||
701 | 248 | var doc = couch.open(recordid); | ||
702 | 249 | if (!doc.application_annotations) { | ||
703 | 250 | doc.application_annotations = {}; | ||
704 | 251 | } | ||
705 | 252 | if (!doc.application_annotations.Firefox) { | ||
706 | 253 | doc.application_annotations.Firefox = {}; | ||
707 | 254 | } | ||
708 | 255 | doc.application_annotations.Firefox.guid = guid; | ||
709 | 256 | couch.save(doc); | ||
710 | 257 | } | ||
711 | 258 | } | ||
712 | 259 | // reschedule ourself | ||
713 | 260 | setTimeout(Bindwood.pullBookmarks, 5000); | ||
714 | 261 | }, | ||
715 | 262 | |||
716 | 263 | Observer: { | ||
717 | 264 | // An nsINavBookmarkObserver | ||
718 | 265 | onBeginUpdateBatch: function() {}, | ||
719 | 266 | onEndUpdateBatch: function() {}, | ||
720 | 267 | onItemAdded: function(aItemId, aFolder, aIndex) { | ||
721 | 268 | // A bookmark has been added, so we create a blank entry | ||
722 | 269 | // in Couch with our local itemId attached. | ||
723 | 270 | Bindwood.writeMessage("onItemAdded!!!!" + Bindwood.bookmarksService.getItemGUID(aItemId)); | ||
724 | 271 | var list; | ||
725 | 272 | switch(aFolder) { | ||
726 | 273 | case Bindwood.bookmarksService.toolbarFolder: | ||
727 | 274 | list = "toolbarFolder"; | ||
728 | 275 | break; | ||
729 | 276 | case Bindwood.bookmarksService.bookmarksMenuFolder: | ||
730 | 277 | list = "bookmarksMenuFolder"; | ||
731 | 278 | break; | ||
732 | 279 | default: | ||
733 | 280 | list = "toolbarFolder"; | ||
734 | 281 | break; | ||
735 | 282 | } | ||
736 | 283 | |||
737 | 284 | netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead UniversalBrowserWrite"); | ||
738 | 285 | var couch = new CouchDB('bookmarks'); | ||
739 | 286 | |||
740 | 287 | var doc = { | ||
741 | 288 | record_type: "http://example.com/bookmark", | ||
742 | 289 | application_annotations: { | ||
743 | 290 | Firefox: { | ||
744 | 291 | guid: Bindwood.bookmarksService.getItemGUID(aItemId), | ||
745 | 292 | list: list | ||
746 | 293 | } | ||
747 | 294 | } | ||
748 | 295 | }; | ||
749 | 296 | try { | ||
750 | 297 | var result = couch.save(doc); | ||
751 | 298 | Bindwood.writeMessage("Saved record: " + result.rev); | ||
752 | 299 | } catch(e) { | ||
753 | 300 | Bindwood.writeMessage("Error '" + e.error + "': " + e.reason); | ||
754 | 301 | } | ||
755 | 302 | return true; | ||
756 | 303 | }, | ||
757 | 304 | onItemRemoved: function(aItemId, aFolder, aIndex) { | ||
758 | 305 | // A bookmark has been removed. This is called after it's | ||
759 | 306 | // been removed locally, though we're passed the itemId, | ||
760 | 307 | // which we use to delete from Couch. | ||
761 | 308 | var guid = Bindwood.bookmarksService.getItemGUID(aItemId); | ||
762 | 309 | var results = db.query(function(doc) { | ||
763 | 310 | if (doc.application_annotations && | ||
764 | 311 | doc.application_annotations.Firefox && | ||
765 | 312 | doc.application_annotations.Firefox.guid) { | ||
766 | 313 | emit(doc.application_annotations.Firefox.guid, doc); | ||
767 | 314 | } | ||
768 | 315 | }, null, { | ||
769 | 316 | startkey: guid, endkey: guid | ||
770 | 317 | }); | ||
771 | 318 | Bindwood.writeMessage("deleted item " + JSON.stringify(results)); | ||
772 | 319 | }, | ||
773 | 320 | onItemChanged: function(aBookmarkId, aProperty, aIsAnnotationProperty, aValue) { | ||
774 | 321 | // A property of a bookmark has changed. On multiple | ||
775 | 322 | // property updates, this will be called multiple times, | ||
776 | 323 | // once per property (i.e., for title and URI) | ||
777 | 324 | bindwood.writeMessage("in onItemChanged: " + aProperty + " changed to " + aValue); | ||
778 | 325 | netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead UniversalBrowserWrite"); | ||
779 | 326 | var couch = new CouchDB('bookmarks'); | ||
780 | 327 | var guid = Bindwood.bookmarksService.getItemGUID(aBookmarkId); | ||
781 | 328 | var results = db.query(function(doc) { | ||
782 | 329 | if (doc.application_annotations && | ||
783 | 330 | doc.application_annotations.Firefox && | ||
784 | 331 | doc.application_annotations.Firefox.guid) { | ||
785 | 332 | emit(doc.application_annotations.Firefox.guid, doc); | ||
786 | 333 | } | ||
787 | 334 | }, null, { | ||
788 | 335 | startkey: guid, endkey: guid | ||
789 | 336 | }); | ||
790 | 337 | if (results.rows.length === 0) { | ||
791 | 338 | Bindwood.writeMessage("a bookmark has changed, but this bookmark isn't in CouchDB. this isn't supposed to happen."); | ||
792 | 339 | return; | ||
793 | 340 | } | ||
794 | 341 | Bindwood.writeMessage("We don't actually update Couch here."); | ||
795 | 342 | return; | ||
796 | 343 | |||
797 | 344 | var doc = couch.open(results.rows[0].id); | ||
798 | 345 | doc[aProperty.toString()] = aValue.toString(); | ||
799 | 346 | try { | ||
800 | 347 | var result = couch.save(doc); | ||
801 | 348 | Bindwood.writeMessage("Updated record: " + result.rev + ", setting (" + aProperty.toString() + ") to (" + aValue.toString() + ")"); | ||
802 | 349 | } catch(e) { | ||
803 | 350 | Bindwood.writeMessage("Error '" + e.error + "': " + e.reason); | ||
804 | 351 | } | ||
805 | 352 | return true; | ||
806 | 353 | }, | ||
807 | 354 | onItemVisited: function(aBookmarkId, aVisitID, time) {}, | ||
808 | 355 | onItemMoved: function(aItemId, aOldParent, aOldIndex, aNewParent, aNewIndex) {}, | ||
809 | 356 | //QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsINavBookmarkObserver]) | ||
810 | 357 | } | ||
811 | 358 | }; | ||
812 | 0 | 359 | ||
813 | === added file 'chrome/content/tutorial.html' | |||
814 | --- chrome/content/tutorial.html 1970-01-01 00:00:00 +0000 | |||
815 | +++ chrome/content/tutorial.html 2009-07-02 13:41:07 +0000 | |||
816 | @@ -0,0 +1,8 @@ | |||
817 | 1 | <html> | ||
818 | 2 | <head> | ||
819 | 3 | <title>BindWood Tutorial</title> | ||
820 | 4 | </head> | ||
821 | 5 | <body> | ||
822 | 6 | This is BindWood. | ||
823 | 7 | </body> | ||
824 | 8 | </html> | ||
825 | 0 | 9 | ||
826 | === added directory 'chrome/locale' | |||
827 | === added directory 'chrome/locale/en' | |||
828 | === added file 'chrome/locale/en/bindwood.dtd' | |||
829 | === modified file 'install.rdf' | |||
830 | --- install.rdf 2009-06-30 13:47:50 +0000 | |||
831 | +++ install.rdf 2009-07-03 02:22:26 +0000 | |||
832 | @@ -3,7 +3,7 @@ | |||
833 | 3 | xmlns:em="http://www.mozilla.org/2004/em-rdf#"> | 3 | xmlns:em="http://www.mozilla.org/2004/em-rdf#"> |
834 | 4 | 4 | ||
835 | 5 | <Description about="urn:mozilla:install-manifest"> | 5 | <Description about="urn:mozilla:install-manifest"> |
837 | 6 | <em:id>ubuntuone-firefox-bookmark-sync@ubuntu.com</em:id> | 6 | <em:id>bindwood@ubuntu.com</em:id> |
838 | 7 | <em:version>1.0</em:version> | 7 | <em:version>1.0</em:version> |
839 | 8 | <em:type>2</em:type> | 8 | <em:type>2</em:type> |
840 | 9 | 9 | ||
841 | @@ -18,8 +18,8 @@ | |||
842 | 18 | </em:targetApplication> | 18 | </em:targetApplication> |
843 | 19 | 19 | ||
844 | 20 | <!-- Front End MetaData --> | 20 | <!-- Front End MetaData --> |
847 | 21 | <em:name>UbuntuOne Bookmarks Sync</em:name> | 21 | <em:name>BindWood</em:name> |
848 | 22 | <em:description>An extension to synchronize your bookmarks to UbuntuOne.</em:description> | 22 | <em:description>An extension to synchronize your bookmarks to a local CouchDB.</em:description> |
849 | 23 | <em:creator>Zachery Bir</em:creator> | 23 | <em:creator>Zachery Bir</em:creator> |
850 | 24 | <em:homepageURL>http://launchpad.net/ubuntuone-firefox-bookmark-sync</em:homepageURL> | 24 | <em:homepageURL>http://launchpad.net/ubuntuone-firefox-bookmark-sync</em:homepageURL> |
851 | 25 | </Description> | 25 | </Description> |
Add a design document, providing a more convenient view on your bookmarks