diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index 98624c429cde..c9935e7ae644 100644 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -2001,8 +2001,12 @@ function getShortcutOrURI(aURL, aPostDataRef) var shortcutURL = null; #ifdef MOZ_PLACES_BOOKMARKS var shortcutURI = PlacesUtils.bookmarks.getURIForKeyword(aURL); - if (shortcutURI) + if (shortcutURI) { shortcutURL = shortcutURI.spec; + // get POST data + var postData = PlacesUtils.getPostDataForURI(shortcutURI); + aPostDataRef.value = postData; + } #else shortcutURL = BMSVC.resolveKeyword(aURL, aPostDataRef); #endif @@ -5242,7 +5246,8 @@ function AddKeywordForSearchField() BROWSER_ADD_BM_FEATURES, dialogArgs); #else var description = PlacesUtils.getDescriptionFromDocument(node.ownerDocument); - PlacesUtils.showAddBookmarkUI(makeURI(spec), "", description, null, null, null, ""); + PlacesUtils.showMinimalAddBookmarkUI(makeURI(spec), "", description, null, + null, null, "", postData); #endif } diff --git a/browser/components/places/content/bookmarkProperties.js b/browser/components/places/content/bookmarkProperties.js index 6f25b54f474b..4b8248d15034 100755 --- a/browser/components/places/content/bookmarkProperties.js +++ b/browser/components/places/content/bookmarkProperties.js @@ -58,6 +58,7 @@ * @ defaultInsertionPoint (InsertionPoint JS object) - optional, the * default insertion point for the new item. * @ keyword (String) - optional, the default keyword for the new item. + * @ postData (String) - optional, POST data to accompany the keyword. * Notes: * 1) If |uri| is set for a bookmark/livemark item and |title| isn't, * the dialog will query the history tables for the title associated @@ -132,6 +133,7 @@ var BookmarkPropertiesPanel = { _itemDescription: "", _microsummaries: null, _URIList: null, + _postData: null, // sizeToContent is not usable due to bug 90276, so we'll use resizeTo // instead and cache the bookmarks tree view size. See WSucks in the legacy @@ -223,8 +225,11 @@ var BookmarkPropertiesPanel = { if ("loadBookmarkInSidebar" in dialogInfo) this._loadBookmarkInSidebar = dialogInfo.loadBookmarkInSidebar; - if ("keyword" in dialogInfo) + if ("keyword" in dialogInfo) { this._bookmarkKeyword = dialogInfo.keyword; + if ("postData" in dialogInfo) + this._postData = dialogInfo.postData; + } break; case "folder": @@ -896,9 +901,17 @@ var BookmarkPropertiesPanel = { } var [container, index] = this._getInsertionPointDetails(); - return new PlacesCreateItemTransaction(uri, container, index, - title, keyword, annotations, - childTransactions); + var transactions = [new PlacesCreateItemTransaction(uri, container, index, + title, keyword, + annotations, + childTransactions)]; + + if (this._postData) { + transactions.push(new PlacesEditURIPostDataTransaction(uri, + this._postData)); + } + return new PlacesAggregateTransaction(this._getDialogTitle(), + transactions); }, /** diff --git a/browser/components/places/content/controller.js b/browser/components/places/content/controller.js index d8208622e3ed..cabdfbb25cbe 100755 --- a/browser/components/places/content/controller.js +++ b/browser/components/places/content/controller.js @@ -2093,6 +2093,28 @@ PlacesEditBookmarkKeywordTransaction.prototype = { } }; +/** + * Edit the post data associated with a URI + */ +function PlacesEditURIPostDataTransaction(aURI, aPostData) { + this._uri = aURI; + this._newPostData = aPostData; + this._oldPostData = null; + this.redoTransaction = this.doTransaction; +} +PlacesEditURIPostDataTransaction.prototype = { + __proto__: PlacesBaseTransaction.prototype, + + doTransaction: function PEUPDT_doTransaction() { + this._oldPostData = this.utils.getPostDataForURI(this._uri); + this.utils.setPostDataForURI(this._uri, this._newPostData); + }, + + undoTransaction: function PEUPDT_undoTransaction() { + this.utils.setPostDataForURI(this._uri, this._oldPostData); + } +}; + /** * Edit a live bookmark's site URI. */ diff --git a/browser/components/places/content/utils.js b/browser/components/places/content/utils.js index a5cfe255cfa7..48b1d1b97692 100644 --- a/browser/components/places/content/utils.js +++ b/browser/components/places/content/utils.js @@ -47,6 +47,7 @@ const Cr = Components.results; const LOAD_IN_SIDEBAR_ANNO = "bookmarkProperties/loadInSidebar"; const DESCRIPTION_ANNO = "bookmarkProperties/description"; +const POST_DATA_ANNO = "URIProperties/POSTData"; function QI_node(aNode, aIID) { var result = null; @@ -744,6 +745,8 @@ var PlacesUtils = { * @param [optional] aKeyword * The default keyword for the new bookmark. The keyword field * will be shown in the dialog if this is used. + * @param [optional] aPostData + * POST data for POST-style keywords. * @return true if any transaction has been performed. * * Notes: @@ -758,7 +761,8 @@ var PlacesUtils = { aDefaultInsertionPoint, aShowPicker, aLoadInSidebar, - aKeyword) { + aKeyword, + aPostData) { var info = { action: "add", type: "bookmark" @@ -783,8 +787,11 @@ var PlacesUtils = { if (aLoadInSidebar) info.loadBookmarkInSidebar = true; - if (typeof(aKeyword) == "string") + if (typeof(aKeyword) == "string") { info.keyword = aKeyword; + if (typeof(aPostData) == "string") + info.postData = aPostData; + } return this._showBookmarkDialog(info); }, @@ -803,11 +810,11 @@ var PlacesUtils = { showMinimalAddBookmarkUI: function PU_showMinimalAddBookmarkUI(aURI, aTitle, aDescription, aDefaultInsertionPoint, aShowPicker, - aLoadInSidebar, aKeyword) { + aLoadInSidebar, aKeyword, aPostData) { var info = { action: "add", type: "bookmark", - hiddenRows: ["location", "keyword", "description", "load in sidebar"] + hiddenRows: ["location", "description", "load in sidebar"] }; if (aURI) info.uri = aURI; @@ -828,8 +835,11 @@ var PlacesUtils = { if (aLoadInSidebar) info.loadBookmarkInSidebar = true; - if (typeof(aKeyword) == "string") + if (typeof(aKeyword) == "string") { info.keyword = aKeyword; + if (typeof(aPostData) == "string") + info.postData = aPostData; + } else info.hiddenRows.push("keyword"); @@ -1313,6 +1323,33 @@ var PlacesUtils = { this._toolbarFolderId = this.bookmarks.toolbarFolder; return this._toolbarFolderId; + }, + + /** + * Set the POST data associated with a URI, if any. + * Used by POST keywords. + * @param aURI + * @returns string of POST data + */ + setPostDataForURI: function PU_setPostDataForURI(aURI, aPostData) { + const annos = this.annotations; + if (aPostData) + annos.setPageAnnotationString(aURI, POST_DATA_ANNO, aPostData, 0, 0); + else if (annos.pageHasAnnotation(aURI, POST_DATA_ANNO)) + annos.removePageAnnotation(aURI, POST_DATA_ANNO); + }, + + /** + * Get the POST data associated with a bookmark, if any. + * @param aURI + * @returns string of POST data if set for aURI. null otherwise. + */ + getPostDataForURI: function PU_getPostDataForURI(aURI) { + const annos = this.annotations; + if (annos.pageHasAnnotation(aURI, POST_DATA_ANNO)) + return annos.getPageAnnotationString(aURI, POST_DATA_ANNO); + + return null; } }; diff --git a/browser/components/places/src/nsPlacesImportExportService.cpp b/browser/components/places/src/nsPlacesImportExportService.cpp index cb6821136b71..59081de05805 100644 --- a/browser/components/places/src/nsPlacesImportExportService.cpp +++ b/browser/components/places/src/nsPlacesImportExportService.cpp @@ -115,10 +115,12 @@ static NS_DEFINE_CID(kParserCID, NS_PARSER_CID); #define KEY_ICON_LOWER "icon" #define KEY_ICON_URI_LOWER "icon_uri" #define KEY_SHORTCUTURL_LOWER "shortcuturl" +#define KEY_POST_DATA_LOWER "post_data" #define KEY_ID_LOWER "id" #define LOAD_IN_SIDEBAR_ANNO NS_LITERAL_CSTRING("bookmarkProperties/loadInSidebar") #define DESCRIPTION_ANNO NS_LITERAL_CSTRING("bookmarkProperties/description") +#define POST_DATA_ANNO NS_LITERAL_CSTRING("URIProperties/POSTData") #define BOOKMARKSS_MENU_ICON_URI "chrome://browser/skin/places/bookmarksMenu.png" #define BOOKMARKSS_TOOLBAR_ICON_URI "chrome://browser/skin/places/bookmarksToolbar.png" @@ -737,6 +739,7 @@ BookmarkContentSink::HandleLinkBegin(const nsIParserNode& node) nsAutoString iconUri; nsAutoString lastCharset; nsAutoString keyword; + nsAutoString postData; nsAutoString webPanel; nsAutoString id; PRInt32 attrCount = node.GetAttributeCount(); @@ -754,6 +757,8 @@ BookmarkContentSink::HandleLinkBegin(const nsIParserNode& node) lastCharset = node.GetValueAt(i); } else if (key.LowerCaseEqualsLiteral(KEY_SHORTCUTURL_LOWER)) { keyword = node.GetValueAt(i); + } else if (key.LowerCaseEqualsLiteral(KEY_POST_DATA_LOWER)) { + postData = node.GetValueAt(i); } else if (key.LowerCaseEqualsLiteral(KEY_WEB_PANEL_LOWER)) { webPanel = node.GetValueAt(i); } else if (key.LowerCaseEqualsLiteral(KEY_ID_LOWER)) { @@ -766,6 +771,7 @@ BookmarkContentSink::HandleLinkBegin(const nsIParserNode& node) iconUri.Trim(kWhitespace); lastCharset.Trim(kWhitespace); keyword.Trim(kWhitespace); + postData.Trim(kWhitespace); webPanel.Trim(kWhitespace); id.Trim(kWhitespace); @@ -831,9 +837,16 @@ BookmarkContentSink::HandleLinkBegin(const nsIParserNode& node) } // save the keyword, ignore errors - if (!keyword.IsEmpty()) + if (!keyword.IsEmpty()) { mBookmarksService->SetKeywordForBookmark(frame.mPreviousId, keyword); + // post data + if (!postData.IsEmpty()) { + mAnnotationService->SetPageAnnotationString(frame.mPreviousLink, POST_DATA_ANNO, + postData, 0, + nsIAnnotationService::EXPIRE_NEVER); + } + } if (webPanel.LowerCaseEqualsLiteral("true")) { // set load-in-sidebar annotation for the bookmark @@ -1243,6 +1256,7 @@ static const char kHrefAttribute[] = " HREF=\""; static const char kFeedURIAttribute[] = " FEEDURL=\""; static const char kWebPanelAttribute[] = " WEB_PANEL=\"true\""; static const char kKeywordAttribute[] = " SHORTCUTURL=\""; +static const char kPostDataAttribute[] = " POST_DATA=\""; static const char kIdAttribute[] = " ID=\""; // WriteContainerPrologue @@ -1592,6 +1606,30 @@ nsPlacesImportExportService::WriteItem(nsINavHistoryResultNode* aItem, NS_ENSURE_SUCCESS(rv, rv); } + // post data + nsCOMPtr pageURI; + rv = NS_NewURI(getter_AddRefs(pageURI), uri, nsnull); + NS_ENSURE_SUCCESS(rv, rv); + + PRBool hasPostData; + rv = mAnnotationService->PageHasAnnotation(pageURI, POST_DATA_ANNO, + &hasPostData); + NS_ENSURE_SUCCESS(rv, rv); + if (hasPostData) { + nsAutoString postData; + rv = mAnnotationService->GetPageAnnotationString(pageURI, POST_DATA_ANNO, + postData); + NS_ENSURE_SUCCESS(rv, rv); + rv = aOutput->Write(kPostDataAttribute, sizeof(kPostDataAttribute)-1, &dummy); + NS_ENSURE_SUCCESS(rv, rv); + char* escapedPostData = nsEscapeHTML(NS_ConvertUTF16toUTF8(postData).get()); + rv = aOutput->Write(escapedPostData, strlen(escapedPostData), &dummy); + nsMemory::Free(escapedPostData); + NS_ENSURE_SUCCESS(rv, rv); + rv = aOutput->Write(kQuoteStr, sizeof(kQuoteStr)-1, &dummy); + NS_ENSURE_SUCCESS(rv, rv); + } + // Write WEB_PANEL="true" if the load-in-sidebar annotation is set for the // item PRBool loadInSidebar = PR_FALSE;