Move codes to override behaviors around bookmarks to a JS code module.
Moreover, it reduces use of eval.
This commit is contained in:
parent
978bda448d
commit
fdc472441b
@ -1,221 +1,15 @@
|
||||
Components.utils.import('resource://gre/modules/XPCOMUtils.jsm');
|
||||
XPCOMUtils.defineLazyModuleGetter(this,
|
||||
'TreeStyleTabUtils', 'resource://treestyletab-modules/utils.js');
|
||||
XPCOMUtils.defineLazyModuleGetter(this,
|
||||
'TreeStyleTabBookmarksService', 'resource://treestyletab-modules/bookmark.js');
|
||||
|
||||
(function() {
|
||||
let { ReferenceCounter } = Components.utils.import('resource://treestyletab-modules/ReferenceCounter.js', {});
|
||||
let { inherit } = Components.utils.import('resource://treestyletab-modules/lib/inherit.jsm', {});
|
||||
var TreeStyleTabBookmarksService = inherit(TreeStyleTabService, {
|
||||
|
||||
get BookmarksService() {
|
||||
if (!this._BookmarksService) {
|
||||
this._BookmarksService = Components
|
||||
.classes['@mozilla.org/browser/nav-bookmarks-service;1']
|
||||
.getService(Components.interfaces.nsINavBookmarksService);
|
||||
}
|
||||
return this._BookmarksService;
|
||||
},
|
||||
_BookmarksService : null,
|
||||
|
||||
|
||||
beginAddBookmarksFromTabs : function TSTBMService_beginAddBookmarksFromTabs(aTabs) /* PUBLIC API */
|
||||
{
|
||||
if (this._observing) return;
|
||||
this._observing = true;
|
||||
|
||||
aTabs = this.cleanUpTabsArray(aTabs);
|
||||
|
||||
this._addingBookmarks = [];
|
||||
this._addingBookmarkTreeStructure = aTabs.map(function(aTab) {
|
||||
var parent = this.getParentTab(aTab);
|
||||
return aTabs.indexOf(parent);
|
||||
}, this);
|
||||
|
||||
this.BookmarksService.addObserver(this, false);
|
||||
},
|
||||
|
||||
endAddBookmarksFromTabs : function TSTBMService_endAddBookmarksFromTabs() /* PUBLIC API */
|
||||
{
|
||||
if (!this._observing) return;
|
||||
this._observing = false;
|
||||
|
||||
this.BookmarksService.removeObserver(this);
|
||||
this.handleNewBookmarksFromTabs(this._addingBookmarks, this._addingBookmarkTreeStructure);
|
||||
this._addingBookmarks = [];
|
||||
this._addingBookmarkTreeStructure = [];
|
||||
},
|
||||
|
||||
handleNewBookmarksFromTabs : function TSTBMService_handleNewBookmarksFromTabs(aBookarmks, aTreeStructure)
|
||||
{
|
||||
// this is adding bookmark folder from tabs, so ignroe the first item!
|
||||
if (
|
||||
aBookarmks.length == aTreeStructure.length+1 &&
|
||||
this.BookmarksService.getItemType(aBookarmks[0].id) == this.BookmarksService.TYPE_FOLDER
|
||||
) {
|
||||
aBookarmks.shift();
|
||||
}
|
||||
else if (aBookarmks.length != aTreeStructure.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (let i = 0, maxi = aBookarmks.length; i < maxi; i++)
|
||||
{
|
||||
let item = aBookarmks[i];
|
||||
item.position = this.BookmarksService.getItemIndex(item.id);
|
||||
}
|
||||
aBookarmks.sort(function(aA, aB) {
|
||||
return aA.position - aB.position;
|
||||
});
|
||||
|
||||
for (let i = 0, maxi = aBookarmks.length; i < maxi; i++)
|
||||
{
|
||||
let item = aBookarmks[i];
|
||||
if (this.BookmarksService.getItemType(item.id) != this.BookmarksService.TYPE_BOOKMARK)
|
||||
continue;
|
||||
|
||||
let uri = this.BookmarksService.getBookmarkURI(item.id);
|
||||
if (/^about:treestyletab-group\b/.test(uri.spec)) {
|
||||
let title = this.BookmarksService.getItemTitle(item.id);
|
||||
let folderId = this.BookmarksService.createFolder(item.parent, title, item.position);
|
||||
this.BookmarksService.removeItem(item.id);
|
||||
item.id = folderId;
|
||||
item.isFolder = true;
|
||||
}
|
||||
|
||||
let index = aTreeStructure[i];
|
||||
let parent = index > -1 ? aBookarmks[index] : null ;
|
||||
if (parent && (parent.folder || parent).isFolder) {
|
||||
let folder = parent.isFolder ? parent : parent.folder ;
|
||||
this.BookmarksService.moveItem(item.id, folder.id, -1);
|
||||
item.folder = folder;
|
||||
}
|
||||
if (parent && !parent.isFolder) {
|
||||
PlacesUtils.setAnnotationsForItem(item.id, [{
|
||||
name : this.kPARENT,
|
||||
value : parent ? parent.id : -1,
|
||||
expires : PlacesUtils.annotations.EXPIRE_NEVER
|
||||
}]);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
bookmarkTabSubtree : function TSTBMService_bookmarkTabSubtree(aTabOrTabs)
|
||||
{
|
||||
var tabs = aTabOrTabs;
|
||||
if (!Array.isArray(tabs)) {
|
||||
tabs = [aTabOrTabs];
|
||||
}
|
||||
|
||||
var folderName = (this.isGroupTab(tabs[0], true) || tabs.length == 1) ?
|
||||
tabs[0].label :
|
||||
null ;
|
||||
|
||||
var b = this.getTabBrowserFromChild(tabs[0]);
|
||||
var bookmarkedTabs = [];
|
||||
for (let i = 0, maxi = tabs.length; i < maxi; i++)
|
||||
{
|
||||
let tab = tabs[i];
|
||||
if (!this.isGroupTab(tab, i == 0)) bookmarkedTabs.push(tab);
|
||||
bookmarkedTabs = bookmarkedTabs.concat(b.treeStyleTab.getDescendantTabs(tab));
|
||||
}
|
||||
|
||||
this.beginAddBookmarksFromTabs(bookmarkedTabs);
|
||||
try {
|
||||
window['piro.sakura.ne.jp'].bookmarkMultipleTabs.addBookmarkFor(bookmarkedTabs, folderName);
|
||||
}
|
||||
catch(e) {
|
||||
}
|
||||
this.endAddBookmarksFromTabs();
|
||||
},
|
||||
bookmarkTabSubTree : function() { return this.bookmarkTabSubtree.apply(this, arguments); }, // obsolete, for backward compatibility
|
||||
|
||||
getParentItem : function TSTBMService_getParentItem(aId)
|
||||
{
|
||||
if (aId < 0) return -1;
|
||||
var annotations = PlacesUtils.getAnnotationsForItem(aId);
|
||||
for (let i in annotations)
|
||||
{
|
||||
if (annotations[i].name != this.kPARENT) continue;
|
||||
return parseInt(annotations[i].value);
|
||||
}
|
||||
return -1;
|
||||
},
|
||||
|
||||
getTreeStructureFromItems : function TSTBMService_getTreeStructureFromItems(aIDs, aDefaultParentID)
|
||||
{
|
||||
/* this returns a result same to getTreeStructureFromTabs().
|
||||
[A] => -1 (parent is not in this tree)
|
||||
[B] => 0 (parent is 1st item in this tree)
|
||||
[C] => 0 (parent is 1st item in this tree)
|
||||
[D] => 2 (parent is 2nd in this tree)
|
||||
[E] => -1 (parent is not in this tree, and this creates another tree)
|
||||
[F] => 0 (parent is 1st item in this another tree)
|
||||
*/
|
||||
if (aDefaultParentID === void(0))
|
||||
aDefaultParentID = -1;
|
||||
|
||||
/* Get array of parents. The index becomes to -1,
|
||||
if there is NO PARENT or the parent is THE TAB ITSELF. */
|
||||
var treeStructure = aIDs.map(function(aId, aIndex) {
|
||||
let id = this.getParentItem(aId);
|
||||
let index = aIDs.indexOf(id);
|
||||
return index >= aIndex ? aDefaultParentID : index ;
|
||||
}, this);
|
||||
|
||||
/* Correct patterns like:
|
||||
[TabA]
|
||||
[TabB] - this has no parent
|
||||
[TabC] - TabA's child
|
||||
to:
|
||||
[TabA]
|
||||
[TabB]
|
||||
[TabC]
|
||||
*/
|
||||
treeStructure = treeStructure.reverse();
|
||||
treeStructure = treeStructure.map(function(aPosition, aIndex) {
|
||||
if (aIndex > 0 &&
|
||||
aIndex < treeStructure.length-1 &&
|
||||
aPosition < 0) {
|
||||
aPosition = treeStructure[aIndex-1];
|
||||
}
|
||||
return aPosition;
|
||||
});
|
||||
treeStructure = treeStructure.reverse();
|
||||
|
||||
return this.cleanUpTreeStructureArray(treeStructure, aDefaultParentID);
|
||||
},
|
||||
|
||||
// based on PlacesUtils.getURLsForContainerNode()
|
||||
getItemIdsForContainerNode : function TSTBMService_getItemIdsForContainerNode(aNode)
|
||||
{
|
||||
var ids = [];
|
||||
if (!aNode || !PlacesUtils.nodeIsContainer(aNode)) return ids;
|
||||
|
||||
var root = aNode;
|
||||
if ('getContainerNodeWithOptions' in PlacesUtils) {
|
||||
root = PlacesUtils.getContainerNodeWithOptions(root, false, true);
|
||||
}
|
||||
var oldViewer = root.parentResult.viewer;
|
||||
var wasOpen = root.containerOpen;
|
||||
if (!wasOpen) {
|
||||
if (oldViewer)
|
||||
root.parentResult.viewer = null;
|
||||
root.containerOpen = true;
|
||||
}
|
||||
for (let i = 0, maxi = root.childCount; i < maxi; ++i)
|
||||
{
|
||||
let child = root.getChild(i);
|
||||
if (PlacesUtils.nodeIsURI(child)) ids.push(child.itemId || -1);
|
||||
}
|
||||
if (!wasOpen) {
|
||||
root.containerOpen = false;
|
||||
if (oldViewer)
|
||||
root.parentResult.viewer = oldViewer;
|
||||
}
|
||||
return ids;
|
||||
},
|
||||
|
||||
|
||||
var TreeStyleTabBookmarksUIService = inherit(TreeStyleTabService, {
|
||||
preInit : function TSTBMService_preInit()
|
||||
{
|
||||
window.addEventListener('load', this, false);
|
||||
@ -231,250 +25,35 @@ var TreeStyleTabBookmarksService = inherit(TreeStyleTabService, {
|
||||
window.addEventListener('unload', this, false);
|
||||
ReferenceCounter.add('window,unload,TSTBMService,false');
|
||||
|
||||
if (!('PlacesUIUtils' in window)) return;
|
||||
|
||||
if (!PlacesUIUtils.__treestyletab__done) {
|
||||
var ns = Components.utils.import('resource:///modules/PlacesUIUtils.jsm', {});
|
||||
var sv = this;
|
||||
with (ns) {
|
||||
|
||||
{
|
||||
let method = (TreeStyleTabUtils.getTreePref('compatibility.TabUtilities') && PlacesUIUtils.TU__openTabset) ?
|
||||
'TU__openTabset' :
|
||||
'_openTabset';
|
||||
if (PlacesUIUtils.__openbookmarkintab__openTabset)
|
||||
method = '__openbookmarkintab__openTabset';
|
||||
TreeStyleTabUtils.doPatching(PlacesUIUtils[method], 'PlacesUIUtils.'+method, function(aName, aSource) {
|
||||
var patched = eval(aName+' = '+aSource.replace(
|
||||
/(function[^\(]*\([^\)]+)(\))/,
|
||||
'$1, aFolderTitle$2'
|
||||
).replace(
|
||||
'{',
|
||||
'{ var TSTTreeStructure = null, TSTPreviousTabs, TSTTreeStructureApplied = true, TSTOpenGroupBookmarkBehavior;'
|
||||
).replace(
|
||||
'var urls = [];',
|
||||
'$& var ids = [];'
|
||||
).replace(
|
||||
'urls.push(item.uri);',
|
||||
'if (item.uri) { $& ids.push(item.id); }'
|
||||
).replace(
|
||||
'this.markPageAsTyped(item.uri);',
|
||||
'if (item.uri) { $& }'
|
||||
).replace(
|
||||
/(browserWindow\.(?:getBrowser\(\)|gBrowser)\.loadTabs\([^;]+\);)/,
|
||||
'var TSTResult = browserWindow.TreeStyleTabBookmarksService.handleTabsOpenProcess(where, aEvent, browserWindow, ids, urls, aFolderTitle);\n' +
|
||||
'TSTTreeStructure = TSTResult.treeStructure;\n' +
|
||||
'TSTPreviousTabs = TSTResult.previousTabs;\n' +
|
||||
'TSTTreeStructureApplied = TSTResult.treeStructureApplied;\n' +
|
||||
'TSTOpenGroupBookmarkBehavior = TSTResult.behavior;\n' +
|
||||
'$1'
|
||||
).replace(
|
||||
/(\}\)?)$/,
|
||||
' if (TSTTreeStructure && TSTPreviousTabs) {\n' +
|
||||
' let tabs = browserWindow.TreeStyleTabService.getNewTabsFromPreviousTabsInfo(browserWindow.gBrowser, TSTPreviousTabs);\n' +
|
||||
' if (!TSTTreeStructureApplied)\n' +
|
||||
' browserWindow.TreeStyleTabService.applyTreeStructureToTabs(tabs, TSTTreeStructure, TSTOpenGroupBookmarkBehavior & browserWindow.TreeStyleTabBookmarksService.kGROUP_BOOKMARK_EXPAND_ALL_TREE);\n' +
|
||||
' if (!loadInBackground) {\n' +
|
||||
' browserWindow.setTimeout(function() {\n' +
|
||||
' browserWindow.gBrowser.treeStyleTab.scrollToTabs(tabs);\n' +
|
||||
' }, browserWindow.gBrowser.treeStyleTab.collapseDuration); // start scroll after expanding animation is finished\n' +
|
||||
' }\n' +
|
||||
' }\n' +
|
||||
'$1'
|
||||
));
|
||||
if (TreeStyleTabUtils.getTreePref('compatibility.TabUtilities') && method.indexOf('TU_') > -1)
|
||||
window[method] = patched;
|
||||
return patched;
|
||||
}, 'TreeStyleTab');
|
||||
}
|
||||
|
||||
{
|
||||
let method = (TreeStyleTabUtils.getTreePref('compatibility.TabUtilities') && PlacesUIUtils.TU_openContainerNodeInTabs) ?
|
||||
'TU_openContainerNodeInTabs' :
|
||||
'openContainerNodeInTabs';
|
||||
TreeStyleTabUtils.doPatching(PlacesUIUtils[method], 'PlacesUIUtils.'+method, function(aName, aSource) {
|
||||
var patched = eval(aName+' = '+aSource.replace(
|
||||
/(this\._openTabset\([^\)]+)(\))/,
|
||||
'{\n' +
|
||||
' let w = "_getTopBrowserWin" in this ?\n' +
|
||||
' this._getTopBrowserWin() :\n' +
|
||||
' "_getCurrentActiveWin" in this ?\n' +
|
||||
' this._getCurrentActiveWin() :\n' +
|
||||
' window;\n' +
|
||||
' let nodes = w.TreeStyleTabBookmarksService.getItemIdsForContainerNode(aNode);\n' +
|
||||
' for (let i in nodes) {\n' +
|
||||
' urlsToOpen[i].id = nodes[i];\n' +
|
||||
' }\n' +
|
||||
'}\n' +
|
||||
'$1, aNode.title$2'
|
||||
));
|
||||
if (TreeStyleTabUtils.getTreePref('compatibility.TabUtilities') && method.indexOf('TU_') > -1)
|
||||
window[method] = patched;
|
||||
return patched;
|
||||
}, 'TreeStyleTab');
|
||||
}
|
||||
|
||||
{
|
||||
let method = (TreeStyleTabUtils.getTreePref('compatibility.TabUtilities') && PlacesUIUtils.TU_openURINodesInTabs) ?
|
||||
'TU_openURINodesInTabs' :
|
||||
'openURINodesInTabs';
|
||||
TreeStyleTabUtils.doPatching(PlacesUIUtils[method], 'PlacesUIUtils.'+method, function(aName, aSource) {
|
||||
var patched = eval(aName+' = '+aSource.replace(
|
||||
'{',
|
||||
'{\n' +
|
||||
' var TSTBS, TSTUtils;\n' +
|
||||
' {\n'+
|
||||
' let w = "_getTopBrowserWin" in this ?\n' +
|
||||
' this._getTopBrowserWin() :\n' +
|
||||
' "_getCurrentActiveWin" in this ?\n' +
|
||||
' this._getCurrentActiveWin() :\n' +
|
||||
' window;\n' +
|
||||
' TSTBS = w.TreeStyleTabBookmarksService;\n' +
|
||||
' TSTUtils = w.TreeStyleTabUtils;\n' +
|
||||
' PlacesUtils = w.PlacesUtils;\n' +
|
||||
' }'
|
||||
).replace(
|
||||
'uri: aNodes[i].uri,',
|
||||
'id: aNodes[i].itemId, $&'
|
||||
).replace(
|
||||
/(this\._openTabset\([^\)]+)(\))/,
|
||||
'$1,\n' +
|
||||
' TSTUtils.treeBundle\n' +
|
||||
' .getFormattedString(\n' +
|
||||
' PlacesUtils.nodeIsBookmark(aNodes[0]) ?\n' +
|
||||
' "openSelectedPlaces.bookmarks" :\n' +
|
||||
' "openSelectedPlaces.history",\n' +
|
||||
' [aNodes[0].title, aNodes.length]\n' +
|
||||
' )\n' +
|
||||
'$2'
|
||||
));
|
||||
if (TreeStyleTabUtils.getTreePref('compatibility.TabUtilities') && method.indexOf('TU_') > -1)
|
||||
window[method] = patched;
|
||||
return patched;
|
||||
}, 'TreeStyleTab');
|
||||
}
|
||||
|
||||
PlacesUIUtils.__treestyletab__done = true;
|
||||
|
||||
} // end of with
|
||||
}
|
||||
|
||||
if ('PlacesCommandHook' in window && 'bookmarkCurrentPages' in PlacesCommandHook) {
|
||||
// Bookmark All Tabs
|
||||
TreeStyleTabUtils.doPatching(PlacesCommandHook.bookmarkCurrentPages, 'PlacesCommandHook.bookmarkCurrentPages', function(aName, aSource) {
|
||||
return eval(aName+' = '+aSource.replace(
|
||||
'{',
|
||||
'{\n' +
|
||||
' TreeStyleTabBookmarksService.beginAddBookmarksFromTabs((function() {\n' +
|
||||
' var tabs = [];\n' +
|
||||
' var seen = {};\n' +
|
||||
' var allTabs = getBrowser().mTabContainer.childNodes;\n' +
|
||||
' for (let i = 0, maxi = allTabs.length; i < maxi; i++)\n' +
|
||||
' {\n' +
|
||||
' let tab = allTabs[i];\n' +
|
||||
' let uri = tab.linkedBrowser.currentURI.spec;\n' +
|
||||
' if (uri in seen) continue;\n' +
|
||||
' seen[uri] = true;\n' +
|
||||
' tabs.push(tab);\n' +
|
||||
' }\n' +
|
||||
' return tabs;\n' +
|
||||
' })());\n' +
|
||||
' try {'
|
||||
).replace(
|
||||
/(\}\)?)$/,
|
||||
' }\n' +
|
||||
' catch(e) {\n' +
|
||||
' }\n' +
|
||||
' TreeStyleTabBookmarksService.endAddBookmarksFromTabs();\n' +
|
||||
'$1'
|
||||
));
|
||||
}, 'TreeStyleTab');
|
||||
}
|
||||
},
|
||||
handleTabsOpenProcess : function TSTBMService_handleTabsOpenProcess(aWhere, aEvent, aBrowserWindow, aIDs, aURLs, aFolderTitle)
|
||||
{
|
||||
var result = {
|
||||
behavior : undefined,
|
||||
treeStructure : undefined,
|
||||
previousTabs : undefined,
|
||||
treeStructureApplied : false
|
||||
PlacesCommandHook.__treestyletab__bookmarkCurrentPages = PlacesCommandHook.bookmarkCurrentPages;
|
||||
PlacesCommandHook.bookmarkCurrentPages = function(...aArgs) {
|
||||
TreeStyleTabBookmarksService.beginAddBookmarksFromTabs((function() {
|
||||
var tabs = [];
|
||||
var seen = {};
|
||||
var allTabs = gBrowser.mTabContainer.childNodes;
|
||||
for (let i = 0, maxi = allTabs.length; i < maxi; i++)
|
||||
{
|
||||
let tab = allTabs[i];
|
||||
let uri = tab.linkedBrowser.currentURI.spec;
|
||||
if (uri in seen)
|
||||
continue;
|
||||
seen[uri] = true;
|
||||
tabs.push(tab);
|
||||
}
|
||||
return tabs;
|
||||
})());
|
||||
try {
|
||||
return this.__treestyletab__bookmarkCurrentPages.apply(this, aArgs);
|
||||
}
|
||||
finally {
|
||||
TreeStyleTabBookmarksService.endAddBookmarksFromTabs();
|
||||
}
|
||||
};
|
||||
if (
|
||||
aEvent.type != 'drop' &&
|
||||
aWhere.indexOf('tab') != 0 &&
|
||||
aEvent.target.id != 'placesContext_openContainer:tabs' &&
|
||||
aEvent.target.id != 'placesContext_openLinks:tabs' &&
|
||||
aEvent.target != aEvent.target.parentNode._endOptOpenAllInTabs &&
|
||||
aEvent.target.getAttribute('openInTabs') != 'true'
|
||||
)
|
||||
return result;
|
||||
|
||||
var sv = aBrowserWindow.TreeStyleTabBookmarksService;
|
||||
result.behavior = sv.openGroupBookmarkBehavior();
|
||||
if (result.behavior & sv.kGROUP_BOOKMARK_SUBTREE) {
|
||||
let treeStructure = result.behavior & sv.kGROUP_BOOKMARK_DONT_RESTORE_TREE_STRUCTURE ?
|
||||
null :
|
||||
sv.getTreeStructureFromItems(aIDs) ;
|
||||
if (treeStructure) {
|
||||
let parentTabs = treeStructure.filter(function(aParent) {
|
||||
return aParent < 0;
|
||||
});
|
||||
let haveMultipleTrees = parentTabs.length != treeStructure.length;
|
||||
if (result.behavior & sv.kGROUP_BOOKMARK_USE_DUMMY) {
|
||||
let parentCount = 0;
|
||||
let childCount = 0;
|
||||
for (let i in treeStructure) {
|
||||
if (treeStructure[i] == -1)
|
||||
parentCount++;
|
||||
else
|
||||
childCount++;
|
||||
}
|
||||
if (
|
||||
parentCount > 1 &&
|
||||
(
|
||||
result.behavior & sv.kGROUP_BOOKMARK_USE_DUMMY_FORCE ||
|
||||
// when there is any orphan, then all of parents and orphans should be grouped under a dummy tab.
|
||||
childCount < parentCount
|
||||
)
|
||||
) {
|
||||
aIDs.unshift(-1);
|
||||
treeStructure = sv.getTreeStructureFromItems(aIDs, 0);
|
||||
aURLs.unshift(sv.getGroupTabURI({
|
||||
title: aFolderTitle,
|
||||
temporary: TreeStyleTabUtils.getTreePref('openGroupBookmark.temporaryGroup')
|
||||
}));
|
||||
}
|
||||
}
|
||||
else if (!haveMultipleTrees) {
|
||||
// make the first item parent.
|
||||
treeStructure = treeStructure.map(function(aParent, aIndex) {
|
||||
if (aIndex == 0)
|
||||
return aParent;
|
||||
if (aParent < 0)
|
||||
return 0;
|
||||
return aParent;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
result.treeStructure = treeStructure;
|
||||
result.previousTabs = aBrowserWindow.TreeStyleTabService.getTabsInfo(aBrowserWindow.gBrowser);
|
||||
|
||||
if (TreeStyleTabUtils.getTreePref('compatibility.TMP') &&
|
||||
'TMP_Places' in aBrowserWindow &&
|
||||
'openGroup' in aBrowserWindow.TMP_Places) {
|
||||
result.treeStructureApplied = false;
|
||||
}
|
||||
else {
|
||||
sv.readyToOpenNewTabGroup(null, treeStructure, result.behavior & sv.kGROUP_BOOKMARK_EXPAND_ALL_TREE);
|
||||
result.treeStructureApplied = true;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
|
||||
|
||||
destroy : function TSTBMService_destroy()
|
||||
{
|
||||
window.removeEventListener('unload', this, false);
|
||||
@ -483,22 +62,6 @@ var TreeStyleTabBookmarksService = inherit(TreeStyleTabService, {
|
||||
ReferenceCounter.remove('window,EVENT_TYPE_TABS_DROP,TSTBMService,false');
|
||||
},
|
||||
|
||||
// observer for nsINavBookmarksService
|
||||
onItemAdded : function TSTBMService_onItemAdded(aID, aFolderID, aPosition)
|
||||
{
|
||||
this._addingBookmarks.push({
|
||||
id : aID,
|
||||
parent : aFolderID
|
||||
});
|
||||
},
|
||||
onItemRemoved : function TSTBMService_onItemRemoved(aID, aFolderID, aPosition) {},
|
||||
onItemMoved : function TSTBMService_onItemMoved(aID, aFolderID, aPosition) {},
|
||||
onItemChanged : function TSTBMService_onItemChanged(aID, aChange, aIsAnnotation, aNewValue) {},
|
||||
onItemVisited : function TSTBMService_onItemVisited(aID, aHistoryID, aDate) {},
|
||||
onBeginUpdateBatch : function TSTBMService_onBeginUpdateBatch() {},
|
||||
onEndUpdateBatch : function TSTBMService_onEndUpdateBatch() {},
|
||||
|
||||
|
||||
_onTabsDrop : function TSTBMService_onTabsDrop(aEvent)
|
||||
{
|
||||
var tabs = aEvent.detail.tabs;
|
||||
@ -533,7 +96,7 @@ var TreeStyleTabBookmarksService = inherit(TreeStyleTabService, {
|
||||
|
||||
});
|
||||
|
||||
TreeStyleTabBookmarksService.preInit();
|
||||
TreeStyleTabBookmarksUIService.preInit();
|
||||
|
||||
window.TreeStyleTabBookmarksService = TreeStyleTabBookmarksService;
|
||||
window.TreeStyleTabBookmarksUIService = TreeStyleTabBookmarksUIService;
|
||||
})();
|
||||
|
@ -327,13 +327,22 @@ var TreeStyleTabBookmarksServiceEditable = inherit(TreeStyleTabBookmarksService,
|
||||
},
|
||||
_getSiblingItemsIterator : function TSTBMEditable_getSiblingItemsIterator(aId)
|
||||
{
|
||||
return this._getItemsInFolderIterator(PlacesUtils.bookmarks.getFolderIdForItem(aId));
|
||||
try {
|
||||
var folderId = PlacesUtils.bookmarks.getFolderIdForItem(aId);
|
||||
return this._getItemsInFolderIterator(folderId);
|
||||
}
|
||||
catch(e) {
|
||||
dump('TSTBMEditable_getSiblingItemsIterator('+aId+') failed.\n');
|
||||
dump(e+'\n');
|
||||
dump(new Error().stack+'\n');
|
||||
}
|
||||
},
|
||||
|
||||
saveParentFor : function TSTBMEditable_saveParentFor(aId, aJustNow)
|
||||
{
|
||||
var newParentId = parseInt(this.menulist.value || -1);
|
||||
if (this.canceled || newParentId == this.getParentItem(aId)) return;
|
||||
if (this.canceled || newParentId == this.getParentItem(aId))
|
||||
return;
|
||||
|
||||
var itemsIterator = this._getSiblingItemsIterator(aId);
|
||||
var items = [];
|
||||
|
@ -726,6 +726,7 @@ pref("extensions.treestyletab.prefsVersion", 0);
|
||||
pref("extensions.treestyletab.debug.all", false);
|
||||
pref("extensions.treestyletab.debug.autoHide", false);
|
||||
pref("extensions.treestyletab.debug.base", false);
|
||||
pref("extensions.treestyletab.debug.bookmark", false);
|
||||
pref("extensions.treestyletab.debug.browser", false);
|
||||
pref("extensions.treestyletab.debug.browserUIShowHideObserver", false);
|
||||
pref("extensions.treestyletab.debug.contentBridge", false);
|
||||
|
@ -370,10 +370,6 @@ var TreeStyleTabBase = inherit(TreeStyleTabConstants, {
|
||||
|
||||
return behavior
|
||||
},
|
||||
kDROPLINK_ASK : 0,
|
||||
kDROPLINK_FIXED : 1 + 2,
|
||||
kDROPLINK_LOAD : 1,
|
||||
kDROPLINK_NEWTAB : 2,
|
||||
|
||||
openGroupBookmarkBehavior : function TSTBase_openGroupBookmarkBehavior()
|
||||
{
|
||||
@ -409,14 +405,6 @@ var TreeStyleTabBase = inherit(TreeStyleTabConstants, {
|
||||
}
|
||||
return behavior;
|
||||
},
|
||||
kGROUP_BOOKMARK_ASK : 0,
|
||||
kGROUP_BOOKMARK_FIXED : 1 + 2 + 4,
|
||||
kGROUP_BOOKMARK_SUBTREE : 1,
|
||||
kGROUP_BOOKMARK_SEPARATE : 2,
|
||||
kGROUP_BOOKMARK_USE_DUMMY : 256,
|
||||
kGROUP_BOOKMARK_USE_DUMMY_FORCE : 1024,
|
||||
kGROUP_BOOKMARK_DONT_RESTORE_TREE_STRUCTURE : 512,
|
||||
kGROUP_BOOKMARK_EXPAND_ALL_TREE : 2048,
|
||||
|
||||
bookmarkDroppedTabsBehavior : function TSTBase_bookmarkDroppedTabsBehavior()
|
||||
{
|
||||
@ -2282,48 +2270,6 @@ var TreeStyleTabBase = inherit(TreeStyleTabConstants, {
|
||||
return collapsedStates;
|
||||
},
|
||||
|
||||
getTreeStructureFromTabs : function TSTBase_getTreeStructureFromTabs(aTabs)
|
||||
{
|
||||
/* this returns...
|
||||
[A] => -1 (parent is not in this tree)
|
||||
[B] => 0 (parent is 1st item in this tree)
|
||||
[C] => 0 (parent is 1st item in this tree)
|
||||
[D] => 2 (parent is 2nd in this tree)
|
||||
[E] => -1 (parent is not in this tree, and this creates another tree)
|
||||
[F] => 0 (parent is 1st item in this another tree)
|
||||
*/
|
||||
return this.cleanUpTreeStructureArray(
|
||||
aTabs.map(function(aTab, aIndex) {
|
||||
let tab = this.getParentTab(aTab);
|
||||
let index = tab ? aTabs.indexOf(tab) : -1 ;
|
||||
return index >= aIndex ? -1 : index ;
|
||||
}, this),
|
||||
-1
|
||||
);
|
||||
},
|
||||
cleanUpTreeStructureArray : function TSTBase_cleanUpTreeStructureArray(aTreeStructure, aDefaultParent)
|
||||
{
|
||||
var offset = 0;
|
||||
aTreeStructure = aTreeStructure
|
||||
.map(function(aPosition, aIndex) {
|
||||
return (aPosition == aIndex) ? -1 : aPosition ;
|
||||
})
|
||||
.map(function(aPosition, aIndex) {
|
||||
if (aPosition == -1) {
|
||||
offset = aIndex;
|
||||
return aPosition;
|
||||
}
|
||||
return aPosition - offset;
|
||||
});
|
||||
|
||||
/* The final step, this validates all of values.
|
||||
Smaller than -1 is invalid, so it becomes to -1. */
|
||||
aTreeStructure = aTreeStructure.map(function(aIndex) {
|
||||
return aIndex < -1 ? aDefaultParent : aIndex ;
|
||||
}, this);
|
||||
return aTreeStructure;
|
||||
},
|
||||
|
||||
applyTreeStructureToTabs : function TSTBase_applyTreeStructureToTabs(aTabs, aTreeStructure, aExpandStates)
|
||||
{
|
||||
var b = this.getTabBrowserFromChild(aTabs[0]);
|
||||
@ -2375,7 +2321,7 @@ var TreeStyleTabBase = inherit(TreeStyleTabConstants, {
|
||||
|
||||
getTreeStructureFromTabBrowser : function TSTBase_getTreeStructureFromTabBrowser(aTabBrowser)
|
||||
{
|
||||
return this.getTreeStructureFromTabs(this.getAllTabs(aTabBrowser));
|
||||
return utils.getTreeStructureFromTabs(this.getAllTabs(aTabBrowser));
|
||||
},
|
||||
|
||||
applyTreeStructureToTabBrowser : function TSTBase_applyTreeStructureToTabBrowser(aTabBrowser, aTreeStructure, aExpandAllTree)
|
||||
|
489
modules/bookmark.js
Normal file
489
modules/bookmark.js
Normal file
@ -0,0 +1,489 @@
|
||||
/* ***** 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 the Tree Style Tab.
|
||||
*
|
||||
* The Initial Developer of the Original Code is YUKI "Piro" Hiroshi.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2016
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s): YUKI "Piro" Hiroshi <piro.outsider.reflex@gmail.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 ******/
|
||||
|
||||
var EXPORTED_SYMBOLS = ['TreeStyleTabBookmarksService'];
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
|
||||
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
|
||||
|
||||
Cu.import('resource:///modules/PlacesUIUtils.jsm');
|
||||
Cu.import('resource://gre/modules/PlacesUtils.jsm');
|
||||
|
||||
Cu.import('resource://treestyletab-modules/lib/inherit.jsm');
|
||||
Cu.import('resource://treestyletab-modules/constants.js');
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, 'utils', 'resource://treestyletab-modules/utils.js', 'TreeStyleTabUtils');
|
||||
|
||||
function mydump(aString) {
|
||||
if (utils.isDebugging('bookmark'))
|
||||
dump(aString);
|
||||
}
|
||||
|
||||
var TreeStyleTabBookmarksService = inherit(TreeStyleTabConstants, {
|
||||
get BookmarksService() {
|
||||
if (!this._BookmarksService) {
|
||||
this._BookmarksService = Cc['@mozilla.org/browser/nav-bookmarks-service;1']
|
||||
.getService(Ci.nsINavBookmarksService);
|
||||
}
|
||||
return this._BookmarksService;
|
||||
},
|
||||
_BookmarksService : null,
|
||||
|
||||
|
||||
beginAddBookmarksFromTabs : function TSTBMService_beginAddBookmarksFromTabs(aTabs) /* PUBLIC API */
|
||||
{
|
||||
if (this._observing ||
|
||||
!aTabs ||
|
||||
aTabs.length <= 0)
|
||||
return;
|
||||
|
||||
this._observing = true;
|
||||
|
||||
var TST = aTabs[0].ownerDocument.defaultView.TreeStyleTabService;
|
||||
aTabs = TST.cleanUpTabsArray(aTabs);
|
||||
|
||||
this._addingBookmarks = [];
|
||||
this._addingBookmarkTreeStructure = aTabs.map(function(aTab) {
|
||||
var parent = TST.getParentTab(aTab);
|
||||
return aTabs.indexOf(parent);
|
||||
}, this);
|
||||
|
||||
this.BookmarksService.addObserver(this, false);
|
||||
},
|
||||
|
||||
endAddBookmarksFromTabs : function TSTBMService_endAddBookmarksFromTabs() /* PUBLIC API */
|
||||
{
|
||||
if (!this._observing)
|
||||
return;
|
||||
|
||||
this._observing = false;
|
||||
|
||||
this.BookmarksService.removeObserver(this);
|
||||
this.handleNewBookmarksFromTabs(this._addingBookmarks, this._addingBookmarkTreeStructure);
|
||||
this._addingBookmarks = [];
|
||||
this._addingBookmarkTreeStructure = [];
|
||||
},
|
||||
|
||||
handleNewBookmarksFromTabs : function TSTBMService_handleNewBookmarksFromTabs(aBookarmks, aTreeStructure)
|
||||
{
|
||||
// this is adding bookmark folder from tabs, so ignroe the first item!
|
||||
if (
|
||||
aBookarmks.length == aTreeStructure.length+1 &&
|
||||
this.BookmarksService.getItemType(aBookarmks[0].id) == this.BookmarksService.TYPE_FOLDER
|
||||
) {
|
||||
aBookarmks.shift();
|
||||
}
|
||||
else if (aBookarmks.length != aTreeStructure.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (let i = 0, maxi = aBookarmks.length; i < maxi; i++)
|
||||
{
|
||||
let item = aBookarmks[i];
|
||||
item.position = this.BookmarksService.getItemIndex(item.id);
|
||||
}
|
||||
aBookarmks.sort(function(aA, aB) {
|
||||
return aA.position - aB.position;
|
||||
});
|
||||
|
||||
for (let i = 0, maxi = aBookarmks.length; i < maxi; i++)
|
||||
{
|
||||
let item = aBookarmks[i];
|
||||
if (this.BookmarksService.getItemType(item.id) != this.BookmarksService.TYPE_BOOKMARK)
|
||||
continue;
|
||||
|
||||
let uri = this.BookmarksService.getBookmarkURI(item.id);
|
||||
if (/^about:treestyletab-group\b/.test(uri.spec)) {
|
||||
let title = this.BookmarksService.getItemTitle(item.id);
|
||||
let folderId = this.BookmarksService.createFolder(item.parent, title, item.position);
|
||||
this.BookmarksService.removeItem(item.id);
|
||||
item.id = folderId;
|
||||
item.isFolder = true;
|
||||
}
|
||||
|
||||
let index = aTreeStructure[i];
|
||||
let parent = index > -1 ? aBookarmks[index] : null ;
|
||||
if (parent && (parent.folder || parent).isFolder) {
|
||||
let folder = parent.isFolder ? parent : parent.folder ;
|
||||
this.BookmarksService.moveItem(item.id, folder.id, -1);
|
||||
item.folder = folder;
|
||||
}
|
||||
if (parent && !parent.isFolder) {
|
||||
PlacesUtils.setAnnotationsForItem(item.id, [{
|
||||
name : this.kPARENT,
|
||||
value : parent ? parent.id : -1,
|
||||
expires : PlacesUtils.annotations.EXPIRE_NEVER
|
||||
}]);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
bookmarkTabSubtree : function TSTBMService_bookmarkTabSubtree(aTabOrTabs)
|
||||
{
|
||||
var tabs = aTabOrTabs;
|
||||
if (!Array.isArray(tabs)) {
|
||||
tabs = [aTabOrTabs];
|
||||
}
|
||||
if (tabs.length <= 0)
|
||||
return;
|
||||
|
||||
var window = tabs[0].ownerDocument.defaultView;
|
||||
var TST = window.TreeStyleTabService;
|
||||
|
||||
var folderName = (TST.isGroupTab(tabs[0], true) || tabs.length == 1) ?
|
||||
tabs[0].label :
|
||||
null ;
|
||||
|
||||
var b = TST.getTabBrowserFromChild(tabs[0]);
|
||||
var bookmarkedTabs = [];
|
||||
for (let i = 0, maxi = tabs.length; i < maxi; i++)
|
||||
{
|
||||
let tab = tabs[i];
|
||||
if (!TST.isGroupTab(tab, i == 0))
|
||||
bookmarkedTabs.push(tab);
|
||||
bookmarkedTabs = bookmarkedTabs.concat(b.treeStyleTab.getDescendantTabs(tab));
|
||||
}
|
||||
|
||||
this.beginAddBookmarksFromTabs(bookmarkedTabs);
|
||||
try {
|
||||
window['piro.sakura.ne.jp'].bookmarkMultipleTabs.addBookmarkFor(bookmarkedTabs, folderName);
|
||||
}
|
||||
catch(e) {
|
||||
}
|
||||
this.endAddBookmarksFromTabs();
|
||||
},
|
||||
bookmarkTabSubTree : function() { return this.bookmarkTabSubtree.apply(this, arguments); }, // obsolete, for backward compatibility
|
||||
|
||||
getParentItem : function TSTBMService_getParentItem(aId)
|
||||
{
|
||||
if (aId < 0) return -1;
|
||||
var annotations = PlacesUtils.getAnnotationsForItem(aId);
|
||||
for (let i in annotations)
|
||||
{
|
||||
if (annotations[i].name != this.kPARENT) continue;
|
||||
return parseInt(annotations[i].value);
|
||||
}
|
||||
return -1;
|
||||
},
|
||||
|
||||
getTreeStructureFromItems : function TSTBMService_getTreeStructureFromItems(aIDs, aDefaultParentID)
|
||||
{
|
||||
/* this returns a result same to utils.getTreeStructureFromTabs().
|
||||
[A] => -1 (parent is not in this tree)
|
||||
[B] => 0 (parent is 1st item in this tree)
|
||||
[C] => 0 (parent is 1st item in this tree)
|
||||
[D] => 2 (parent is 2nd in this tree)
|
||||
[E] => -1 (parent is not in this tree, and this creates another tree)
|
||||
[F] => 0 (parent is 1st item in this another tree)
|
||||
*/
|
||||
if (aDefaultParentID === void(0))
|
||||
aDefaultParentID = -1;
|
||||
|
||||
/* Get array of parents. The index becomes to -1,
|
||||
if there is NO PARENT or the parent is THE TAB ITSELF. */
|
||||
var treeStructure = aIDs.map(function(aId, aIndex) {
|
||||
let id = this.getParentItem(aId);
|
||||
let index = aIDs.indexOf(id);
|
||||
return index >= aIndex ? aDefaultParentID : index ;
|
||||
}, this);
|
||||
|
||||
/* Correct patterns like:
|
||||
[TabA]
|
||||
[TabB] - this has no parent
|
||||
[TabC] - TabA's child
|
||||
to:
|
||||
[TabA]
|
||||
[TabB]
|
||||
[TabC]
|
||||
*/
|
||||
treeStructure = treeStructure.reverse();
|
||||
treeStructure = treeStructure.map(function(aPosition, aIndex) {
|
||||
if (aIndex > 0 &&
|
||||
aIndex < treeStructure.length-1 &&
|
||||
aPosition < 0) {
|
||||
aPosition = treeStructure[aIndex-1];
|
||||
}
|
||||
return aPosition;
|
||||
});
|
||||
treeStructure = treeStructure.reverse();
|
||||
|
||||
return utils.cleanUpTreeStructureArray(treeStructure, aDefaultParentID);
|
||||
},
|
||||
|
||||
// based on PlacesUtils.getURLsForContainerNode()
|
||||
getItemIdsForContainerNode : function TSTBMService_getItemIdsForContainerNode(aNode)
|
||||
{
|
||||
var ids = [];
|
||||
if (!aNode || !PlacesUtils.nodeIsContainer(aNode)) return ids;
|
||||
|
||||
var root = aNode;
|
||||
if ('getContainerNodeWithOptions' in PlacesUtils) {
|
||||
root = PlacesUtils.getContainerNodeWithOptions(root, false, true);
|
||||
}
|
||||
var oldViewer = root.parentResult.viewer;
|
||||
var wasOpen = root.containerOpen;
|
||||
if (!wasOpen) {
|
||||
if (oldViewer)
|
||||
root.parentResult.viewer = null;
|
||||
root.containerOpen = true;
|
||||
}
|
||||
for (let i = 0, maxi = root.childCount; i < maxi; ++i)
|
||||
{
|
||||
let child = root.getChild(i);
|
||||
if (PlacesUtils.nodeIsURI(child)) ids.push(child.itemId || -1);
|
||||
}
|
||||
if (!wasOpen) {
|
||||
root.containerOpen = false;
|
||||
if (oldViewer)
|
||||
root.parentResult.viewer = oldViewer;
|
||||
}
|
||||
return ids;
|
||||
},
|
||||
|
||||
handleTabsOpenProcess : function TSTBMService_handleTabsOpenProcess(aWhere, aEvent, aBrowserWindow, aIDs, aURLs, aItemsToOpen, aFolderTitle)
|
||||
{
|
||||
var result = {
|
||||
behavior : undefined,
|
||||
treeStructure : undefined,
|
||||
previousTabs : undefined,
|
||||
treeStructureApplied : false
|
||||
};
|
||||
if (
|
||||
aEvent.type != 'drop' &&
|
||||
aWhere.indexOf('tab') != 0 &&
|
||||
aEvent.target.id != 'placesContext_openContainer:tabs' &&
|
||||
aEvent.target.id != 'placesContext_openLinks:tabs' &&
|
||||
aEvent.target != aEvent.target.parentNode._endOptOpenAllInTabs &&
|
||||
aEvent.target.getAttribute('openInTabs') != 'true'
|
||||
)
|
||||
return result;
|
||||
|
||||
var TST = aBrowserWindow.TreeStyleTabService;
|
||||
|
||||
result.behavior = TST.openGroupBookmarkBehavior();
|
||||
if (result.behavior & this.kGROUP_BOOKMARK_SUBTREE) {
|
||||
mydump('TSTBMService_handleTabsOpenProcess: open as a group\n');
|
||||
let treeStructure = result.behavior & this.kGROUP_BOOKMARK_DONT_RESTORE_TREE_STRUCTURE ?
|
||||
null :
|
||||
this.getTreeStructureFromItems(aIDs) ;
|
||||
mydump(' treeStructure => '+JSON.stringify(treeStructure)+'\n');
|
||||
if (treeStructure) {
|
||||
let parentTabs = treeStructure.filter(function(aParent) {
|
||||
return aParent < 0;
|
||||
});
|
||||
let haveMultipleTrees = parentTabs.length != treeStructure.length;
|
||||
if (result.behavior & this.kGROUP_BOOKMARK_USE_DUMMY) {
|
||||
mydump(' trying to use dummy group tab\n');
|
||||
let parentCount = 0;
|
||||
let childCount = 0;
|
||||
for (let i in treeStructure) {
|
||||
if (treeStructure[i] == -1)
|
||||
parentCount++;
|
||||
else
|
||||
childCount++;
|
||||
}
|
||||
mydump(' parentCount: '+parentCount+'\n');
|
||||
mydump(' childCount: '+childCount+'\n');
|
||||
if (
|
||||
parentCount > 1 &&
|
||||
(
|
||||
result.behavior & this.kGROUP_BOOKMARK_USE_DUMMY_FORCE ||
|
||||
// when there is any orphan, then all of parents and orphans should be grouped under a dummy tab.
|
||||
childCount < parentCount
|
||||
)
|
||||
) {
|
||||
aIDs.unshift(-1);
|
||||
treeStructure = this.getTreeStructureFromItems(aIDs, 0);
|
||||
let uri = TST.getGroupTabURI({
|
||||
title: aFolderTitle,
|
||||
temporary: utils.getTreePref('openGroupBookmark.temporaryGroup')
|
||||
});
|
||||
aURLs.unshift(uri);
|
||||
aItemsToOpen.unshift({
|
||||
itemId: -1,
|
||||
title: aFolderTitle,
|
||||
uri: uri
|
||||
})
|
||||
mydump(' updated treeStructure => '+JSON.stringify(treeStructure)+'\n');
|
||||
}
|
||||
}
|
||||
else if (!haveMultipleTrees) {
|
||||
// make the first item parent.
|
||||
treeStructure = treeStructure.map(function(aParent, aIndex) {
|
||||
if (aIndex == 0)
|
||||
return aParent;
|
||||
if (aParent < 0)
|
||||
return 0;
|
||||
return aParent;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
result.treeStructure = treeStructure;
|
||||
result.previousTabs = TST.getTabsInfo(aBrowserWindow.gBrowser);
|
||||
|
||||
if (utils.getTreePref('compatibility.TMP') &&
|
||||
'TMP_Places' in aBrowserWindow &&
|
||||
'openGroup' in aBrowserWindow.TMP_Places) {
|
||||
result.treeStructureApplied = false;
|
||||
}
|
||||
else {
|
||||
TST.readyToOpenNewTabGroup(null, treeStructure, result.behavior & this.kGROUP_BOOKMARK_EXPAND_ALL_TREE);
|
||||
result.treeStructureApplied = true;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
|
||||
// observer for nsINavBookmarksService
|
||||
onItemAdded : function TSTBMService_onItemAdded(aID, aFolderID, aPosition)
|
||||
{
|
||||
this._addingBookmarks.push({
|
||||
id : aID,
|
||||
parent : aFolderID
|
||||
});
|
||||
},
|
||||
onItemRemoved : function TSTBMService_onItemRemoved(aID, aFolderID, aPosition) {},
|
||||
onItemMoved : function TSTBMService_onItemMoved(aID, aFolderID, aPosition) {},
|
||||
onItemChanged : function TSTBMService_onItemChanged(aID, aChange, aIsAnnotation, aNewValue) {},
|
||||
onItemVisited : function TSTBMService_onItemVisited(aID, aHistoryID, aDate) {},
|
||||
onBeginUpdateBatch : function TSTBMService_onBeginUpdateBatch() {},
|
||||
onEndUpdateBatch : function TSTBMService_onEndUpdateBatch() {}
|
||||
});
|
||||
|
||||
|
||||
PlacesUIUtils.__treestyletab__openTabset = PlacesUIUtils._openTabset;
|
||||
PlacesUIUtils._openTabset = function(aItemsToOpen, aEvent, aWindow, ...aArgs) {
|
||||
mydump('TSTBookmarks_openTabset\n');
|
||||
|
||||
var uris = [];
|
||||
var ids = [];
|
||||
var nodes = this.__treestyletab__openTabset_rawNodes || [];
|
||||
aItemsToOpen = aItemsToOpen.filter(function(aItem, aIndex) {
|
||||
if (aItem.uri) {
|
||||
uris.push(aItem.uri);
|
||||
let id = aItem.id;
|
||||
if (!id && aIndex in nodes)
|
||||
id = nodes[aIndex].itemId;
|
||||
ids.push(id);
|
||||
mydump(' '+aIndex+': '+id+' / '+aItem.uri+'\n');
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
mydump(' items => '+aItemsToOpen.length+'\n');
|
||||
|
||||
var allArgs = [aItemsToOpen, aEvent, aWindow].concat(aArgs);
|
||||
if (aItemsToOpen.length <= 0)
|
||||
return this.__treestyletab__openTabset.apply(this, allArgs);
|
||||
|
||||
var w = aWindow && aWindow.document.documentElement.getAttribute('windowtype') == 'navigator:browser' ?
|
||||
aWindow :
|
||||
this._getTopBrowserWin() ;
|
||||
var TST = w.TreeStyleTabService;
|
||||
var BS = TreeStyleTabBookmarksService;
|
||||
|
||||
var where = w && w.whereToOpenLink(aEvent, false, true) || 'window';
|
||||
mydump(' where: '+where+'\n');
|
||||
if (where === 'window')
|
||||
return this.__treestyletab__openTabset.apply(this, allArgs);
|
||||
|
||||
var result = BS.handleTabsOpenProcess(where, aEvent, w, ids, uris, aItemsToOpen, this.__treestyletab__folderName);
|
||||
|
||||
mydump(' result: '+JSON.stringify(result)+'\n');
|
||||
this.__treestyletab__openTabset.apply(this, allArgs);
|
||||
|
||||
var tabs = [];
|
||||
if (result.treeStructure && result.previousTabs)
|
||||
tabs = TST.getNewTabsFromPreviousTabsInfo(w.gBrowser, result.previousTabs);
|
||||
|
||||
if (!result.treeStructureApplied)
|
||||
TST.applyTreeStructureToTabs(
|
||||
tabs,
|
||||
result.treeStructure,
|
||||
result.behavior & BS.kGROUP_BOOKMARK_EXPAND_ALL_TREE
|
||||
);
|
||||
|
||||
var loadInBackground = where == 'tabshifted';
|
||||
if (!loadInBackground) {
|
||||
// start scroll after expanding animation is finished
|
||||
w.setTimeout(function() {
|
||||
w.gBrowser.treeStyleTab.scrollToTabs(tabs);
|
||||
}, w.gBrowser.treeStyleTab.collapseDuration);
|
||||
}
|
||||
};
|
||||
|
||||
PlacesUtils.__treestyletab__getURLsForContainerNode = PlacesUtils.getURLsForContainerNode;
|
||||
PlacesUtils.getURLsForContainerNode = function(aNode, ...aArgs) {
|
||||
var uris = this.__treestyletab__getURLsForContainerNode.apply(this, [aNode].concat(aArgs));
|
||||
var nodes = TreeStyleTabBookmarksService.getItemIdsForContainerNode(aNode);
|
||||
for (let i in nodes) {
|
||||
uris[i].id = nodes[i];
|
||||
}
|
||||
return uris;
|
||||
};
|
||||
|
||||
PlacesUIUtils.__treestyletab__openContainerNodeInTabs = PlacesUIUtils.openContainerNodeInTabs;
|
||||
PlacesUIUtils.openContainerNodeInTabs = function(aNode, ...aArgs) {
|
||||
this.__treestyletab__folderName = aNode.title;
|
||||
try {
|
||||
return this.__treestyletab__openContainerNodeInTabs.apply(this, [aNode].concat(aArgs));
|
||||
}
|
||||
finally {
|
||||
delete this.__treestyletab__folderName;
|
||||
}
|
||||
};
|
||||
|
||||
PlacesUIUtils.__treestyletab__openURINodesInTabs = PlacesUIUtils.openURINodesInTabs;
|
||||
PlacesUIUtils.openURINodesInTabs = function(aNode, ...aArgs) {
|
||||
try {
|
||||
this.__treestyletab__openTabset_rawNodes = aNodes;
|
||||
this.__treestyletab__folderName = utils.treeBundle.getFormattedString(
|
||||
PlacesUtils.nodeIsBookmark(aNodes[0]) ?
|
||||
'openSelectedPlaces.bookmarks' :
|
||||
'openSelectedPlaces.history',
|
||||
[aNodes[0].title, aNodes.length]
|
||||
);
|
||||
return this.__treestyletab__openURINodesInTabs.apply(this, [aNode].concat(aArgs));
|
||||
}
|
||||
finally {
|
||||
delete this.__treestyletab__openTabset_rawNodes;
|
||||
delete this.__treestyletab__folderName;
|
||||
}
|
||||
};
|
@ -6274,7 +6274,7 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, {
|
||||
sourceService.getAllTabs(sourceBrowser).length == aTabs.length
|
||||
);
|
||||
var newTabs = [];
|
||||
var treeStructure = sourceService.getTreeStructureFromTabs(aTabs);
|
||||
var treeStructure = utils.getTreeStructureFromTabs(aTabs);
|
||||
|
||||
// Firefox fails to "move" collapsed tabs. So, expand them first
|
||||
// and collapse them after they are moved.
|
||||
@ -6979,7 +6979,8 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, {
|
||||
scrollToTabs : function TSTBrowser_scrollToTabs(aTabs)
|
||||
{
|
||||
var firstTab = aTabs[0];
|
||||
if (!firstTab.parentNode) // do nothing for closed tab!
|
||||
if (!firstTab ||
|
||||
!firstTab.parentNode) // do nothing for closed tab!
|
||||
return;
|
||||
|
||||
var b = this.mTabBrowser;
|
||||
|
@ -220,6 +220,22 @@ var TreeStyleTabConstants = Object.freeze({
|
||||
RESTORE_STATE_STRUCTURE_RESTORED : 2,
|
||||
|
||||
|
||||
kDROPLINK_ASK : 0,
|
||||
kDROPLINK_FIXED : 1 + 2,
|
||||
kDROPLINK_LOAD : 1,
|
||||
kDROPLINK_NEWTAB : 2,
|
||||
|
||||
|
||||
kGROUP_BOOKMARK_ASK : 0,
|
||||
kGROUP_BOOKMARK_FIXED : 1 + 2 + 4,
|
||||
kGROUP_BOOKMARK_SUBTREE : 1,
|
||||
kGROUP_BOOKMARK_SEPARATE : 2,
|
||||
kGROUP_BOOKMARK_USE_DUMMY : 256,
|
||||
kGROUP_BOOKMARK_USE_DUMMY_FORCE : 1024,
|
||||
kGROUP_BOOKMARK_DONT_RESTORE_TREE_STRUCTURE : 512,
|
||||
kGROUP_BOOKMARK_EXPAND_ALL_TREE : 2048,
|
||||
|
||||
|
||||
CONTENT_SCRIPT : 'chrome://treestyletab/content/content-utils.js',
|
||||
CONTENT_SCRIPT_AUTOHIDE : 'chrome://treestyletab/content/content-utils-autohide.js',
|
||||
MESSAGE_TYPE : 'treestyletab',
|
||||
|
@ -572,7 +572,7 @@ catch(e) {
|
||||
}
|
||||
}
|
||||
|
||||
var treeStructure = sourceService.getTreeStructureFromTabs(draggedTabs);
|
||||
var treeStructure = utils.getTreeStructureFromTabs(draggedTabs);
|
||||
|
||||
var newTabs = sv.moveTabsInternal(draggedTabs, {
|
||||
duplicate : aInfo.action & sv.kACTION_DUPLICATE,
|
||||
|
@ -335,6 +335,50 @@ var TreeStyleTabUtils = {
|
||||
this.isPrefChanging(aKey);
|
||||
},
|
||||
|
||||
|
||||
|
||||
getTreeStructureFromTabs : function TSTUtils_getTreeStructureFromTabs(aTabs)
|
||||
{
|
||||
/* this returns...
|
||||
[A] => -1 (parent is not in this tree)
|
||||
[B] => 0 (parent is 1st item in this tree)
|
||||
[C] => 0 (parent is 1st item in this tree)
|
||||
[D] => 2 (parent is 2nd in this tree)
|
||||
[E] => -1 (parent is not in this tree, and this creates another tree)
|
||||
[F] => 0 (parent is 1st item in this another tree)
|
||||
*/
|
||||
return this.cleanUpTreeStructureArray(
|
||||
aTabs.map(function(aTab, aIndex) {
|
||||
let tab = this.getParentTab(aTab);
|
||||
let index = tab ? aTabs.indexOf(tab) : -1 ;
|
||||
return index >= aIndex ? -1 : index ;
|
||||
}, this),
|
||||
-1
|
||||
);
|
||||
},
|
||||
cleanUpTreeStructureArray : function TSTUtils_cleanUpTreeStructureArray(aTreeStructure, aDefaultParent)
|
||||
{
|
||||
var offset = 0;
|
||||
aTreeStructure = aTreeStructure
|
||||
.map(function(aPosition, aIndex) {
|
||||
return (aPosition == aIndex) ? -1 : aPosition ;
|
||||
})
|
||||
.map(function(aPosition, aIndex) {
|
||||
if (aPosition == -1) {
|
||||
offset = aIndex;
|
||||
return aPosition;
|
||||
}
|
||||
return aPosition - offset;
|
||||
});
|
||||
|
||||
/* The final step, this validates all of values.
|
||||
Smaller than -1 is invalid, so it becomes to -1. */
|
||||
aTreeStructure = aTreeStructure.map(function(aIndex) {
|
||||
return aIndex < -1 ? aDefaultParent : aIndex ;
|
||||
}, this);
|
||||
return aTreeStructure;
|
||||
},
|
||||
|
||||
/* Pref Listener */
|
||||
domains : [
|
||||
'extensions.treestyletab.'
|
||||
|
Loading…
x
Reference in New Issue
Block a user