mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-02 01:48:05 +00:00
Bug 613477 - Make the primary Star UI async.
r=sdwilsh ui-r=limi a=blocking
This commit is contained in:
parent
b82341a3bb
commit
ac635aae45
@ -23,6 +23,7 @@
|
||||
# Joe Hughes <joe@retrovirus.com>
|
||||
# Asaf Romano <mano@mozilla.com>
|
||||
# Ehsan Akhgari <ehsan.akhgari@gmail.com>
|
||||
# Marco Bonardo <mak77@bonardo.net>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -920,7 +921,8 @@ var PlacesMenuDNDHandler = {
|
||||
|
||||
|
||||
var PlacesStarButton = {
|
||||
init: function PSB_init() {
|
||||
init: function PSB_init()
|
||||
{
|
||||
try {
|
||||
PlacesUtils.bookmarks.addObserver(this, false);
|
||||
} catch(ex) {
|
||||
@ -928,74 +930,139 @@ var PlacesStarButton = {
|
||||
}
|
||||
},
|
||||
|
||||
uninit: function PSB_uninit() {
|
||||
PlacesUtils.bookmarks.removeObserver(this);
|
||||
uninit: function PSB_uninit()
|
||||
{
|
||||
try {
|
||||
PlacesUtils.bookmarks.removeObserver(this);
|
||||
} catch(ex) {}
|
||||
},
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsINavBookmarkObserver]),
|
||||
QueryInterface: XPCOMUtils.generateQI([
|
||||
Ci.nsINavBookmarkObserver
|
||||
]),
|
||||
|
||||
_starred: false,
|
||||
_batching: false,
|
||||
get _starredTooltip()
|
||||
{
|
||||
delete this._starredTooltip;
|
||||
return this._starredTooltip =
|
||||
gNavigatorBundle.getString("starButtonOn.tooltip");
|
||||
},
|
||||
get _unstarredTooltip()
|
||||
{
|
||||
delete this._unstarredTooltip;
|
||||
return this._unstarredTooltip =
|
||||
gNavigatorBundle.getString("starButtonOff.tooltip");
|
||||
},
|
||||
|
||||
updateState: function PSB_updateState() {
|
||||
var starIcon = document.getElementById("star-button");
|
||||
if (!starIcon)
|
||||
updateState: function PSB_updateState()
|
||||
{
|
||||
this._starIcon = document.getElementById("star-button");
|
||||
if (!this._starIcon || gBrowser.currentURI.equals(this._uri)) {
|
||||
return;
|
||||
|
||||
var uri = gBrowser.currentURI;
|
||||
this._starred = uri && (PlacesUtils.getMostRecentBookmarkForURI(uri) != -1 ||
|
||||
PlacesUtils.getMostRecentFolderForFeedURI(uri) != -1);
|
||||
if (this._starred) {
|
||||
starIcon.setAttribute("starred", "true");
|
||||
starIcon.setAttribute("tooltiptext", gNavigatorBundle.getString("starButtonOn.tooltip"));
|
||||
}
|
||||
else {
|
||||
starIcon.removeAttribute("starred");
|
||||
starIcon.setAttribute("tooltiptext", gNavigatorBundle.getString("starButtonOff.tooltip"));
|
||||
|
||||
// Reset tracked values.
|
||||
this._uri = gBrowser.currentURI;
|
||||
this._itemIds = [];
|
||||
|
||||
// Hide the star while we update its state.
|
||||
this._starIcon.hidden = true;
|
||||
|
||||
PlacesUtils.asyncGetBookmarkIds(this._uri, function (aItemIds) {
|
||||
this._itemIds = aItemIds;
|
||||
this._updateStateInternal();
|
||||
// Finally show the star.
|
||||
this._starIcon.hidden = false;
|
||||
}, this);
|
||||
},
|
||||
|
||||
_updateStateInternal: function PSB__updateStateInternal()
|
||||
{
|
||||
if (!this._starIcon) {
|
||||
return;
|
||||
}
|
||||
|
||||
let starred = this._starIcon.hasAttribute("starred");
|
||||
if (this._itemIds.length > 0 && !starred) {
|
||||
this._starIcon.setAttribute("starred", "true");
|
||||
this._starIcon.setAttribute("tooltiptext", this._starredTooltip);
|
||||
}
|
||||
else if (this._itemIds.length == 0 && starred) {
|
||||
this._starIcon.removeAttribute("starred");
|
||||
this._starIcon.setAttribute("tooltiptext", this._unstarredTooltip);
|
||||
}
|
||||
},
|
||||
|
||||
onClick: function PSB_onClick(aEvent) {
|
||||
if (aEvent.button == 0)
|
||||
PlacesCommandHook.bookmarkCurrentPage(this._starred);
|
||||
|
||||
// don't bubble to the textbox so that the address won't be selected
|
||||
onClick: function PSB_onClick(aEvent)
|
||||
{
|
||||
if (aEvent.button == 0) {
|
||||
PlacesCommandHook.bookmarkCurrentPage(this._itemIds.length > 0);
|
||||
}
|
||||
// Don't bubble to the textbox, to avoid unwanted selection of the address.
|
||||
aEvent.stopPropagation();
|
||||
},
|
||||
|
||||
// nsINavBookmarkObserver
|
||||
onBeginUpdateBatch: function PSB_onBeginUpdateBatch() {
|
||||
this._batching = true;
|
||||
// nsINavBookmarkObserver
|
||||
onItemAdded:
|
||||
function PSB_onItemAdded(aItemId, aFolder, aIndex, aItemType, aURI)
|
||||
{
|
||||
if (!this._starIcon) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aURI.equals(this._uri)) {
|
||||
// If a new bookmark has been added to the tracked uri, register it.
|
||||
if (this._itemIds.indexOf(aItemId) == -1) {
|
||||
this._itemIds.push(aItemId);
|
||||
this._updateStateInternal();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onEndUpdateBatch: function PSB_onEndUpdateBatch() {
|
||||
this.updateState();
|
||||
this._batching = false;
|
||||
onItemRemoved:
|
||||
function PSB_onItemRemoved(aItemId, aFolder, aIndex, aItemType)
|
||||
{
|
||||
if (!this._starIcon) {
|
||||
return;
|
||||
}
|
||||
|
||||
let index = this._itemIds.indexOf(aItemId);
|
||||
// If one of the tracked bookmarks has been removed, unregister it.
|
||||
if (index != -1) {
|
||||
this._itemIds.splice(index, 1);
|
||||
this._updateStateInternal();
|
||||
}
|
||||
},
|
||||
|
||||
onItemAdded: function PSB_onItemAdded(aItemId, aFolder, aIndex, aItemType,
|
||||
aURI) {
|
||||
if (!this._batching && !this._starred)
|
||||
this.updateState();
|
||||
onItemChanged:
|
||||
function PSB_onItemChanged(aItemId, aProperty, aIsAnnotationProperty,
|
||||
aNewValue, aLastModified, aItemType)
|
||||
{
|
||||
if (!this._starIcon) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aProperty == "uri") {
|
||||
let index = this._itemIds.indexOf(aItemId);
|
||||
// If the changed bookmark was tracked, check if it is now pointing to
|
||||
// a different uri and unregister it.
|
||||
if (index != -1 && aNewValue != this._uri.spec) {
|
||||
this._itemIds.splice(index, 1);
|
||||
this._updateStateInternal();
|
||||
}
|
||||
// If another bookmark is now pointing to the tracked uri, register it.
|
||||
else if (index == -1 && aNewValue == this._uri.spec) {
|
||||
this._itemIds.push(aItemId);
|
||||
this._updateStateInternal();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onBeforeItemRemoved: function() {},
|
||||
|
||||
onItemRemoved: function PSB_onItemRemoved(aItemId, aFolder, aIndex,
|
||||
aItemType) {
|
||||
if (!this._batching)
|
||||
this.updateState();
|
||||
},
|
||||
|
||||
onItemChanged: function PSB_onItemChanged(aItemId, aProperty,
|
||||
aIsAnnotationProperty, aNewValue,
|
||||
aLastModified, aItemType) {
|
||||
if (!this._batching && aProperty == "uri")
|
||||
this.updateState();
|
||||
},
|
||||
|
||||
onItemVisited: function() {},
|
||||
onItemMoved: function() {}
|
||||
onBeginUpdateBatch: function () {},
|
||||
onEndUpdateBatch: function () {},
|
||||
onBeforeItemRemoved: function () {},
|
||||
onItemVisited: function () {},
|
||||
onItemMoved: function () {}
|
||||
};
|
||||
|
||||
|
||||
|
@ -572,6 +572,7 @@
|
||||
<hbox id="urlbar-icons">
|
||||
<image id="star-button"
|
||||
class="urlbar-icon"
|
||||
hidden="true"
|
||||
onclick="PlacesStarButton.onClick(event);"/>
|
||||
<image id="go-button"
|
||||
class="urlbar-icon"
|
||||
|
@ -31,28 +31,47 @@ function invokeUsingStarButton(phase) {
|
||||
}
|
||||
|
||||
var testURL = "data:text/plain,Content";
|
||||
var bookmarkId;
|
||||
|
||||
function add_bookmark(aURI, aTitle) {
|
||||
return PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
|
||||
aURI, PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
aTitle);
|
||||
}
|
||||
|
||||
// test bug 432599
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.selectedBrowser.addEventListener("load", initTest, true);
|
||||
gBrowser.selectedBrowser.addEventListener("load", function () {
|
||||
gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
|
||||
waitForStarChange(false, initTest);
|
||||
}, true);
|
||||
|
||||
content.location = testURL;
|
||||
}
|
||||
|
||||
let invokers = [invokeUsingStarButton, invokeUsingCtrlD];
|
||||
let currentInvoker = 0;
|
||||
|
||||
function initTest() {
|
||||
gBrowser.selectedBrowser.removeEventListener("load", initTest, true);
|
||||
// first, bookmark the page
|
||||
Application.bookmarks.toolbar.addBookmark("Bug 432599 Test", makeURI(testURL));
|
||||
// First, bookmark the page.
|
||||
bookmarkId = add_bookmark(makeURI(testURL), "Bug 432599 Test");
|
||||
|
||||
checkBookmarksPanel(invokers[currentInvoker], 1);
|
||||
}
|
||||
|
||||
function waitForStarChange(aValue, aCallback) {
|
||||
let starButton = document.getElementById("star-button");
|
||||
if (starButton.hidden || starButton.hasAttribute("starred") != aValue) {
|
||||
info("Waiting for star button change.");
|
||||
setTimeout(arguments.callee, 50, aValue, aCallback);
|
||||
return;
|
||||
}
|
||||
aCallback();
|
||||
}
|
||||
|
||||
let invokers = [invokeUsingStarButton, invokeUsingCtrlD];
|
||||
let currentInvoker = 0;
|
||||
|
||||
let initialValue;
|
||||
let initialRemoveHidden;
|
||||
|
||||
@ -64,12 +83,13 @@ function checkBookmarksPanel(invoker, phase)
|
||||
{
|
||||
let onPopupShown = function(aEvent) {
|
||||
if (aEvent.originalTarget == popupElement) {
|
||||
popupElement.removeEventListener("popupshown", arguments.callee, false);
|
||||
checkBookmarksPanel(invoker, phase + 1);
|
||||
popupElement.removeEventListener("popupshown", onPopupShown, false);
|
||||
}
|
||||
};
|
||||
let onPopupHidden = function(aEvent) {
|
||||
if (aEvent.originalTarget == popupElement) {
|
||||
popupElement.removeEventListener("popuphidden", arguments.callee, false);
|
||||
if (phase < 4) {
|
||||
checkBookmarksPanel(invoker, phase + 1);
|
||||
} else {
|
||||
@ -78,10 +98,10 @@ function checkBookmarksPanel(invoker, phase)
|
||||
checkBookmarksPanel(invokers[currentInvoker], 1);
|
||||
} else {
|
||||
gBrowser.removeCurrentTab();
|
||||
finish();
|
||||
PlacesUtils.bookmarks.removeItem(bookmarkId);
|
||||
executeSoon(finish);
|
||||
}
|
||||
}
|
||||
popupElement.removeEventListener("popuphidden", onPopupHidden, false);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -21,19 +21,33 @@ function test() {
|
||||
PlacesUtils.transactionManager.doTransaction(bmTxn);
|
||||
|
||||
ok(PlacesUtils.bookmarks.isBookmarked(uri), "the test url is bookmarked");
|
||||
ok(starButton.getAttribute("starred") == "true",
|
||||
"star button indicates that the page is bookmarked");
|
||||
|
||||
let tagTxn = new PlacesTagURITransaction(uri, [testTag]);
|
||||
PlacesUtils.transactionManager.doTransaction(tagTxn);
|
||||
|
||||
StarUI.panel.addEventListener("popupshown", onPanelShown, false);
|
||||
starButton.click();
|
||||
waitForStarChange(true, onStarred);
|
||||
}), true);
|
||||
|
||||
content.location = testURL;
|
||||
}
|
||||
|
||||
function waitForStarChange(aValue, aCallback) {
|
||||
let starButton = document.getElementById("star-button");
|
||||
if (starButton.hidden || starButton.hasAttribute("starred") != aValue) {
|
||||
info("Waiting for star button change.");
|
||||
setTimeout(arguments.callee, 50, aValue, aCallback);
|
||||
return;
|
||||
}
|
||||
aCallback();
|
||||
}
|
||||
|
||||
function onStarred() {
|
||||
ok(starButton.getAttribute("starred") == "true",
|
||||
"star button indicates that the page is bookmarked");
|
||||
|
||||
let uri = makeURI(testURL);
|
||||
let tagTxn = new PlacesTagURITransaction(uri, [testTag]);
|
||||
PlacesUtils.transactionManager.doTransaction(tagTxn);
|
||||
|
||||
StarUI.panel.addEventListener("popupshown", onPanelShown, false);
|
||||
starButton.click();
|
||||
}
|
||||
|
||||
function onPanelShown(aEvent) {
|
||||
if (aEvent.target == StarUI.panel) {
|
||||
|
@ -1,226 +1,186 @@
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Places test code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Corp.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* David Dahl <ddahl@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
// Get history services
|
||||
var hs = Cc["@mozilla.org/browser/nav-history-service;1"].
|
||||
getService(Ci.nsINavHistoryService);
|
||||
var gh = hs.QueryInterface(Ci.nsIGlobalHistory2);
|
||||
var bh = hs.QueryInterface(Ci.nsIBrowserHistory);
|
||||
var ts = Cc["@mozilla.org/browser/tagging-service;1"].
|
||||
getService(Components.interfaces.nsITaggingService);
|
||||
var bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
|
||||
getService(Ci.nsINavBookmarksService);
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
function add_visit(aURI, aReferrer) {
|
||||
var visitId = hs.addVisit(aURI,
|
||||
Date.now() * 1000,
|
||||
aReferrer,
|
||||
hs.TRANSITION_TYPED, // user typed in URL bar
|
||||
false, // not redirect
|
||||
0);
|
||||
return visitId;
|
||||
return PlacesUtils.history.addVisit(aURI, Date.now() * 1000, aReferrer,
|
||||
PlacesUtils.history.TRANSITION_TYPED,
|
||||
false, 0);
|
||||
}
|
||||
|
||||
function add_bookmark(aURI) {
|
||||
var bId = bs.insertBookmark(bs.unfiledBookmarksFolder, aURI,
|
||||
bs.DEFAULT_INDEX, "bookmark/" + aURI.spec);
|
||||
return bId;
|
||||
return PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
|
||||
aURI, PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
"bookmark/" + aURI.spec);
|
||||
}
|
||||
|
||||
Components.utils.import("resource://gre/modules/NetUtil.jsm");
|
||||
|
||||
const TEST_URL = "http://example.com/";
|
||||
const MOZURISPEC = "http://mozilla.com/";
|
||||
|
||||
let gLibrary;
|
||||
let PlacesOrganizer;
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
var win = window.openDialog("chrome://browser/content/places/places.xul",
|
||||
"",
|
||||
"chrome,toolbar=yes,dialog=no,resizable");
|
||||
|
||||
win.addEventListener("load", function onload() {
|
||||
win.removeEventListener("load", onload, false);
|
||||
executeSoon(function () {
|
||||
var PU = win.PlacesUtils;
|
||||
var PO = win.PlacesOrganizer;
|
||||
var PUIU = win.PlacesUIUtils;
|
||||
|
||||
// individual tests for each step of tagging a history item
|
||||
var tests = {
|
||||
|
||||
sanity: function(){
|
||||
// sanity check
|
||||
ok(PU, "PlacesUtils in scope");
|
||||
ok(PUIU, "PlacesUIUtils in scope");
|
||||
ok(PO, "Places organizer in scope");
|
||||
},
|
||||
|
||||
makeHistVisit: function() {
|
||||
// need to add a history object
|
||||
var testURI1 = PU._uri(MOZURISPEC);
|
||||
isnot(testURI1, null, "testURI is not null");
|
||||
var visitId = add_visit(testURI1);
|
||||
ok(visitId > 0, "A visit was added to the history");
|
||||
ok(gh.isVisited(testURI1), MOZURISPEC + " is a visited url.");
|
||||
},
|
||||
|
||||
makeTag: function() {
|
||||
// create an initial tag to work with
|
||||
var bmId = add_bookmark(PlacesUtils._uri(TEST_URL));
|
||||
ok(bmId > 0, "A bookmark was added");
|
||||
ts.tagURI(PlacesUtils._uri(TEST_URL), ["foo"]);
|
||||
var tags = ts.getTagsForURI(PU._uri(TEST_URL));
|
||||
is(tags[0], 'foo', "tag is foo");
|
||||
},
|
||||
|
||||
focusTag: function (paste){
|
||||
// focus the new tag
|
||||
PO.selectLeftPaneQuery("Tags");
|
||||
var tags = PO._places.selectedNode;
|
||||
tags.containerOpen = true;
|
||||
var fooTag = tags.getChild(0);
|
||||
this.tagNode = fooTag;
|
||||
PO._places.selectNode(fooTag);
|
||||
is(this.tagNode.title, 'foo', "tagNode title is foo");
|
||||
var ip = PO._places.insertionPoint;
|
||||
ok(ip.isTag, "IP is a tag");
|
||||
if (paste) {
|
||||
ok(true, "About to paste");
|
||||
PO._places.controller.paste();
|
||||
}
|
||||
},
|
||||
|
||||
histNode: null,
|
||||
|
||||
copyHistNode: function (){
|
||||
// focus the history object
|
||||
PO.selectLeftPaneQuery("History");
|
||||
var histContainer = PO._places.selectedNode.QueryInterface(Ci.nsINavHistoryContainerResultNode);
|
||||
histContainer.containerOpen = true;
|
||||
PO._places.selectNode(histContainer.getChild(0));
|
||||
this.histNode = PO._content.view.nodeForTreeIndex(0);
|
||||
PO._content.selectNode(this.histNode);
|
||||
is(this.histNode.uri, MOZURISPEC,
|
||||
"historyNode exists: " + this.histNode.uri);
|
||||
// copy the history node
|
||||
PO._content.controller.copy();
|
||||
},
|
||||
|
||||
waitForPaste: function (){
|
||||
try {
|
||||
var xferable = Cc["@mozilla.org/widget/transferable;1"].
|
||||
createInstance(Ci.nsITransferable);
|
||||
xferable.addDataFlavor(PU.TYPE_X_MOZ_PLACE);
|
||||
var clipboard = Cc["@mozilla.org/widget/clipboard;1"].
|
||||
getService(Ci.nsIClipboard);
|
||||
clipboard.getData(xferable, Ci.nsIClipboard.kGlobalClipboard);
|
||||
var data = { }, type = { };
|
||||
xferable.getAnyTransferData(type, data, { });
|
||||
// Data is in the clipboard
|
||||
continue_test();
|
||||
} catch (ex) {
|
||||
// check again after 100ms.
|
||||
setTimeout(tests.waitForPaste, 100);
|
||||
}
|
||||
},
|
||||
|
||||
pasteToTag: function (){
|
||||
// paste history node into tag
|
||||
this.focusTag(true);
|
||||
},
|
||||
|
||||
historyNode: function (){
|
||||
// re-focus the history again
|
||||
PO.selectLeftPaneQuery("History");
|
||||
var histContainer = PO._places.selectedNode.QueryInterface(Ci.nsINavHistoryContainerResultNode);
|
||||
histContainer.containerOpen = true;
|
||||
PO._places.selectNode(histContainer.getChild(0));
|
||||
var histNode = PO._content.view.nodeForTreeIndex(0);
|
||||
ok(histNode, "histNode exists: " + histNode.title);
|
||||
// check to see if the history node is tagged!
|
||||
var tags = PU.tagging.getTagsForURI(PU._uri(MOZURISPEC));
|
||||
ok(tags.length == 1, "history node is tagged: " + tags.length);
|
||||
// check if a bookmark was created
|
||||
var isBookmarked = PU.bookmarks.isBookmarked(PU._uri(MOZURISPEC));
|
||||
is(isBookmarked, true, MOZURISPEC + " is bookmarked");
|
||||
var bookmarkIds = PU.bookmarks.getBookmarkIdsForURI(
|
||||
PU._uri(histNode.uri));
|
||||
ok(bookmarkIds.length > 0, "bookmark exists for the tagged history item: " + bookmarkIds);
|
||||
},
|
||||
|
||||
checkForBookmarkInUI: function(){
|
||||
// is the bookmark visible in the UI?
|
||||
// get the Unsorted Bookmarks node
|
||||
PO.selectLeftPaneQuery("UnfiledBookmarks");
|
||||
// now we can see what is in the _content tree
|
||||
var unsortedNode = PO._content.view.nodeForTreeIndex(1);
|
||||
ok(unsortedNode, "unsortedNode is not null: " + unsortedNode.uri);
|
||||
is(unsortedNode.uri, MOZURISPEC, "node uri's are the same");
|
||||
},
|
||||
|
||||
tagNode: null,
|
||||
|
||||
cleanUp: function(){
|
||||
ts.untagURI(PU._uri(MOZURISPEC), ["foo"]);
|
||||
ts.untagURI(PU._uri(TEST_URL), ["foo"]);
|
||||
hs.removeAllPages();
|
||||
var tags = ts.getTagsForURI(PU._uri(TEST_URL));
|
||||
is(tags.length, 0, "tags are gone");
|
||||
bs.removeFolderChildren(bs.unfiledBookmarksFolder);
|
||||
}
|
||||
};
|
||||
|
||||
tests.sanity();
|
||||
tests.makeHistVisit();
|
||||
tests.makeTag();
|
||||
tests.focusTag();
|
||||
tests.copyHistNode();
|
||||
tests.waitForPaste();
|
||||
|
||||
function continue_test() {
|
||||
tests.pasteToTag();
|
||||
tests.historyNode();
|
||||
tests.checkForBookmarkInUI();
|
||||
|
||||
// remove new places data we created
|
||||
tests.cleanUp();
|
||||
|
||||
win.close();
|
||||
finish();
|
||||
}
|
||||
|
||||
});
|
||||
},false);
|
||||
gLibrary = window.openDialog("chrome://browser/content/places/places.xul",
|
||||
"", "chrome,toolbar=yes,dialog=no,resizable");
|
||||
waitForFocus(onLibraryReady, gLibrary);
|
||||
}
|
||||
|
||||
function onLibraryReady() {
|
||||
ok(PlacesUtils, "PlacesUtils in scope");
|
||||
ok(PlacesUIUtils, "PlacesUIUtils in scope");
|
||||
|
||||
PlacesOrganizer = gLibrary.PlacesOrganizer;
|
||||
ok(PlacesOrganizer, "Places organizer in scope");
|
||||
|
||||
tests.makeHistVisit();
|
||||
tests.makeTag();
|
||||
tests.focusTag();
|
||||
tests.copyHistNode();
|
||||
tests.waitForClipboard();
|
||||
}
|
||||
|
||||
function onClipboardReady() {
|
||||
tests.pasteToTag();
|
||||
tests.historyNode();
|
||||
tests.checkForBookmarkInUI();
|
||||
|
||||
gLibrary.close();
|
||||
|
||||
// Remove new Places data we created.
|
||||
PlacesUtils.tagging.untagURI(NetUtil.newURI(MOZURISPEC), ["foo"]);
|
||||
PlacesUtils.tagging.untagURI(NetUtil.newURI(TEST_URL), ["foo"]);
|
||||
let tags = PlacesUtils.tagging.getTagsForURI(NetUtil.newURI(TEST_URL));
|
||||
is(tags.length, 0, "tags are gone");
|
||||
PlacesUtils.bookmarks.removeFolderChildren(PlacesUtils.unfiledBookmarksFolderId);
|
||||
|
||||
waitForClearHistory(finish);
|
||||
}
|
||||
|
||||
let tests = {
|
||||
|
||||
makeHistVisit: function() {
|
||||
// need to add a history object
|
||||
let testURI1 = NetUtil.newURI(MOZURISPEC);
|
||||
isnot(testURI1, null, "testURI is not null");
|
||||
let visitId = add_visit(testURI1);
|
||||
ok(visitId > 0, "A visit was added to the history");
|
||||
ok(PlacesUtils.ghistory2.isVisited(testURI1), MOZURISPEC + " is a visited url.");
|
||||
},
|
||||
|
||||
makeTag: function() {
|
||||
// create an initial tag to work with
|
||||
let bmId = add_bookmark(NetUtil.newURI(TEST_URL));
|
||||
ok(bmId > 0, "A bookmark was added");
|
||||
PlacesUtils.tagging.tagURI(NetUtil.newURI(TEST_URL), ["foo"]);
|
||||
let tags = PlacesUtils.tagging.getTagsForURI(NetUtil.newURI(TEST_URL));
|
||||
is(tags[0], 'foo', "tag is foo");
|
||||
},
|
||||
|
||||
focusTag: function (paste){
|
||||
// focus the new tag
|
||||
PlacesOrganizer.selectLeftPaneQuery("Tags");
|
||||
let tags = PlacesOrganizer._places.selectedNode;
|
||||
tags.containerOpen = true;
|
||||
let fooTag = tags.getChild(0);
|
||||
this.tagNode = fooTag;
|
||||
PlacesOrganizer._places.selectNode(fooTag);
|
||||
is(this.tagNode.title, 'foo', "tagNode title is foo");
|
||||
let ip = PlacesOrganizer._places.insertionPoint;
|
||||
ok(ip.isTag, "IP is a tag");
|
||||
if (paste) {
|
||||
ok(true, "About to paste");
|
||||
PlacesOrganizer._places.controller.paste();
|
||||
}
|
||||
},
|
||||
|
||||
histNode: null,
|
||||
|
||||
copyHistNode: function (){
|
||||
// focus the history object
|
||||
PlacesOrganizer.selectLeftPaneQuery("History");
|
||||
let histContainer = PlacesOrganizer._places.selectedNode;
|
||||
PlacesUtils.asContainer(histContainer);
|
||||
histContainer.containerOpen = true;
|
||||
PlacesOrganizer._places.selectNode(histContainer.getChild(0));
|
||||
this.histNode = PlacesOrganizer._content.view.nodeForTreeIndex(0);
|
||||
PlacesOrganizer._content.selectNode(this.histNode);
|
||||
is(this.histNode.uri, MOZURISPEC,
|
||||
"historyNode exists: " + this.histNode.uri);
|
||||
// copy the history node
|
||||
PlacesOrganizer._content.controller.copy();
|
||||
},
|
||||
|
||||
waitForClipboard: function (){
|
||||
try {
|
||||
let xferable = Cc["@mozilla.org/widget/transferable;1"].
|
||||
createInstance(Ci.nsITransferable);
|
||||
xferable.addDataFlavor(PlacesUtils.TYPE_X_MOZ_PLACE);
|
||||
let clipboard = Cc["@mozilla.org/widget/clipboard;1"].
|
||||
getService(Ci.nsIClipboard);
|
||||
clipboard.getData(xferable, Ci.nsIClipboard.kGlobalClipboard);
|
||||
let data = { }, type = { };
|
||||
xferable.getAnyTransferData(type, data, { });
|
||||
// Data is in the clipboard
|
||||
onClipboardReady();
|
||||
} catch (ex) {
|
||||
// check again after 100ms.
|
||||
setTimeout(arguments.callee, 100);
|
||||
}
|
||||
},
|
||||
|
||||
pasteToTag: function (){
|
||||
// paste history node into tag
|
||||
this.focusTag(true);
|
||||
},
|
||||
|
||||
historyNode: function (){
|
||||
// re-focus the history again
|
||||
PlacesOrganizer.selectLeftPaneQuery("History");
|
||||
let histContainer = PlacesOrganizer._places.selectedNode;
|
||||
PlacesUtils.asContainer(histContainer);
|
||||
histContainer.containerOpen = true;
|
||||
PlacesOrganizer._places.selectNode(histContainer.getChild(0));
|
||||
let histNode = PlacesOrganizer._content.view.nodeForTreeIndex(0);
|
||||
ok(histNode, "histNode exists: " + histNode.title);
|
||||
// check to see if the history node is tagged!
|
||||
let tags = PlacesUtils.tagging.getTagsForURI(NetUtil.newURI(MOZURISPEC));
|
||||
ok(tags.length == 1, "history node is tagged: " + tags.length);
|
||||
// check if a bookmark was created
|
||||
let isBookmarked = PlacesUtils.bookmarks.isBookmarked(NetUtil.newURI(MOZURISPEC));
|
||||
is(isBookmarked, true, MOZURISPEC + " is bookmarked");
|
||||
let bookmarkIds = PlacesUtils.bookmarks.getBookmarkIdsForURI(
|
||||
NetUtil.newURI(histNode.uri));
|
||||
ok(bookmarkIds.length > 0, "bookmark exists for the tagged history item: " + bookmarkIds);
|
||||
},
|
||||
|
||||
checkForBookmarkInUI: function(){
|
||||
// is the bookmark visible in the UI?
|
||||
// get the Unsorted Bookmarks node
|
||||
PlacesOrganizer.selectLeftPaneQuery("UnfiledBookmarks");
|
||||
// now we can see what is in the _content tree
|
||||
let unsortedNode = PlacesOrganizer._content.view.nodeForTreeIndex(1);
|
||||
ok(unsortedNode, "unsortedNode is not null: " + unsortedNode.uri);
|
||||
is(unsortedNode.uri, MOZURISPEC, "node uri's are the same");
|
||||
},
|
||||
|
||||
tagNode: null,
|
||||
};
|
||||
|
||||
/**
|
||||
* Clears history invoking callback when done.
|
||||
*/
|
||||
function waitForClearHistory(aCallback) {
|
||||
const TOPIC_EXPIRATION_FINISHED = "places-expiration-finished";
|
||||
let observer = {
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
Services.obs.removeObserver(this, TOPIC_EXPIRATION_FINISHED);
|
||||
aCallback();
|
||||
}
|
||||
};
|
||||
Services.obs.addObserver(observer, TOPIC_EXPIRATION_FINISHED, false);
|
||||
PlacesUtils.bhistory.removeAllPages();
|
||||
}
|
||||
|
@ -82,10 +82,6 @@ XPCOMUtils.defineLazyGetter(this, "NetUtil", function() {
|
||||
return NetUtil;
|
||||
});
|
||||
|
||||
// Global observers flags.
|
||||
let gHasAnnotationsObserver = false;
|
||||
let gHasShutdownObserver = false;
|
||||
|
||||
// The minimum amount of transactions before starting a batch. Usually we do
|
||||
// do incremental updates, a batch will cause views to completely
|
||||
// refresh instead.
|
||||
@ -275,15 +271,11 @@ var PlacesUtils = {
|
||||
*/
|
||||
get _readOnly() {
|
||||
// Add annotations observer.
|
||||
if (!gHasAnnotationsObserver) {
|
||||
this.annotations.addObserver(this, false);
|
||||
gHasAnnotationsObserver = true;
|
||||
}
|
||||
// Observe shutdown, so we can remove the anno observer.
|
||||
if (!gHasShutdownObserver) {
|
||||
Services.obs.addObserver(this, this.TOPIC_SHUTDOWN, false);
|
||||
gHasShutdownObserver = true;
|
||||
}
|
||||
this.annotations.addObserver(this, false);
|
||||
this.registerShutdownFunction(function () {
|
||||
this.annotations.removeObserver(this);
|
||||
});
|
||||
|
||||
var readOnly = this.annotations.getItemsWithAnnotation(this.READ_ONLY_ANNO);
|
||||
this.__defineGetter__("_readOnly", function() readOnly);
|
||||
return this._readOnly;
|
||||
@ -295,24 +287,25 @@ var PlacesUtils = {
|
||||
, Ci.nsITransactionListener
|
||||
]),
|
||||
|
||||
// nsIObserver
|
||||
observe: function PU_observe(aSubject, aTopic, aData) {
|
||||
if (aTopic == this.TOPIC_SHUTDOWN) {
|
||||
if (gHasAnnotationsObserver)
|
||||
this.annotations.removeObserver(this);
|
||||
|
||||
if (Object.getOwnPropertyDescriptor(this, "transactionManager").value !== undefined) {
|
||||
// Clear all references to local transactions in the transaction manager,
|
||||
// this prevents from leaking it.
|
||||
this.transactionManager.RemoveListener(this);
|
||||
this.transactionManager.clear();
|
||||
}
|
||||
|
||||
Services.obs.removeObserver(this, this.TOPIC_SHUTDOWN);
|
||||
gHasShutdownObserver = false;
|
||||
_shutdownFunctions: [],
|
||||
registerShutdownFunction: function PU_registerShutdownFunction(aFunc)
|
||||
{
|
||||
// If this is the first registered function, add the shutdown observer.
|
||||
if (this._shutdownFunctions.length == 0) {
|
||||
Services.obs.addObserver(this, this.TOPIC_SHUTDOWN, false);
|
||||
}
|
||||
this._shutdownFunctions.push(aFunc);
|
||||
},
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// nsIObserver
|
||||
observe: function PU_observe(aSubject, aTopic, aData)
|
||||
{
|
||||
if (aTopic == this.TOPIC_SHUTDOWN) {
|
||||
Services.obs.removeObserver(this, this.TOPIC_SHUTDOWN);
|
||||
this._shutdownFunctions.forEach(function (aFunc) aFunc.apply(this), this);
|
||||
}
|
||||
},
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// nsIAnnotationObserver
|
||||
@ -2048,6 +2041,63 @@ var PlacesUtils = {
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* Given a uri returns list of itemIds associated to it.
|
||||
*
|
||||
* @param aURI
|
||||
* nsIURI or spec of the page.
|
||||
* @param aCallback
|
||||
* Function to be called when done.
|
||||
* The function will receive an array of itemIds associated to aURI.
|
||||
* @param aScope
|
||||
* Scope for the callback.
|
||||
*
|
||||
* @note Children of live bookmarks folders are excluded.
|
||||
*/
|
||||
asyncGetBookmarkIds: function PU_asyncGetBookmarkIds(aURI, aCallback, aScope)
|
||||
{
|
||||
if (!this._asyncGetBookmarksStmt) {
|
||||
let db = this.history.QueryInterface(Ci.nsPIPlacesDatabase).DBConnection;
|
||||
this._asyncGetBookmarksStmt = db.createAsyncStatement(
|
||||
"SELECT b.id "
|
||||
+ "FROM moz_bookmarks b "
|
||||
+ "JOIN moz_places h on h.id = b.fk "
|
||||
+ "WHERE h.url = :url "
|
||||
+ "AND NOT EXISTS( "
|
||||
+ "SELECT 1 FROM moz_items_annos a "
|
||||
+ "JOIN moz_anno_attributes n ON a.anno_attribute_id = n.id "
|
||||
+ "WHERE a.item_id = b.parent AND n.name = :name "
|
||||
+ ") "
|
||||
);
|
||||
this.registerShutdownFunction(function () {
|
||||
this._asyncGetBookmarksStmt.finalize();
|
||||
});
|
||||
}
|
||||
|
||||
let url = aURI instanceof Ci.nsIURI ? aURI.spec : aURI;
|
||||
this._asyncGetBookmarksStmt.params.url = url;
|
||||
this._asyncGetBookmarksStmt.params.name = this.LMANNO_FEEDURI;
|
||||
this._asyncGetBookmarksStmt.executeAsync({
|
||||
_itemIds: [],
|
||||
handleResult: function(aResultSet) {
|
||||
let row, haveMatches = false;
|
||||
for (let row; (row = aResultSet.getNextRow());) {
|
||||
this._itemIds.push(row.getResultByIndex(0));
|
||||
}
|
||||
},
|
||||
handleError: function(aError) {
|
||||
Cu.reportError("Async statement execution returned (" + aError.result +
|
||||
"): " + aError.message);
|
||||
},
|
||||
handleCompletion: function(aReason)
|
||||
{
|
||||
if (aReason == Ci.mozIStorageStatementCallback.REASON_FINISHED) {
|
||||
aCallback.apply(aScope, [this._itemIds]);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(PlacesUtils, "history",
|
||||
@ -2091,18 +2141,15 @@ XPCOMUtils.defineLazyServiceGetter(PlacesUtils, "microsummaries",
|
||||
"nsIMicrosummaryService");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(PlacesUtils, "transactionManager", function() {
|
||||
Services.obs.addObserver(PlacesUtils,
|
||||
PlacesUtils.TOPIC_SHUTDOWN,
|
||||
false);
|
||||
// Observe shutdown, so we can remove the anno observer.
|
||||
if (!gHasShutdownObserver) {
|
||||
Services.obs.addObserver(PlacesUtils, PlacesUtils.TOPIC_SHUTDOWN, false);
|
||||
gHasShutdownObserver = true;
|
||||
}
|
||||
|
||||
let tm = Cc["@mozilla.org/transactionmanager;1"].
|
||||
getService(Ci.nsITransactionManager);
|
||||
tm.AddListener(PlacesUtils);
|
||||
this.registerShutdownFunction(function () {
|
||||
// Clear all references to local transactions in the transaction manager,
|
||||
// this prevents from leaking it.
|
||||
this.transactionManager.RemoveListener(this);
|
||||
this.transactionManager.clear();
|
||||
});
|
||||
return tm;
|
||||
});
|
||||
|
||||
|
@ -193,7 +193,7 @@ TaggingService.prototype = {
|
||||
{
|
||||
if (tag.id == -1) {
|
||||
// Tag does not exist yet, create it.
|
||||
tag.id = this._createTag(tag.name);
|
||||
this._createTag(tag.name);
|
||||
}
|
||||
|
||||
if (this._getItemIdForTaggedURI(aURI, tag.name) == -1) {
|
||||
|
Loading…
Reference in New Issue
Block a user