Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 this.EXPORTED_SYMBOLS = ["RecentlyClosedTabsAndWindowsMenuUtils"];
7 const kNSXUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
9 var Ci = Components.interfaces;
10 var Cc = Components.classes;
11 var Cr = Components.results;
12 var Cu = Components.utils;
14 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
15 Cu.import("resource://gre/modules/Services.jsm");
17 XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
18 "resource://gre/modules/PluralForm.jsm");
20 let navigatorBundle = Services.strings.createBundle("chrome://browser/locale/browser.properties");
21 let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
23 this.RecentlyClosedTabsAndWindowsMenuUtils = {
25 /**
26 * Builds up a document fragment of UI items for the recently closed tabs.
27 * @param aWindow
28 * The window that the tabs were closed in.
29 * @param aTagName
30 * The tag name that will be used when creating the UI items.
31 * @param aPrefixRestoreAll (defaults to false)
32 * Whether the 'restore all tabs' item is suffixed or prefixed to the list.
33 * If suffixed (the default) a separator will be inserted before it.
34 * @param aRestoreAllLabel (defaults to "menuRestoreAllTabs.label")
35 * Which localizable string to use for the 'restore all tabs' item.
36 * @returns A document fragment with UI items for each recently closed tab.
37 */
38 getTabsFragment: function(aWindow, aTagName, aPrefixRestoreAll=false,
39 aRestoreAllLabel="menuRestoreAllTabs.label") {
40 let doc = aWindow.document;
41 let fragment = doc.createDocumentFragment();
42 if (ss.getClosedTabCount(aWindow) != 0) {
43 let closedTabs = JSON.parse(ss.getClosedTabData(aWindow));
44 for (let i = 0; i < closedTabs.length; i++) {
45 let element = doc.createElementNS(kNSXUL, aTagName);
46 element.setAttribute("label", closedTabs[i].title);
47 if (closedTabs[i].image) {
48 setImage(closedTabs[i], element);
49 }
50 element.setAttribute("value", i);
51 if (aTagName == "menuitem") {
52 element.setAttribute("class", "menuitem-iconic bookmark-item menuitem-with-favicon");
53 }
54 element.setAttribute("oncommand", "undoCloseTab(" + i + ");");
56 // Set the targetURI attribute so it will be shown in tooltip and trigger
57 // onLinkHovered. SessionStore uses one-based indexes, so we need to
58 // normalize them.
59 let tabData = closedTabs[i].state;
60 let activeIndex = (tabData.index || tabData.entries.length) - 1;
61 if (activeIndex >= 0 && tabData.entries[activeIndex]) {
62 element.setAttribute("targetURI", tabData.entries[activeIndex].url);
63 }
65 element.addEventListener("click", this._undoCloseMiddleClick, false);
66 if (i == 0)
67 element.setAttribute("key", "key_undoCloseTab");
68 fragment.appendChild(element);
69 }
71 let restoreAllTabs = doc.createElementNS(kNSXUL, aTagName);
72 restoreAllTabs.classList.add("restoreallitem");
73 restoreAllTabs.setAttribute("label", navigatorBundle.GetStringFromName(aRestoreAllLabel));
74 restoreAllTabs.setAttribute("oncommand",
75 "for (var i = 0; i < " + closedTabs.length + "; i++) undoCloseTab();");
76 if (!aPrefixRestoreAll) {
77 fragment.appendChild(doc.createElementNS(kNSXUL, "menuseparator"));
78 fragment.appendChild(restoreAllTabs);
79 } else {
80 fragment.insertBefore(restoreAllTabs, fragment.firstChild);
81 }
82 }
83 return fragment;
84 },
86 /**
87 * Builds up a document fragment of UI items for the recently closed windows.
88 * @param aWindow
89 * A window that can be used to create the elements and document fragment.
90 * @param aTagName
91 * The tag name that will be used when creating the UI items.
92 * @param aPrefixRestoreAll (defaults to false)
93 * Whether the 'restore all windows' item is suffixed or prefixed to the list.
94 * If suffixed (the default) a separator will be inserted before it.
95 * @param aRestoreAllLabel (defaults to "menuRestoreAllWindows.label")
96 * Which localizable string to use for the 'restore all windows' item.
97 * @returns A document fragment with UI items for each recently closed window.
98 */
99 getWindowsFragment: function(aWindow, aTagName, aPrefixRestoreAll=false,
100 aRestoreAllLabel="menuRestoreAllWindows.label") {
101 let closedWindowData = JSON.parse(ss.getClosedWindowData());
102 let fragment = aWindow.document.createDocumentFragment();
103 if (closedWindowData.length != 0) {
104 let menuLabelString = navigatorBundle.GetStringFromName("menuUndoCloseWindowLabel");
105 let menuLabelStringSingleTab =
106 navigatorBundle.GetStringFromName("menuUndoCloseWindowSingleTabLabel");
108 let doc = aWindow.document;
109 for (let i = 0; i < closedWindowData.length; i++) {
110 let undoItem = closedWindowData[i];
111 let otherTabsCount = undoItem.tabs.length - 1;
112 let label = (otherTabsCount == 0) ? menuLabelStringSingleTab
113 : PluralForm.get(otherTabsCount, menuLabelString);
114 let menuLabel = label.replace("#1", undoItem.title)
115 .replace("#2", otherTabsCount);
116 let item = doc.createElementNS(kNSXUL, aTagName);
117 item.setAttribute("label", menuLabel);
118 let selectedTab = undoItem.tabs[undoItem.selected - 1];
119 if (selectedTab.image) {
120 setImage(selectedTab, item);
121 }
122 if (aTagName == "menuitem") {
123 item.setAttribute("class", "menuitem-iconic bookmark-item menuitem-with-favicon");
124 }
125 item.setAttribute("oncommand", "undoCloseWindow(" + i + ");");
127 // Set the targetURI attribute so it will be shown in tooltip.
128 // SessionStore uses one-based indexes, so we need to normalize them.
129 let activeIndex = (selectedTab.index || selectedTab.entries.length) - 1;
130 if (activeIndex >= 0 && selectedTab.entries[activeIndex])
131 item.setAttribute("targetURI", selectedTab.entries[activeIndex].url);
133 if (i == 0)
134 item.setAttribute("key", "key_undoCloseWindow");
135 fragment.appendChild(item);
136 }
138 // "Open All in Windows"
139 let restoreAllWindows = doc.createElementNS(kNSXUL, aTagName);
140 restoreAllWindows.classList.add("restoreallitem");
141 restoreAllWindows.setAttribute("label", navigatorBundle.GetStringFromName(aRestoreAllLabel));
142 restoreAllWindows.setAttribute("oncommand",
143 "for (var i = 0; i < " + closedWindowData.length + "; i++) undoCloseWindow();");
144 if (!aPrefixRestoreAll) {
145 fragment.appendChild(doc.createElementNS(kNSXUL, "menuseparator"));
146 fragment.appendChild(restoreAllWindows);
147 } else {
148 fragment.insertBefore(restoreAllWindows, fragment.firstChild);
149 }
150 }
151 return fragment;
152 },
155 /**
156 * Re-open a closed tab and put it to the end of the tab strip.
157 * Used for a middle click.
158 * @param aEvent
159 * The event when the user clicks the menu item
160 */
161 _undoCloseMiddleClick: function(aEvent) {
162 if (aEvent.button != 1)
163 return;
165 aEvent.view.undoCloseTab(aEvent.originalTarget.getAttribute("value"));
166 aEvent.view.gBrowser.moveTabToEnd();
167 },
168 };
170 function setImage(aItem, aElement) {
171 let iconURL = aItem.image;
172 // don't initiate a connection just to fetch a favicon (see bug 467828)
173 if (/^https?:/.test(iconURL))
174 iconURL = "moz-anno:favicon:" + iconURL;
175 aElement.setAttribute("image", iconURL);
176 }