|
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 /** |
|
7 * The panel is initialized based on data given in the js object passed |
|
8 * as window.arguments[0]. The object must have the following fields set: |
|
9 * @ action (String). Possible values: |
|
10 * - "add" - for adding a new item. |
|
11 * @ type (String). Possible values: |
|
12 * - "bookmark" |
|
13 * @ loadBookmarkInSidebar - optional, the default state for the |
|
14 * "Load this bookmark in the sidebar" field. |
|
15 * - "folder" |
|
16 * @ URIList (Array of nsIURI objects) - optional, list of uris to |
|
17 * be bookmarked under the new folder. |
|
18 * - "livemark" |
|
19 * @ uri (nsIURI object) - optional, the default uri for the new item. |
|
20 * The property is not used for the "folder with items" type. |
|
21 * @ title (String) - optional, the default title for the new item. |
|
22 * @ description (String) - optional, the default description for the new |
|
23 * item. |
|
24 * @ defaultInsertionPoint (InsertionPoint JS object) - optional, the |
|
25 * default insertion point for the new item. |
|
26 * @ keyword (String) - optional, the default keyword for the new item. |
|
27 * @ postData (String) - optional, POST data to accompany the keyword. |
|
28 * @ charSet (String) - optional, character-set to accompany the keyword. |
|
29 * Notes: |
|
30 * 1) If |uri| is set for a bookmark/livemark item and |title| isn't, |
|
31 * the dialog will query the history tables for the title associated |
|
32 * with the given uri. If the dialog is set to adding a folder with |
|
33 * bookmark items under it (see URIList), a default static title is |
|
34 * used ("[Folder Name]"). |
|
35 * 2) The index field of the default insertion point is ignored if |
|
36 * the folder picker is shown. |
|
37 * - "edit" - for editing a bookmark item or a folder. |
|
38 * @ type (String). Possible values: |
|
39 * - "bookmark" |
|
40 * @ itemId (Integer) - the id of the bookmark item. |
|
41 * - "folder" (also applies to livemarks) |
|
42 * @ itemId (Integer) - the id of the folder. |
|
43 * @ hiddenRows (Strings array) - optional, list of rows to be hidden |
|
44 * regardless of the item edited or added by the dialog. |
|
45 * Possible values: |
|
46 * - "title" |
|
47 * - "location" |
|
48 * - "description" |
|
49 * - "keyword" |
|
50 * - "tags" |
|
51 * - "loadInSidebar" |
|
52 * - "feedLocation" |
|
53 * - "siteLocation" |
|
54 * - "folderPicker" - hides both the tree and the menu. |
|
55 * @ readOnly (Boolean) - optional, states if the panel should be read-only |
|
56 * |
|
57 * window.arguments[0].performed is set to true if any transaction has |
|
58 * been performed by the dialog. |
|
59 */ |
|
60 |
|
61 Components.utils.import('resource://gre/modules/XPCOMUtils.jsm'); |
|
62 XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils", |
|
63 "resource://gre/modules/PrivateBrowsingUtils.jsm"); |
|
64 |
|
65 const BOOKMARK_ITEM = 0; |
|
66 const BOOKMARK_FOLDER = 1; |
|
67 const LIVEMARK_CONTAINER = 2; |
|
68 |
|
69 const ACTION_EDIT = 0; |
|
70 const ACTION_ADD = 1; |
|
71 |
|
72 var BookmarkPropertiesPanel = { |
|
73 |
|
74 /** UI Text Strings */ |
|
75 __strings: null, |
|
76 get _strings() { |
|
77 if (!this.__strings) { |
|
78 this.__strings = document.getElementById("stringBundle"); |
|
79 } |
|
80 return this.__strings; |
|
81 }, |
|
82 |
|
83 _action: null, |
|
84 _itemType: null, |
|
85 _itemId: -1, |
|
86 _uri: null, |
|
87 _loadInSidebar: false, |
|
88 _title: "", |
|
89 _description: "", |
|
90 _URIs: [], |
|
91 _keyword: "", |
|
92 _postData: null, |
|
93 _charSet: "", |
|
94 _feedURI: null, |
|
95 _siteURI: null, |
|
96 |
|
97 _defaultInsertionPoint: null, |
|
98 _hiddenRows: [], |
|
99 _batching: false, |
|
100 _readOnly: false, |
|
101 |
|
102 /** |
|
103 * This method returns the correct label for the dialog's "accept" |
|
104 * button based on the variant of the dialog. |
|
105 */ |
|
106 _getAcceptLabel: function BPP__getAcceptLabel() { |
|
107 if (this._action == ACTION_ADD) { |
|
108 if (this._URIs.length) |
|
109 return this._strings.getString("dialogAcceptLabelAddMulti"); |
|
110 |
|
111 if (this._itemType == LIVEMARK_CONTAINER) |
|
112 return this._strings.getString("dialogAcceptLabelAddLivemark"); |
|
113 |
|
114 if (this._dummyItem || this._loadInSidebar) |
|
115 return this._strings.getString("dialogAcceptLabelAddItem"); |
|
116 |
|
117 return this._strings.getString("dialogAcceptLabelSaveItem"); |
|
118 } |
|
119 return this._strings.getString("dialogAcceptLabelEdit"); |
|
120 }, |
|
121 |
|
122 /** |
|
123 * This method returns the correct title for the current variant |
|
124 * of this dialog. |
|
125 */ |
|
126 _getDialogTitle: function BPP__getDialogTitle() { |
|
127 if (this._action == ACTION_ADD) { |
|
128 if (this._itemType == BOOKMARK_ITEM) |
|
129 return this._strings.getString("dialogTitleAddBookmark"); |
|
130 if (this._itemType == LIVEMARK_CONTAINER) |
|
131 return this._strings.getString("dialogTitleAddLivemark"); |
|
132 |
|
133 // add folder |
|
134 NS_ASSERT(this._itemType == BOOKMARK_FOLDER, "Unknown item type"); |
|
135 if (this._URIs.length) |
|
136 return this._strings.getString("dialogTitleAddMulti"); |
|
137 |
|
138 return this._strings.getString("dialogTitleAddFolder"); |
|
139 } |
|
140 if (this._action == ACTION_EDIT) { |
|
141 return this._strings.getFormattedString("dialogTitleEdit", [this._title]); |
|
142 } |
|
143 return ""; |
|
144 }, |
|
145 |
|
146 /** |
|
147 * Determines the initial data for the item edited or added by this dialog |
|
148 */ |
|
149 _determineItemInfo: function BPP__determineItemInfo() { |
|
150 var dialogInfo = window.arguments[0]; |
|
151 this._action = dialogInfo.action == "add" ? ACTION_ADD : ACTION_EDIT; |
|
152 this._hiddenRows = dialogInfo.hiddenRows ? dialogInfo.hiddenRows : []; |
|
153 if (this._action == ACTION_ADD) { |
|
154 NS_ASSERT("type" in dialogInfo, "missing type property for add action"); |
|
155 |
|
156 if ("title" in dialogInfo) |
|
157 this._title = dialogInfo.title; |
|
158 |
|
159 if ("defaultInsertionPoint" in dialogInfo) { |
|
160 this._defaultInsertionPoint = dialogInfo.defaultInsertionPoint; |
|
161 } |
|
162 else |
|
163 this._defaultInsertionPoint = |
|
164 new InsertionPoint(PlacesUtils.bookmarksMenuFolderId, |
|
165 PlacesUtils.bookmarks.DEFAULT_INDEX, |
|
166 Ci.nsITreeView.DROP_ON); |
|
167 |
|
168 switch (dialogInfo.type) { |
|
169 case "bookmark": |
|
170 this._itemType = BOOKMARK_ITEM; |
|
171 if ("uri" in dialogInfo) { |
|
172 NS_ASSERT(dialogInfo.uri instanceof Ci.nsIURI, |
|
173 "uri property should be a uri object"); |
|
174 this._uri = dialogInfo.uri; |
|
175 if (typeof(this._title) != "string") { |
|
176 this._title = this._getURITitleFromHistory(this._uri) || |
|
177 this._uri.spec; |
|
178 } |
|
179 } |
|
180 else { |
|
181 this._uri = PlacesUtils._uri("about:blank"); |
|
182 this._title = this._strings.getString("newBookmarkDefault"); |
|
183 this._dummyItem = true; |
|
184 } |
|
185 |
|
186 if ("loadBookmarkInSidebar" in dialogInfo) |
|
187 this._loadInSidebar = dialogInfo.loadBookmarkInSidebar; |
|
188 |
|
189 if ("keyword" in dialogInfo) { |
|
190 this._keyword = dialogInfo.keyword; |
|
191 this._isAddKeywordDialog = true; |
|
192 if ("postData" in dialogInfo) |
|
193 this._postData = dialogInfo.postData; |
|
194 if ("charSet" in dialogInfo) |
|
195 this._charSet = dialogInfo.charSet; |
|
196 } |
|
197 break; |
|
198 |
|
199 case "folder": |
|
200 this._itemType = BOOKMARK_FOLDER; |
|
201 if (!this._title) { |
|
202 if ("URIList" in dialogInfo) { |
|
203 this._title = this._strings.getString("bookmarkAllTabsDefault"); |
|
204 this._URIs = dialogInfo.URIList; |
|
205 } |
|
206 else |
|
207 this._title = this._strings.getString("newFolderDefault"); |
|
208 this._dummyItem = true; |
|
209 } |
|
210 break; |
|
211 |
|
212 case "livemark": |
|
213 this._itemType = LIVEMARK_CONTAINER; |
|
214 if ("feedURI" in dialogInfo) |
|
215 this._feedURI = dialogInfo.feedURI; |
|
216 if ("siteURI" in dialogInfo) |
|
217 this._siteURI = dialogInfo.siteURI; |
|
218 |
|
219 if (!this._title) { |
|
220 if (this._feedURI) { |
|
221 this._title = this._getURITitleFromHistory(this._feedURI) || |
|
222 this._feedURI.spec; |
|
223 } |
|
224 else |
|
225 this._title = this._strings.getString("newLivemarkDefault"); |
|
226 } |
|
227 } |
|
228 |
|
229 if ("description" in dialogInfo) |
|
230 this._description = dialogInfo.description; |
|
231 } |
|
232 else { // edit |
|
233 NS_ASSERT("itemId" in dialogInfo); |
|
234 this._itemId = dialogInfo.itemId; |
|
235 this._title = PlacesUtils.bookmarks.getItemTitle(this._itemId); |
|
236 this._readOnly = !!dialogInfo.readOnly; |
|
237 |
|
238 switch (dialogInfo.type) { |
|
239 case "bookmark": |
|
240 this._itemType = BOOKMARK_ITEM; |
|
241 |
|
242 this._uri = PlacesUtils.bookmarks.getBookmarkURI(this._itemId); |
|
243 // keyword |
|
244 this._keyword = PlacesUtils.bookmarks |
|
245 .getKeywordForBookmark(this._itemId); |
|
246 // Load In Sidebar |
|
247 this._loadInSidebar = PlacesUtils.annotations |
|
248 .itemHasAnnotation(this._itemId, |
|
249 PlacesUIUtils.LOAD_IN_SIDEBAR_ANNO); |
|
250 break; |
|
251 |
|
252 case "folder": |
|
253 this._itemType = BOOKMARK_FOLDER; |
|
254 PlacesUtils.livemarks.getLivemark({ id: this._itemId }) |
|
255 .then(aLivemark => { |
|
256 this._itemType = LIVEMARK_CONTAINER; |
|
257 this._feedURI = aLivemark.feedURI; |
|
258 this._siteURI = aLivemark.siteURI; |
|
259 this._fillEditProperties(); |
|
260 |
|
261 let acceptButton = document.documentElement.getButton("accept"); |
|
262 acceptButton.disabled = !this._inputIsValid(); |
|
263 |
|
264 let newHeight = window.outerHeight + |
|
265 this._element("descriptionField").boxObject.height; |
|
266 window.resizeTo(window.outerWidth, newHeight); |
|
267 }, () => undefined); |
|
268 |
|
269 break; |
|
270 } |
|
271 |
|
272 // Description |
|
273 if (PlacesUtils.annotations |
|
274 .itemHasAnnotation(this._itemId, PlacesUIUtils.DESCRIPTION_ANNO)) { |
|
275 this._description = PlacesUtils.annotations |
|
276 .getItemAnnotation(this._itemId, |
|
277 PlacesUIUtils.DESCRIPTION_ANNO); |
|
278 } |
|
279 } |
|
280 }, |
|
281 |
|
282 /** |
|
283 * This method returns the title string corresponding to a given URI. |
|
284 * If none is available from the bookmark service (probably because |
|
285 * the given URI doesn't appear in bookmarks or history), we synthesize |
|
286 * a title from the first 100 characters of the URI. |
|
287 * |
|
288 * @param aURI |
|
289 * nsIURI object for which we want the title |
|
290 * |
|
291 * @returns a title string |
|
292 */ |
|
293 _getURITitleFromHistory: function BPP__getURITitleFromHistory(aURI) { |
|
294 NS_ASSERT(aURI instanceof Ci.nsIURI); |
|
295 |
|
296 // get the title from History |
|
297 return PlacesUtils.history.getPageTitle(aURI); |
|
298 }, |
|
299 |
|
300 /** |
|
301 * This method should be called by the onload of the Bookmark Properties |
|
302 * dialog to initialize the state of the panel. |
|
303 */ |
|
304 onDialogLoad: function BPP_onDialogLoad() { |
|
305 this._determineItemInfo(); |
|
306 |
|
307 document.title = this._getDialogTitle(); |
|
308 var acceptButton = document.documentElement.getButton("accept"); |
|
309 acceptButton.label = this._getAcceptLabel(); |
|
310 |
|
311 this._beginBatch(); |
|
312 |
|
313 switch (this._action) { |
|
314 case ACTION_EDIT: |
|
315 this._fillEditProperties(); |
|
316 acceptButton.disabled = this._readOnly; |
|
317 break; |
|
318 case ACTION_ADD: |
|
319 this._fillAddProperties(); |
|
320 // if this is an uri related dialog disable accept button until |
|
321 // the user fills an uri value. |
|
322 if (this._itemType == BOOKMARK_ITEM) |
|
323 acceptButton.disabled = !this._inputIsValid(); |
|
324 break; |
|
325 } |
|
326 |
|
327 // When collapsible elements change their collapsed attribute we must |
|
328 // resize the dialog. |
|
329 // sizeToContent is not usable due to bug 90276, so we'll use resizeTo |
|
330 // instead and cache the element size. See WSucks in the legacy |
|
331 // UI code (addBookmark2.js). |
|
332 if (!this._element("tagsRow").collapsed) { |
|
333 this._element("tagsSelectorRow") |
|
334 .addEventListener("DOMAttrModified", this, false); |
|
335 } |
|
336 if (!this._element("folderRow").collapsed) { |
|
337 this._element("folderTreeRow") |
|
338 .addEventListener("DOMAttrModified", this, false); |
|
339 } |
|
340 |
|
341 if (!this._readOnly) { |
|
342 // Listen on uri fields to enable accept button if input is valid |
|
343 if (this._itemType == BOOKMARK_ITEM) { |
|
344 this._element("locationField") |
|
345 .addEventListener("input", this, false); |
|
346 if (this._isAddKeywordDialog) { |
|
347 this._element("keywordField") |
|
348 .addEventListener("input", this, false); |
|
349 } |
|
350 } |
|
351 else if (this._itemType == LIVEMARK_CONTAINER) { |
|
352 this._element("feedLocationField") |
|
353 .addEventListener("input", this, false); |
|
354 this._element("siteLocationField") |
|
355 .addEventListener("input", this, false); |
|
356 } |
|
357 } |
|
358 |
|
359 window.sizeToContent(); |
|
360 }, |
|
361 |
|
362 // nsIDOMEventListener |
|
363 _elementsHeight: [], |
|
364 handleEvent: function BPP_handleEvent(aEvent) { |
|
365 var target = aEvent.target; |
|
366 switch (aEvent.type) { |
|
367 case "input": |
|
368 if (target.id == "editBMPanel_locationField" || |
|
369 target.id == "editBMPanel_feedLocationField" || |
|
370 target.id == "editBMPanel_siteLocationField" || |
|
371 target.id == "editBMPanel_keywordField") { |
|
372 // Check uri fields to enable accept button if input is valid |
|
373 document.documentElement |
|
374 .getButton("accept").disabled = !this._inputIsValid(); |
|
375 } |
|
376 break; |
|
377 |
|
378 case "DOMAttrModified": |
|
379 // this is called when collapsing a node, but also its direct children, |
|
380 // we only need to resize when the original node changes. |
|
381 if ((target.id == "editBMPanel_tagsSelectorRow" || |
|
382 target.id == "editBMPanel_folderTreeRow") && |
|
383 aEvent.attrName == "collapsed" && |
|
384 target == aEvent.originalTarget) { |
|
385 var id = target.id; |
|
386 var newHeight = window.outerHeight; |
|
387 if (aEvent.newValue) // is collapsed |
|
388 newHeight -= this._elementsHeight[id]; |
|
389 else { |
|
390 this._elementsHeight[id] = target.boxObject.height; |
|
391 newHeight += this._elementsHeight[id]; |
|
392 } |
|
393 |
|
394 window.resizeTo(window.outerWidth, newHeight); |
|
395 } |
|
396 break; |
|
397 } |
|
398 }, |
|
399 |
|
400 _beginBatch: function BPP__beginBatch() { |
|
401 if (this._batching) |
|
402 return; |
|
403 |
|
404 PlacesUtils.transactionManager.beginBatch(null); |
|
405 this._batching = true; |
|
406 }, |
|
407 |
|
408 _endBatch: function BPP__endBatch() { |
|
409 if (!this._batching) |
|
410 return; |
|
411 |
|
412 PlacesUtils.transactionManager.endBatch(false); |
|
413 this._batching = false; |
|
414 }, |
|
415 |
|
416 _fillEditProperties: function BPP__fillEditProperties() { |
|
417 gEditItemOverlay.initPanel(this._itemId, |
|
418 { hiddenRows: this._hiddenRows, |
|
419 forceReadOnly: this._readOnly }); |
|
420 }, |
|
421 |
|
422 _fillAddProperties: function BPP__fillAddProperties() { |
|
423 this._createNewItem(); |
|
424 // Edit the new item |
|
425 gEditItemOverlay.initPanel(this._itemId, |
|
426 { hiddenRows: this._hiddenRows }); |
|
427 // Empty location field if the uri is about:blank, this way inserting a new |
|
428 // url will be easier for the user, Accept button will be automatically |
|
429 // disabled by the input listener until the user fills the field. |
|
430 var locationField = this._element("locationField"); |
|
431 if (locationField.value == "about:blank") |
|
432 locationField.value = ""; |
|
433 }, |
|
434 |
|
435 // nsISupports |
|
436 QueryInterface: function BPP_QueryInterface(aIID) { |
|
437 if (aIID.equals(Ci.nsIDOMEventListener) || |
|
438 aIID.equals(Ci.nsISupports)) |
|
439 return this; |
|
440 |
|
441 throw Cr.NS_NOINTERFACE; |
|
442 }, |
|
443 |
|
444 _element: function BPP__element(aID) { |
|
445 return document.getElementById("editBMPanel_" + aID); |
|
446 }, |
|
447 |
|
448 onDialogUnload: function BPP_onDialogUnload() { |
|
449 // gEditItemOverlay does not exist anymore here, so don't rely on it. |
|
450 // Calling removeEventListener with arguments which do not identify any |
|
451 // currently registered EventListener on the EventTarget has no effect. |
|
452 this._element("tagsSelectorRow") |
|
453 .removeEventListener("DOMAttrModified", this, false); |
|
454 this._element("folderTreeRow") |
|
455 .removeEventListener("DOMAttrModified", this, false); |
|
456 this._element("locationField") |
|
457 .removeEventListener("input", this, false); |
|
458 this._element("feedLocationField") |
|
459 .removeEventListener("input", this, false); |
|
460 this._element("siteLocationField") |
|
461 .removeEventListener("input", this, false); |
|
462 }, |
|
463 |
|
464 onDialogAccept: function BPP_onDialogAccept() { |
|
465 // We must blur current focused element to save its changes correctly |
|
466 document.commandDispatcher.focusedElement.blur(); |
|
467 // The order here is important! We have to uninit the panel first, otherwise |
|
468 // late changes could force it to commit more transactions. |
|
469 gEditItemOverlay.uninitPanel(true); |
|
470 gEditItemOverlay = null; |
|
471 this._endBatch(); |
|
472 window.arguments[0].performed = true; |
|
473 }, |
|
474 |
|
475 onDialogCancel: function BPP_onDialogCancel() { |
|
476 // The order here is important! We have to uninit the panel first, otherwise |
|
477 // changes done as part of Undo may change the panel contents and by |
|
478 // that force it to commit more transactions. |
|
479 gEditItemOverlay.uninitPanel(true); |
|
480 gEditItemOverlay = null; |
|
481 this._endBatch(); |
|
482 PlacesUtils.transactionManager.undoTransaction(); |
|
483 window.arguments[0].performed = false; |
|
484 }, |
|
485 |
|
486 /** |
|
487 * This method checks to see if the input fields are in a valid state. |
|
488 * |
|
489 * @returns true if the input is valid, false otherwise |
|
490 */ |
|
491 _inputIsValid: function BPP__inputIsValid() { |
|
492 if (this._itemType == BOOKMARK_ITEM && |
|
493 !this._containsValidURI("locationField")) |
|
494 return false; |
|
495 if (this._isAddKeywordDialog && !this._element("keywordField").value.length) |
|
496 return false; |
|
497 |
|
498 return true; |
|
499 }, |
|
500 |
|
501 /** |
|
502 * Determines whether the XUL textbox with the given ID contains a |
|
503 * string that can be converted into an nsIURI. |
|
504 * |
|
505 * @param aTextboxID |
|
506 * the ID of the textbox element whose contents we'll test |
|
507 * |
|
508 * @returns true if the textbox contains a valid URI string, false otherwise |
|
509 */ |
|
510 _containsValidURI: function BPP__containsValidURI(aTextboxID) { |
|
511 try { |
|
512 var value = this._element(aTextboxID).value; |
|
513 if (value) { |
|
514 PlacesUIUtils.createFixedURI(value); |
|
515 return true; |
|
516 } |
|
517 } catch (e) { } |
|
518 return false; |
|
519 }, |
|
520 |
|
521 /** |
|
522 * [New Item Mode] Get the insertion point details for the new item, given |
|
523 * dialog state and opening arguments. |
|
524 * |
|
525 * The container-identifier and insertion-index are returned separately in |
|
526 * the form of [containerIdentifier, insertionIndex] |
|
527 */ |
|
528 _getInsertionPointDetails: function BPP__getInsertionPointDetails() { |
|
529 var containerId = this._defaultInsertionPoint.itemId; |
|
530 var indexInContainer = this._defaultInsertionPoint.index; |
|
531 |
|
532 return [containerId, indexInContainer]; |
|
533 }, |
|
534 |
|
535 /** |
|
536 * Returns a transaction for creating a new bookmark item representing the |
|
537 * various fields and opening arguments of the dialog. |
|
538 */ |
|
539 _getCreateNewBookmarkTransaction: |
|
540 function BPP__getCreateNewBookmarkTransaction(aContainer, aIndex) { |
|
541 var annotations = []; |
|
542 var childTransactions = []; |
|
543 |
|
544 if (this._description) { |
|
545 let annoObj = { name : PlacesUIUtils.DESCRIPTION_ANNO, |
|
546 type : Ci.nsIAnnotationService.TYPE_STRING, |
|
547 flags : 0, |
|
548 value : this._description, |
|
549 expires: Ci.nsIAnnotationService.EXPIRE_NEVER }; |
|
550 let editItemTxn = new PlacesSetItemAnnotationTransaction(-1, annoObj); |
|
551 childTransactions.push(editItemTxn); |
|
552 } |
|
553 |
|
554 if (this._loadInSidebar) { |
|
555 let annoObj = { name : PlacesUIUtils.LOAD_IN_SIDEBAR_ANNO, |
|
556 value : true }; |
|
557 let setLoadTxn = new PlacesSetItemAnnotationTransaction(-1, annoObj); |
|
558 childTransactions.push(setLoadTxn); |
|
559 } |
|
560 |
|
561 if (this._postData) { |
|
562 let postDataTxn = new PlacesEditBookmarkPostDataTransaction(-1, this._postData); |
|
563 childTransactions.push(postDataTxn); |
|
564 } |
|
565 |
|
566 //XXX TODO: this should be in a transaction! |
|
567 if (this._charSet && !PrivateBrowsingUtils.isWindowPrivate(window)) |
|
568 PlacesUtils.setCharsetForURI(this._uri, this._charSet); |
|
569 |
|
570 let createTxn = new PlacesCreateBookmarkTransaction(this._uri, |
|
571 aContainer, |
|
572 aIndex, |
|
573 this._title, |
|
574 this._keyword, |
|
575 annotations, |
|
576 childTransactions); |
|
577 |
|
578 return new PlacesAggregatedTransaction(this._getDialogTitle(), |
|
579 [createTxn]); |
|
580 }, |
|
581 |
|
582 /** |
|
583 * Returns a childItems-transactions array representing the URIList with |
|
584 * which the dialog has been opened. |
|
585 */ |
|
586 _getTransactionsForURIList: function BPP__getTransactionsForURIList() { |
|
587 var transactions = []; |
|
588 for (var i = 0; i < this._URIs.length; ++i) { |
|
589 var uri = this._URIs[i]; |
|
590 var title = this._getURITitleFromHistory(uri); |
|
591 var createTxn = new PlacesCreateBookmarkTransaction(uri, -1, |
|
592 PlacesUtils.bookmarks.DEFAULT_INDEX, |
|
593 title); |
|
594 transactions.push(createTxn); |
|
595 } |
|
596 return transactions; |
|
597 }, |
|
598 |
|
599 /** |
|
600 * Returns a transaction for creating a new folder item representing the |
|
601 * various fields and opening arguments of the dialog. |
|
602 */ |
|
603 _getCreateNewFolderTransaction: |
|
604 function BPP__getCreateNewFolderTransaction(aContainer, aIndex) { |
|
605 var annotations = []; |
|
606 var childItemsTransactions; |
|
607 if (this._URIs.length) |
|
608 childItemsTransactions = this._getTransactionsForURIList(); |
|
609 |
|
610 if (this._description) |
|
611 annotations.push(this._getDescriptionAnnotation(this._description)); |
|
612 |
|
613 return new PlacesCreateFolderTransaction(this._title, aContainer, |
|
614 aIndex, annotations, |
|
615 childItemsTransactions); |
|
616 }, |
|
617 |
|
618 /** |
|
619 * Returns a transaction for creating a new live-bookmark item representing |
|
620 * the various fields and opening arguments of the dialog. |
|
621 */ |
|
622 _getCreateNewLivemarkTransaction: |
|
623 function BPP__getCreateNewLivemarkTransaction(aContainer, aIndex) { |
|
624 return new PlacesCreateLivemarkTransaction(this._feedURI, this._siteURI, |
|
625 this._title, |
|
626 aContainer, aIndex); |
|
627 }, |
|
628 |
|
629 /** |
|
630 * Dialog-accept code-path for creating a new item (any type) |
|
631 */ |
|
632 _createNewItem: function BPP__getCreateItemTransaction() { |
|
633 var [container, index] = this._getInsertionPointDetails(); |
|
634 var txn; |
|
635 |
|
636 switch (this._itemType) { |
|
637 case BOOKMARK_FOLDER: |
|
638 txn = this._getCreateNewFolderTransaction(container, index); |
|
639 break; |
|
640 case LIVEMARK_CONTAINER: |
|
641 txn = this._getCreateNewLivemarkTransaction(container, index); |
|
642 break; |
|
643 default: // BOOKMARK_ITEM |
|
644 txn = this._getCreateNewBookmarkTransaction(container, index); |
|
645 } |
|
646 |
|
647 PlacesUtils.transactionManager.doTransaction(txn); |
|
648 this._itemId = PlacesUtils.bookmarks.getIdForItemAt(container, index); |
|
649 } |
|
650 }; |