зеркало из https://github.com/mozilla/gecko-dev.git
merge fx-team to mozilla-central
This commit is contained in:
Коммит
2446abd3df
|
@ -219,30 +219,37 @@
|
|||
accesskey="&hidePluginCmd.accesskey;"
|
||||
oncommand="gContextMenu.hidePlugin();"/>
|
||||
<menuseparator id="context-sep-ctp"/>
|
||||
<menuitem id="context-back"
|
||||
label="&backCmd.label;"
|
||||
accesskey="&backCmd.accesskey;"
|
||||
command="Browser:BackOrBackDuplicate"
|
||||
onclick="checkForMiddleClick(this, event);"/>
|
||||
<menuitem id="context-forward"
|
||||
label="&forwardCmd.label;"
|
||||
accesskey="&forwardCmd.accesskey;"
|
||||
command="Browser:ForwardOrForwardDuplicate"
|
||||
onclick="checkForMiddleClick(this, event);"/>
|
||||
<menuitem id="context-reload"
|
||||
label="&reloadCmd.label;"
|
||||
accesskey="&reloadCmd.accesskey;"
|
||||
oncommand="gContextMenu.reload(event);"
|
||||
onclick="checkForMiddleClick(this, event);"/>
|
||||
<menuitem id="context-stop"
|
||||
label="&stopCmd.label;"
|
||||
accesskey="&stopCmd.accesskey;"
|
||||
command="Browser:Stop"/>
|
||||
<menuseparator id="context-sep-stop"/>
|
||||
<menuitem id="context-bookmarkpage"
|
||||
label="&bookmarkPageCmd2.label;"
|
||||
accesskey="&bookmarkPageCmd2.accesskey;"
|
||||
oncommand="gContextMenu.bookmarkThisPage();"/>
|
||||
<menugroup id="context-navigation">
|
||||
<menuitem id="context-back"
|
||||
class="menuitem-iconic"
|
||||
tooltiptext="&backButton.tooltip;"
|
||||
aria-label="&backCmd.label;"
|
||||
command="Browser:BackOrBackDuplicate"
|
||||
onclick="checkForMiddleClick(this, event);"/>
|
||||
<menuitem id="context-forward"
|
||||
class="menuitem-iconic"
|
||||
tooltiptext="&forwardButton.tooltip;"
|
||||
aria-label="&forwardCmd.label;"
|
||||
command="Browser:ForwardOrForwardDuplicate"
|
||||
onclick="checkForMiddleClick(this, event);"/>
|
||||
<menuitem id="context-reload"
|
||||
class="menuitem-iconic"
|
||||
tooltiptext="&reloadButton.tooltip;"
|
||||
aria-label="&reloadCmd.label;"
|
||||
oncommand="gContextMenu.reload(event);"
|
||||
onclick="checkForMiddleClick(this, event);"/>
|
||||
<menuitem id="context-stop"
|
||||
class="menuitem-iconic"
|
||||
tooltiptext="&stopButton.tooltip;"
|
||||
aria-label="&stopCmd.label;"
|
||||
command="Browser:Stop"/>
|
||||
<menuitem id="context-bookmarkpage"
|
||||
class="menuitem-iconic"
|
||||
tooltiptext="&bookmarkPageCmd2.label;"
|
||||
aria-label="&bookmarkPageCmd2.label;"
|
||||
oncommand="gContextMenu.bookmarkThisPage();"/>
|
||||
</menugroup>
|
||||
<menuseparator id="context-sep-navigation"/>
|
||||
<menuitem id="context-sharepage"
|
||||
label="&sharePageCmd.label;"
|
||||
accesskey="&sharePageCmd.accesskey;"
|
||||
|
|
|
@ -1133,3 +1133,9 @@ toolbarpaletteitem[place="palette"][hidden] {
|
|||
animation-name: uitour-color;
|
||||
animation-duration: 2s;
|
||||
}
|
||||
|
||||
/* Combined context-menu items */
|
||||
#context-navigation > .menuitem-iconic > .menu-iconic-text,
|
||||
#context-navigation > .menuitem-iconic > .menu-accel-container {
|
||||
display: none;
|
||||
}
|
||||
|
|
|
@ -151,8 +151,8 @@ nsContextMenu.prototype = {
|
|||
var shouldShow = !(this.isContentSelected || this.onLink || this.onImage ||
|
||||
this.onCanvas || this.onVideo || this.onAudio ||
|
||||
this.onTextInput || this.onSocial);
|
||||
this.showItem("context-back", shouldShow);
|
||||
this.showItem("context-forward", shouldShow);
|
||||
this.showItem("context-navigation", shouldShow);
|
||||
this.showItem("context-sep-navigation", shouldShow);
|
||||
|
||||
let stopped = XULBrowserWindow.stopCommand.getAttribute("disabled") == "true";
|
||||
|
||||
|
@ -163,7 +163,6 @@ nsContextMenu.prototype = {
|
|||
|
||||
this.showItem("context-reload", stopReloadItem == "reload");
|
||||
this.showItem("context-stop", stopReloadItem == "stop");
|
||||
this.showItem("context-sep-stop", !!stopReloadItem);
|
||||
|
||||
// XXX: Stop is determined in browser.js; the canStop broadcaster is broken
|
||||
//this.setItemAttrFromNode( "context-stop", "disabled", "canStop" );
|
||||
|
@ -270,7 +269,8 @@ nsContextMenu.prototype = {
|
|||
// Use "Bookmark This Link" if on a link.
|
||||
this.showItem("context-bookmarkpage",
|
||||
!(this.isContentSelected || this.onTextInput || this.onLink ||
|
||||
this.onImage || this.onVideo || this.onAudio || this.onSocial));
|
||||
this.onImage || this.onVideo || this.onAudio || this.onSocial ||
|
||||
this.onCanvas));
|
||||
this.showItem("context-bookmarklink", (this.onLink && !this.onMailtoLink &&
|
||||
!this.onSocial) || this.onPlainTextLink);
|
||||
this.showItem("context-keywordfield",
|
||||
|
|
|
@ -26,11 +26,13 @@ function test() {
|
|||
EventUtils.synthesizeMouseAtCenter(video1,
|
||||
{ type: "contextmenu", button: 2 },
|
||||
gBrowser.contentWindow);
|
||||
info("context menu click on video1");
|
||||
});
|
||||
});
|
||||
|
||||
function contextMenuOpened(event) {
|
||||
event.currentTarget.removeEventListener("popupshown", contextMenuOpened);
|
||||
info("context menu opened on video1");
|
||||
|
||||
// Create the folder the video will be saved into.
|
||||
var destDir = createTemporarySaveDirectory();
|
||||
|
@ -56,6 +58,7 @@ function test() {
|
|||
// Select "Save Video As" option from context menu
|
||||
var saveVideoCommand = document.getElementById("context-savevideo");
|
||||
saveVideoCommand.doCommand();
|
||||
info("context-savevideo command executed");
|
||||
|
||||
event.target.hidePopup();
|
||||
}
|
||||
|
|
|
@ -96,10 +96,23 @@ function getVisibleMenuItems(aMenu, aData) {
|
|||
}
|
||||
items.push(item.id);
|
||||
items.push(!item.disabled);
|
||||
// Add a dummy item to that the indexes in checkMenu are the same
|
||||
// Add a dummy item so that the indexes in checkMenu are the same
|
||||
// for expectedItems and actualItems.
|
||||
items.push([]);
|
||||
items.push(null);
|
||||
} else if (item.nodeName == "menugroup") {
|
||||
ok(item.id, "child menugroup #" + i + " has an ID");
|
||||
items.push(item.id);
|
||||
items.push(!item.disabled);
|
||||
var menugroupChildren = [];
|
||||
for (var child of item.children) {
|
||||
if (child.hidden)
|
||||
continue;
|
||||
|
||||
menugroupChildren.push([child.id, !child.disabled]);
|
||||
}
|
||||
items.push(menugroupChildren);
|
||||
items.push(null);
|
||||
} else {
|
||||
ok(false, "child #" + i + " of menu ID " + aMenu.id +
|
||||
" has an unknown type (" + item.nodeName + ")");
|
||||
|
@ -114,6 +127,43 @@ function checkContextMenu(expectedItems) {
|
|||
checkMenu(contextMenu, expectedItems, data);
|
||||
}
|
||||
|
||||
function checkMenuItem(actualItem, actualEnabled, expectedItem, expectedEnabled, index) {
|
||||
is(actualItem, expectedItem,
|
||||
"checking item #" + index/2 + " (" + expectedItem + ") name");
|
||||
|
||||
if (typeof expectedEnabled == "object" && expectedEnabled != null ||
|
||||
typeof actualEnabled == "object" && actualEnabled != null) {
|
||||
|
||||
ok(!(actualEnabled == null), "actualEnabled is not null");
|
||||
ok(!(expectedEnabled == null), "expectedEnabled is not null");
|
||||
is(typeof actualEnabled, typeof expectedEnabled, "checking types");
|
||||
|
||||
if (typeof actualEnabled != typeof expectedEnabled ||
|
||||
actualEnabled == null || expectedEnabled == null)
|
||||
return;
|
||||
|
||||
is(actualEnabled.type, expectedEnabled.type,
|
||||
"checking item #" + index/2 + " (" + expectedItem + ") type attr value");
|
||||
var icon = actualEnabled.icon;
|
||||
if (icon) {
|
||||
var tmp = "";
|
||||
var j = icon.length - 1;
|
||||
while (j && icon[j] != "/") {
|
||||
tmp = icon[j--] + tmp;
|
||||
}
|
||||
icon = tmp;
|
||||
}
|
||||
is(icon, expectedEnabled.icon,
|
||||
"checking item #" + index/2 + " (" + expectedItem + ") icon attr value");
|
||||
is(actualEnabled.checked, expectedEnabled.checked,
|
||||
"checking item #" + index/2 + " (" + expectedItem + ") has checked attr");
|
||||
is(actualEnabled.disabled, expectedEnabled.disabled,
|
||||
"checking item #" + index/2 + " (" + expectedItem + ") has disabled attr");
|
||||
} else if (expectedEnabled != null)
|
||||
is(actualEnabled, expectedEnabled,
|
||||
"checking item #" + index/2 + " (" + expectedItem + ") enabled state");
|
||||
}
|
||||
|
||||
/*
|
||||
* checkMenu - checks to see if the specified <menupopup> contains the
|
||||
* expected items and state.
|
||||
|
@ -136,50 +186,26 @@ function checkMenu(menu, expectedItems, data) {
|
|||
var expectedItem = expectedItems[i];
|
||||
var expectedEnabled = expectedItems[i + 1];
|
||||
if (expectedItem instanceof Array) {
|
||||
ok(true, "Checking submenu...");
|
||||
var menuID = expectedItems[i - 2]; // The last item was the menu ID.
|
||||
var submenu = menu.getElementsByAttribute("id", menuID)[0];
|
||||
ok(submenu, "got a submenu element of id='" + menuID + "'");
|
||||
if (submenu) {
|
||||
is(submenu.nodeName, "menu", "submenu element of id='" + menuID +
|
||||
ok(true, "Checking submenu/menugroup...");
|
||||
var previousId = expectedItems[i - 2]; // The last item was the menu ID.
|
||||
var previousItem = menu.getElementsByAttribute("id", previousId)[0];
|
||||
ok(previousItem, (previousItem ? previousItem.nodeName : "item") + " with previous id (" + previousId + ") found");
|
||||
if (previousItem && previousItem.nodeName == "menu") {
|
||||
ok(previousItem, "got a submenu element of id='" + previousId + "'");
|
||||
is(previousItem.nodeName, "menu", "submenu element of id='" + previousId +
|
||||
"' has expected nodeName");
|
||||
checkMenu(submenu.menupopup, expectedItem, data);
|
||||
checkMenu(previousItem.menupopup, expectedItem, data, i);
|
||||
} else if (previousItem && previousItem.nodeName == "menugroup") {
|
||||
ok(expectedItem.length, "menugroup must not be empty");
|
||||
for (var j = 0; j < expectedItem.length / 2; j++) {
|
||||
checkMenuItem(actualItems[i][j][0], actualItems[i][j][1], expectedItem[j*2], expectedItem[j*2+1], i+j*2);
|
||||
}
|
||||
i += j;
|
||||
} else {
|
||||
ok(false, "previous item is not a menu or menugroup");
|
||||
}
|
||||
} else {
|
||||
is(actualItem, expectedItem,
|
||||
"checking item #" + i/2 + " (" + expectedItem + ") name");
|
||||
|
||||
if (typeof expectedEnabled == "object" && expectedEnabled != null ||
|
||||
typeof actualEnabled == "object" && actualEnabled != null) {
|
||||
|
||||
ok(!(actualEnabled == null), "actualEnabled is not null");
|
||||
ok(!(expectedEnabled == null), "expectedEnabled is not null");
|
||||
is(typeof actualEnabled, typeof expectedEnabled, "checking types");
|
||||
|
||||
if (typeof actualEnabled != typeof expectedEnabled ||
|
||||
actualEnabled == null || expectedEnabled == null)
|
||||
continue;
|
||||
|
||||
is(actualEnabled.type, expectedEnabled.type,
|
||||
"checking item #" + i/2 + " (" + expectedItem + ") type attr value");
|
||||
var icon = actualEnabled.icon;
|
||||
if (icon) {
|
||||
var tmp = "";
|
||||
var j = icon.length - 1;
|
||||
while (j && icon[j] != "/") {
|
||||
tmp = icon[j--] + tmp;
|
||||
}
|
||||
icon = tmp;
|
||||
}
|
||||
is(icon, expectedEnabled.icon,
|
||||
"checking item #" + i/2 + " (" + expectedItem + ") icon attr value");
|
||||
is(actualEnabled.checked, expectedEnabled.checked,
|
||||
"checking item #" + i/2 + " (" + expectedItem + ") has checked attr");
|
||||
is(actualEnabled.disabled, expectedEnabled.disabled,
|
||||
"checking item #" + i/2 + " (" + expectedItem + ") has disabled attr");
|
||||
} else if (expectedEnabled != null)
|
||||
is(actualEnabled, expectedEnabled,
|
||||
"checking item #" + i/2 + " (" + expectedItem + ") enabled state");
|
||||
checkMenuItem(actualItem, actualEnabled, expectedItem, expectedEnabled, i);
|
||||
}
|
||||
}
|
||||
// Could find unexpected extra items at the end...
|
||||
|
|
|
@ -91,11 +91,12 @@ function runTest(testNum) {
|
|||
|
||||
case 2:
|
||||
// Context menu for plain text
|
||||
plainTextItems = ["context-back", false,
|
||||
"context-forward", false,
|
||||
"context-reload", true,
|
||||
plainTextItems = ["context-navigation", null,
|
||||
["context-back", false,
|
||||
"context-forward", false,
|
||||
"context-reload", true,
|
||||
"context-bookmarkpage", true], null,
|
||||
"---", null,
|
||||
"context-bookmarkpage", true,
|
||||
"context-savepage", true,
|
||||
"---", null,
|
||||
"context-viewbgimage", false,
|
||||
|
@ -163,7 +164,6 @@ function runTest(testNum) {
|
|||
// Context menu for a canvas
|
||||
checkContextMenu(["context-viewimage", true,
|
||||
"context-saveimage", true,
|
||||
"context-bookmarkpage", true,
|
||||
"context-selectall", true
|
||||
].concat(inspectItems));
|
||||
closeContextMenu();
|
||||
|
@ -264,11 +264,12 @@ function runTest(testNum) {
|
|||
|
||||
case 11:
|
||||
// Context menu for an iframe
|
||||
checkContextMenu(["context-back", false,
|
||||
"context-forward", false,
|
||||
"context-reload", true,
|
||||
checkContextMenu(["context-navigation", null,
|
||||
["context-back", false,
|
||||
"context-forward", false,
|
||||
"context-reload", true,
|
||||
"context-bookmarkpage", true], null,
|
||||
"---", null,
|
||||
"context-bookmarkpage", true,
|
||||
"context-savepage", true,
|
||||
"---", null,
|
||||
"context-viewbgimage", false,
|
||||
|
@ -468,11 +469,12 @@ function runTest(testNum) {
|
|||
"---", null,
|
||||
"+Checkbox", {type: "checkbox", icon: "", checked: false, disabled: false}], null,
|
||||
"---", null,
|
||||
"context-back", false,
|
||||
"context-forward", false,
|
||||
"context-reload", true,
|
||||
"context-navigation", null,
|
||||
["context-back", false,
|
||||
"context-forward", false,
|
||||
"context-reload", true,
|
||||
"context-bookmarkpage", true], null,
|
||||
"---", null,
|
||||
"context-bookmarkpage", true,
|
||||
"context-savepage", true,
|
||||
"---", null,
|
||||
"context-viewbgimage", false,
|
||||
|
@ -501,11 +503,12 @@ function runTest(testNum) {
|
|||
// Context menu for DOM Fullscreen mode (NOTE: this is *NOT* on an img)
|
||||
checkContextMenu(["context-leave-dom-fullscreen", true,
|
||||
"---", null,
|
||||
"context-back", false,
|
||||
"context-forward", false,
|
||||
"context-reload", true,
|
||||
"context-navigation", null,
|
||||
["context-back", false,
|
||||
"context-forward", false,
|
||||
"context-reload", true,
|
||||
"context-bookmarkpage", true], null,
|
||||
"---", null,
|
||||
"context-bookmarkpage", true,
|
||||
"context-savepage", true,
|
||||
"---", null,
|
||||
"context-viewbgimage", false,
|
||||
|
@ -529,11 +532,12 @@ function runTest(testNum) {
|
|||
case 21:
|
||||
// Context menu for element with assigned content context menu
|
||||
// The shift key should bypass content context menu processing
|
||||
checkContextMenu(["context-back", false,
|
||||
"context-forward", false,
|
||||
"context-reload", true,
|
||||
checkContextMenu(["context-navigation", null,
|
||||
["context-back", false,
|
||||
"context-forward", false,
|
||||
"context-reload", true,
|
||||
"context-bookmarkpage", true], null,
|
||||
"---", null,
|
||||
"context-bookmarkpage", true,
|
||||
"context-savepage", true,
|
||||
"---", null,
|
||||
"context-viewbgimage", false,
|
||||
|
@ -693,11 +697,12 @@ function runTest(testNum) {
|
|||
checkContextMenu(["context-ctp-play", true,
|
||||
"context-ctp-hide", true,
|
||||
"---", null,
|
||||
"context-back", false,
|
||||
"context-forward", false,
|
||||
"context-reload", true,
|
||||
"context-navigation", null,
|
||||
["context-back", false,
|
||||
"context-forward", false,
|
||||
"context-reload", true,
|
||||
"context-bookmarkpage", true], null,
|
||||
"---", null,
|
||||
"context-bookmarkpage", true,
|
||||
"context-savepage", true,
|
||||
"---", null,
|
||||
"context-viewbgimage", false,
|
||||
|
@ -730,11 +735,12 @@ function runTest(testNum) {
|
|||
|
||||
case 29:
|
||||
// Context menu for an iframe with srcdoc attribute set
|
||||
checkContextMenu(["context-back", false,
|
||||
"context-forward", false,
|
||||
"context-reload", true,
|
||||
checkContextMenu(["context-navigation", null,
|
||||
["context-back", false,
|
||||
"context-forward", false,
|
||||
"context-reload", true,
|
||||
"context-bookmarkpage", true], null,
|
||||
"---", null,
|
||||
"context-bookmarkpage", true,
|
||||
"context-savepage", true,
|
||||
"---", null,
|
||||
"context-viewbgimage", false,
|
||||
|
|
|
@ -189,11 +189,12 @@ function runTest(testNum) {
|
|||
case 13: // type='number'
|
||||
case 14: // type='color'
|
||||
case 15: // type='range'
|
||||
checkContextMenu(["context-back", false,
|
||||
"context-forward", false,
|
||||
"context-reload", true,
|
||||
checkContextMenu(["context-navigation", null,
|
||||
["context-back", false,
|
||||
"context-forward", false,
|
||||
"context-reload", true,
|
||||
"context-bookmarkpage", true], null,
|
||||
"---", null,
|
||||
"context-bookmarkpage", true,
|
||||
"context-savepage", true,
|
||||
"---", null,
|
||||
"context-viewbgimage", false,
|
||||
|
|
|
@ -74,9 +74,12 @@ function test1() {
|
|||
// When the popupshown DOM event is fired, the actual showing of the popup
|
||||
// may still be pending. Clear the event loop before continuing so that
|
||||
// subsequently-opened popups aren't cancelled by accident.
|
||||
let goToNext = function() {
|
||||
let goToNext = function(aEvent) {
|
||||
window.document.removeEventListener("popupshown", goToNext, false);
|
||||
executeSoon(test2);
|
||||
executeSoon(function() {
|
||||
test2();
|
||||
aEvent.target.hidePopup();
|
||||
});
|
||||
};
|
||||
window.document.addEventListener("popupshown", goToNext, false);
|
||||
EventUtils.synthesizeMouseAtCenter(plugin,
|
||||
|
|
|
@ -85,7 +85,7 @@ function checkSpecialContextMenus() {
|
|||
let menuPopup = document.getElementById(kSpecialItemIDs[menuID]);
|
||||
info("Waiting to open menu for " + menuID);
|
||||
let shownPromise = popupShown(menuPopup);
|
||||
EventUtils.synthesizeMouseAtCenter(menuItem, {});
|
||||
menuPopup.openPopup(menuItem, null, 0, 0, false, false, null);
|
||||
yield shownPromise;
|
||||
|
||||
yield checkPlacesContextMenu(menuPopup);
|
||||
|
|
|
@ -15,6 +15,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "PlacesBackups",
|
|||
XPCOMUtils.defineLazyModuleGetter(this, "DownloadUtils",
|
||||
"resource://gre/modules/DownloadUtils.jsm");
|
||||
|
||||
const RESTORE_FILEPICKER_FILTER_EXT = "*.json;*.jsonlz4";
|
||||
|
||||
var PlacesOrganizer = {
|
||||
_places: null,
|
||||
|
||||
|
@ -489,7 +491,7 @@ var PlacesOrganizer = {
|
|||
fp.init(window, PlacesUIUtils.getString("bookmarksRestoreTitle"),
|
||||
Ci.nsIFilePicker.modeOpen);
|
||||
fp.appendFilter(PlacesUIUtils.getString("bookmarksRestoreFilterName"),
|
||||
PlacesUIUtils.getString("bookmarksRestoreFilterExtension"));
|
||||
RESTORE_FILEPICKER_FILTER_EXT);
|
||||
fp.appendFilters(Ci.nsIFilePicker.filterAll);
|
||||
fp.displayDirectory = backupsDir;
|
||||
fp.open(fpCallback);
|
||||
|
@ -500,7 +502,7 @@ var PlacesOrganizer = {
|
|||
*/
|
||||
restoreBookmarksFromFile: function PO_restoreBookmarksFromFile(aFilePath) {
|
||||
// check file extension
|
||||
if (!aFilePath.endsWith("json")) {
|
||||
if (!aFilePath.endsWith("json") && !aFilePath.endsWith("jsonlz4")) {
|
||||
this._showErrorAlert(PlacesUIUtils.getString("bookmarksRestoreFormatError"));
|
||||
return;
|
||||
}
|
||||
|
@ -551,7 +553,7 @@ var PlacesOrganizer = {
|
|||
fp.init(window, PlacesUIUtils.getString("bookmarksBackupTitle"),
|
||||
Ci.nsIFilePicker.modeSave);
|
||||
fp.appendFilter(PlacesUIUtils.getString("bookmarksRestoreFilterName"),
|
||||
PlacesUIUtils.getString("bookmarksRestoreFilterExtension"));
|
||||
RESTORE_FILEPICKER_FILTER_EXT);
|
||||
fp.defaultString = PlacesBackups.getFilenameForDate();
|
||||
fp.displayDirectory = backupsDir;
|
||||
fp.open(fpCallback);
|
||||
|
|
|
@ -153,18 +153,14 @@ These should match what Safari and other Apple applications use on OS X Lion. --
|
|||
<!ENTITY bookmarksToolbarChevron.tooltip "Show more bookmarks">
|
||||
|
||||
<!ENTITY backCmd.label "Back">
|
||||
<!ENTITY backCmd.accesskey "B">
|
||||
<!ENTITY backButton.tooltip "Go back one page">
|
||||
<!ENTITY forwardCmd.label "Forward">
|
||||
<!ENTITY forwardCmd.accesskey "F">
|
||||
<!ENTITY forwardButton.tooltip "Go forward one page">
|
||||
<!ENTITY backForwardButtonMenu.tooltip "Right-click or pull down to show history">
|
||||
<!ENTITY backForwardButtonMenuMac.tooltip "Pull down to show history">
|
||||
<!ENTITY reloadCmd.label "Reload">
|
||||
<!ENTITY reloadCmd.accesskey "R">
|
||||
<!ENTITY reloadButton.tooltip "Reload current page">
|
||||
<!ENTITY stopCmd.label "Stop">
|
||||
<!ENTITY stopCmd.accesskey "S">
|
||||
<!ENTITY stopCmd.macCommandKey ".">
|
||||
<!ENTITY stopButton.tooltip "Stop loading this page">
|
||||
<!ENTITY goEndCap.tooltip "Go to the address in the Location Bar">
|
||||
|
@ -443,7 +439,6 @@ These should match what Safari and other Apple applications use on OS X Lion. --
|
|||
<!ENTITY setDesktopBackgroundCmd.label "Set As Desktop Background…">
|
||||
<!ENTITY setDesktopBackgroundCmd.accesskey "S">
|
||||
<!ENTITY bookmarkPageCmd2.label "Bookmark This Page">
|
||||
<!ENTITY bookmarkPageCmd2.accesskey "m">
|
||||
<!ENTITY bookmarkThisLinkCmd.label "Bookmark This Link">
|
||||
<!ENTITY bookmarkThisLinkCmd.accesskey "L">
|
||||
<!ENTITY bookmarkThisFrameCmd.label "Bookmark This Frame">
|
||||
|
|
|
@ -13,7 +13,6 @@ bookmarksRestoreAlertTitle=Revert Bookmarks
|
|||
bookmarksRestoreAlert=This will replace all of your current bookmarks with the backup. Are you sure?
|
||||
bookmarksRestoreTitle=Select a bookmarks backup
|
||||
bookmarksRestoreFilterName=JSON
|
||||
bookmarksRestoreFilterExtension=*.json
|
||||
|
||||
bookmarksRestoreFormatError=Unsupported file type.
|
||||
bookmarksRestoreParseError=Unable to process the backup file.
|
||||
|
|
|
@ -437,24 +437,11 @@ menuitem:not([type]):not(.menuitem-tooltip):not(.menuitem-iconic-tooltip) {
|
|||
list-style-image: url("moz-icon://stock/gtk-preferences?size=menu");
|
||||
}
|
||||
|
||||
#context-stop {
|
||||
list-style-image: url("moz-icon://stock/gtk-stop?size=menu");
|
||||
}
|
||||
|
||||
#context-stop[disabled] {
|
||||
list-style-image: url("moz-icon://stock/gtk-stop?size=menu&state=disabled");
|
||||
}
|
||||
|
||||
#placesContext_reload,
|
||||
#context-reload,
|
||||
#context-reloadframe {
|
||||
list-style-image: url("moz-icon://stock/gtk-refresh?size=menu");
|
||||
}
|
||||
|
||||
#context-reload[disabled] {
|
||||
list-style-image: url("moz-icon://stock/gtk-refresh?size=menu&state=disabled");
|
||||
}
|
||||
|
||||
#menu_zoomEnlarge {
|
||||
list-style-image: url("moz-icon://stock/gtk-zoom-in?size=menu");
|
||||
}
|
||||
|
@ -467,38 +454,6 @@ menuitem:not([type]):not(.menuitem-tooltip):not(.menuitem-iconic-tooltip) {
|
|||
list-style-image: url("moz-icon://stock/gtk-zoom-100?size=menu");
|
||||
}
|
||||
|
||||
#context-back {
|
||||
list-style-image: url("moz-icon://stock/gtk-go-back-ltr?size=menu");
|
||||
}
|
||||
|
||||
#context-back[disabled] {
|
||||
list-style-image: url("moz-icon://stock/gtk-go-back-ltr?size=menu&state=disabled");
|
||||
}
|
||||
|
||||
#context-back:-moz-locale-dir(rtl) {
|
||||
list-style-image: url("moz-icon://stock/gtk-go-back-rtl?size=menu");
|
||||
}
|
||||
|
||||
#context-back[disabled]:-moz-locale-dir(rtl) {
|
||||
list-style-image: url("moz-icon://stock/gtk-go-back-rtl?size=menu&state=disabled");
|
||||
}
|
||||
|
||||
#context-forward {
|
||||
list-style-image: url("moz-icon://stock/gtk-go-forward-ltr?size=menu");
|
||||
}
|
||||
|
||||
#context-forward[disabled] {
|
||||
list-style-image: url("moz-icon://stock/gtk-go-forward-ltr?size=menu&state=disabled");
|
||||
}
|
||||
|
||||
#context-forward:-moz-locale-dir(rtl) {
|
||||
list-style-image: url("moz-icon://stock/gtk-go-forward-rtl?size=menu");
|
||||
}
|
||||
|
||||
#context-forward[disabled]:-moz-locale-dir(rtl) {
|
||||
list-style-image: url("moz-icon://stock/gtk-go-forward-rtl?size=menu&state=disabled");
|
||||
}
|
||||
|
||||
#menu_showAllHistory {
|
||||
list-style-image: url("chrome://browser/skin/Toolbar-small.png");
|
||||
-moz-image-region: rect(0px 32px 16px 16px);
|
||||
|
@ -2289,3 +2244,23 @@ chatbox {
|
|||
#UITourTooltipButtons {
|
||||
margin-bottom: -10px;
|
||||
}
|
||||
|
||||
%include ../shared/contextmenu.inc.css
|
||||
|
||||
#context-navigation {
|
||||
background-color: -moz-dialog;
|
||||
padding-bottom: 2px;
|
||||
margin-bottom: 2px;
|
||||
-moz-appearance: menuitem;
|
||||
}
|
||||
|
||||
#context-navigation > .menuitem-iconic > .menu-iconic-left {
|
||||
visibility: visible;
|
||||
/* override toolkit/themes/linux/global/menu.css */
|
||||
-moz-padding-end: 0 !important;
|
||||
-moz-margin-end: 0 !important;
|
||||
}
|
||||
|
||||
#context-sep-navigation {
|
||||
margin-top: -4px;
|
||||
}
|
||||
|
|
|
@ -47,6 +47,11 @@ spinbuttons {
|
|||
-moz-appearance: none;
|
||||
}
|
||||
|
||||
.treecol-sortdirection {
|
||||
/* override the Linux only toolkit rule */
|
||||
-moz-appearance: none;
|
||||
}
|
||||
|
||||
.actionsMenu {
|
||||
font-family: "Clear Sans", sans-serif;
|
||||
font-size: 1.25rem;
|
||||
|
|
|
@ -4430,3 +4430,10 @@ window > chatbox {
|
|||
width: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
%include ../shared/contextmenu.inc.css
|
||||
|
||||
#context-navigation > .menuitem-iconic {
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
|
||||
menugroup > .menuitem-iconic[disabled="true"] > .menu-iconic-left {
|
||||
opacity: .3;
|
||||
}
|
||||
|
||||
#context-navigation > .menuitem-iconic {
|
||||
-moz-box-flex: 1;
|
||||
-moz-box-pack: center;
|
||||
-moz-box-align: center;
|
||||
}
|
||||
|
||||
#context-navigation > .menuitem-iconic > .menu-iconic-left {
|
||||
-moz-appearance: none;
|
||||
}
|
||||
|
||||
#context-navigation > #context-back > .menu-iconic-left {
|
||||
list-style-image: url("chrome://browser/skin/Toolbar.png");
|
||||
-moz-image-region: rect(0, 36px, 18px, 18px);
|
||||
}
|
||||
|
||||
#context-navigation > #context-forward > .menu-iconic-left {
|
||||
list-style-image: url("chrome://browser/skin/Toolbar.png");
|
||||
-moz-image-region: rect(0, 72px, 18px, 54px);
|
||||
}
|
||||
|
||||
#context-navigation > #context-reload > .menu-iconic-left {
|
||||
list-style-image: url("chrome://browser/skin/reload-stop-go.png");
|
||||
-moz-image-region: rect(0, 14px, 14px, 0);
|
||||
}
|
||||
|
||||
#context-navigation > #context-stop > .menu-iconic-left {
|
||||
list-style-image: url("chrome://browser/skin/reload-stop-go.png");
|
||||
-moz-image-region: rect(0, 28px, 14px, 14px);
|
||||
}
|
||||
|
||||
#context-navigation > #context-bookmarkpage > .menu-iconic-left {
|
||||
list-style-image: url("chrome://browser/skin/Toolbar.png");
|
||||
-moz-image-region: rect(0, 144px, 18px, 126px);
|
||||
}
|
||||
|
||||
#context-back:-moz-locale-dir(rtl),
|
||||
#context-forward:-moz-locale-dir(rtl),
|
||||
#context-reload:-moz-locale-dir(rtl) {
|
||||
transform: scaleX(-1);
|
||||
}
|
||||
|
||||
#context-navigation > .menuitem-iconic > .menu-iconic-left > .menu-iconic-icon {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
margin: 7px;
|
||||
}
|
|
@ -2935,3 +2935,16 @@ chatbox {
|
|||
#UITourTooltipButtons {
|
||||
margin: 24px -4px -4px;
|
||||
}
|
||||
|
||||
%include ../shared/contextmenu.inc.css
|
||||
|
||||
#context-navigation {
|
||||
background-color: -moz-dialog;
|
||||
padding-bottom: 2px;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
#context-sep-navigation {
|
||||
-moz-margin-start: -28px;
|
||||
margin-top: -4px;
|
||||
}
|
||||
|
|
|
@ -1013,6 +1013,11 @@ nsGenericDOMDataNode::TextIsOnlyWhitespace()
|
|||
bool
|
||||
nsGenericDOMDataNode::HasTextForTranslation()
|
||||
{
|
||||
if (NodeType() != nsIDOMNode::TEXT_NODE &&
|
||||
NodeType() != nsIDOMNode::CDATA_SECTION_NODE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mText.Is2b()) {
|
||||
// The fragment contains non-8bit characters which means there
|
||||
// was at least one "interesting" character to trigger non-8bit.
|
||||
|
|
|
@ -565,6 +565,7 @@ GK_ATOM(menu, "menu")
|
|||
GK_ATOM(menubar, "menubar")
|
||||
GK_ATOM(menubutton, "menubutton")
|
||||
GK_ATOM(menuButton, "menu-button")
|
||||
GK_ATOM(menugroup, "menugroup")
|
||||
GK_ATOM(menuitem, "menuitem")
|
||||
GK_ATOM(menulist, "menulist")
|
||||
GK_ATOM(menupopup, "menupopup")
|
||||
|
|
|
@ -206,5 +206,22 @@
|
|||
expected="p[root] a b span em">
|
||||
<p>Lorem <a>ipsum <b>dolor <span>sit</span> amet</b></a>, <em>consetetur</em></p>
|
||||
</div>
|
||||
|
||||
<!-- Test that comment nodes are not considered for translation -->
|
||||
<div id="testcase16"
|
||||
expected="p[root] p[root]">
|
||||
<p>Lorem ipsum</p>
|
||||
<div> <!-- Comment --> </div>
|
||||
<p>Lorem ipsum</p>
|
||||
</div>
|
||||
|
||||
<!-- Test that comment nodes are not considered for translation -->
|
||||
<div id="testcase17"
|
||||
expected="p[root]">
|
||||
<div>
|
||||
<!-- Comment -->
|
||||
<p>Lorem Ipsum</p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -37,10 +37,6 @@ html|input.ac {
|
|||
padding: 0 4px !important;
|
||||
}
|
||||
|
||||
#mac html|input.ac {
|
||||
padding: 0 3px !important;
|
||||
}
|
||||
|
||||
html|input.empty {
|
||||
color: graytext;
|
||||
}
|
||||
|
|
|
@ -986,11 +986,11 @@ nsMenuFrame::UpdateMenuSpecialState(nsPresContext* aPresContext)
|
|||
// get the first sibling in this menu popup. This frame may be it, and if we're
|
||||
// being called at creation time, this frame isn't yet in the parent's child list.
|
||||
// All I'm saying is that this may fail, but it's most likely alright.
|
||||
nsIFrame* sib = GetParent()->GetFirstPrincipalChild();
|
||||
|
||||
nsIFrame* firstMenuItem = nsXULPopupManager::GetNextMenuItem(GetParent(), nullptr, true);
|
||||
nsIFrame* sib = firstMenuItem;
|
||||
while (sib) {
|
||||
nsMenuFrame* menu = do_QueryFrame(sib);
|
||||
if (sib != this) {
|
||||
nsMenuFrame* menu = do_QueryFrame(sib);
|
||||
if (menu && menu->GetMenuType() == eMenuType_Radio &&
|
||||
menu->IsChecked() && menu->GetRadioGroupName() == mGroupName) {
|
||||
/* uncheck the old item */
|
||||
|
@ -1000,8 +1000,10 @@ nsMenuFrame::UpdateMenuSpecialState(nsPresContext* aPresContext)
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
sib = sib->GetNextSibling();
|
||||
sib = nsXULPopupManager::GetNextMenuItem(GetParent(), menu, true);
|
||||
if (sib == firstMenuItem) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1682,13 +1682,13 @@ nsMenuPopupFrame::FindMenuWithShortcut(nsIDOMKeyEvent* aKeyEvent, bool& doAction
|
|||
|
||||
lastKeyTime = keyTime;
|
||||
|
||||
nsIFrame* currFrame;
|
||||
// NOTE: If you crashed here due to a bogus |immediateParent| it is
|
||||
// possible that the menu whose shortcut is being looked up has
|
||||
// been destroyed already. One strategy would be to
|
||||
// setTimeout(<func>,0) as detailed in:
|
||||
// <http://bugzilla.mozilla.org/show_bug.cgi?id=126675#c32>
|
||||
currFrame = immediateParent->GetFirstPrincipalChild();
|
||||
nsIFrame* firstMenuItem = nsXULPopupManager::GetNextMenuItem(immediateParent, nullptr, true);
|
||||
nsIFrame* currFrame = firstMenuItem;
|
||||
|
||||
int32_t menuAccessKey = -1;
|
||||
nsMenuBarListener::GetMenuAccessKey(&menuAccessKey);
|
||||
|
@ -1697,64 +1697,64 @@ nsMenuPopupFrame::FindMenuWithShortcut(nsIDOMKeyEvent* aKeyEvent, bool& doAction
|
|||
// -- before current and after current -- by the current item
|
||||
while (currFrame) {
|
||||
nsIContent* current = currFrame->GetContent();
|
||||
|
||||
// See if it's a menu item.
|
||||
if (nsXULPopupManager::IsValidMenuItem(PresContext(), current, true)) {
|
||||
nsAutoString textKey;
|
||||
if (menuAccessKey >= 0) {
|
||||
// Get the shortcut attribute.
|
||||
current->GetAttr(kNameSpaceID_None, nsGkAtoms::accesskey, textKey);
|
||||
}
|
||||
if (textKey.IsEmpty()) { // No shortcut, try first letter
|
||||
isShortcut = false;
|
||||
current->GetAttr(kNameSpaceID_None, nsGkAtoms::label, textKey);
|
||||
if (textKey.IsEmpty()) // No label, try another attribute (value)
|
||||
current->GetAttr(kNameSpaceID_None, nsGkAtoms::value, textKey);
|
||||
nsAutoString textKey;
|
||||
if (menuAccessKey >= 0) {
|
||||
// Get the shortcut attribute.
|
||||
current->GetAttr(kNameSpaceID_None, nsGkAtoms::accesskey, textKey);
|
||||
}
|
||||
if (textKey.IsEmpty()) { // No shortcut, try first letter
|
||||
isShortcut = false;
|
||||
current->GetAttr(kNameSpaceID_None, nsGkAtoms::label, textKey);
|
||||
if (textKey.IsEmpty()) // No label, try another attribute (value)
|
||||
current->GetAttr(kNameSpaceID_None, nsGkAtoms::value, textKey);
|
||||
}
|
||||
else
|
||||
isShortcut = true;
|
||||
|
||||
if (StringBeginsWith(textKey, incrementalString,
|
||||
nsCaseInsensitiveStringComparator())) {
|
||||
// mIncrementalString is a prefix of textKey
|
||||
nsMenuFrame* menu = do_QueryFrame(currFrame);
|
||||
if (menu) {
|
||||
// There is one match
|
||||
matchCount++;
|
||||
if (isShortcut) {
|
||||
// There is one shortcut-key match
|
||||
matchShortcutCount++;
|
||||
// Record the matched item. If there is only one matched shortcut item, do it
|
||||
frameShortcut = menu;
|
||||
}
|
||||
if (!foundActive) {
|
||||
// It's a first candidate item located before/on the current item
|
||||
if (!frameBefore)
|
||||
frameBefore = menu;
|
||||
}
|
||||
else {
|
||||
// It's a first candidate item located after the current item
|
||||
if (!frameAfter)
|
||||
frameAfter = menu;
|
||||
}
|
||||
}
|
||||
else
|
||||
isShortcut = true;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (StringBeginsWith(textKey, incrementalString,
|
||||
nsCaseInsensitiveStringComparator())) {
|
||||
// mIncrementalString is a prefix of textKey
|
||||
nsMenuFrame* menu = do_QueryFrame(currFrame);
|
||||
if (menu) {
|
||||
// There is one match
|
||||
matchCount++;
|
||||
if (isShortcut) {
|
||||
// There is one shortcut-key match
|
||||
matchShortcutCount++;
|
||||
// Record the matched item. If there is only one matched shortcut item, do it
|
||||
frameShortcut = menu;
|
||||
}
|
||||
if (!foundActive) {
|
||||
// It's a first candidate item located before/on the current item
|
||||
if (!frameBefore)
|
||||
frameBefore = menu;
|
||||
}
|
||||
else {
|
||||
// It's a first candidate item located after the current item
|
||||
if (!frameAfter)
|
||||
frameAfter = menu;
|
||||
}
|
||||
}
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Get the active status
|
||||
if (current->AttrValueIs(kNameSpaceID_None, nsGkAtoms::menuactive,
|
||||
nsGkAtoms::_true, eCaseMatters)) {
|
||||
foundActive = true;
|
||||
if (stringLength > 1) {
|
||||
// If there is more than one char typed, the current item has highest priority,
|
||||
// otherwise the item next to current has highest priority
|
||||
if (currFrame == frameBefore)
|
||||
return frameBefore;
|
||||
}
|
||||
// Get the active status
|
||||
if (current->AttrValueIs(kNameSpaceID_None, nsGkAtoms::menuactive,
|
||||
nsGkAtoms::_true, eCaseMatters)) {
|
||||
foundActive = true;
|
||||
if (stringLength > 1) {
|
||||
// If there is more than one char typed, the current item has highest priority,
|
||||
// otherwise the item next to current has highest priority
|
||||
if (currFrame == frameBefore)
|
||||
return frameBefore;
|
||||
}
|
||||
}
|
||||
currFrame = currFrame->GetNextSibling();
|
||||
|
||||
nsMenuFrame* menu = do_QueryFrame(currFrame);
|
||||
currFrame = nsXULPopupManager::GetNextMenuItem(immediateParent, menu, true);
|
||||
if (currFrame == firstMenuItem)
|
||||
break;
|
||||
}
|
||||
|
||||
doAction = (isMenu && (matchCount == 1 || matchShortcutCount == 1));
|
||||
|
|
|
@ -1761,7 +1761,10 @@ nsXULPopupManager::UpdateMenuItems(nsIContent* aPopup)
|
|||
for (nsCOMPtr<nsIContent> grandChild = aPopup->GetFirstChild();
|
||||
grandChild;
|
||||
grandChild = grandChild->GetNextSibling()) {
|
||||
if (grandChild->NodeInfo()->Equals(nsGkAtoms::menuitem, kNameSpaceID_XUL)) {
|
||||
if (grandChild->IsXUL(nsGkAtoms::menugroup)) {
|
||||
grandChild = grandChild->GetFirstChild();
|
||||
}
|
||||
if (grandChild->IsXUL(nsGkAtoms::menuitem)) {
|
||||
// See if we have a command attribute.
|
||||
nsAutoString command;
|
||||
grandChild->GetAttr(kNameSpaceID_None, nsGkAtoms::command, command);
|
||||
|
@ -1794,6 +1797,10 @@ nsXULPopupManager::UpdateMenuItems(nsIContent* aPopup)
|
|||
}
|
||||
}
|
||||
}
|
||||
if (!grandChild->GetNextSibling() &&
|
||||
grandChild->GetParent()->IsXUL(nsGkAtoms::menugroup)) {
|
||||
grandChild = grandChild->GetParent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2155,17 +2162,28 @@ nsXULPopupManager::GetNextMenuItem(nsContainerFrame* aParent,
|
|||
immediateParent = aParent;
|
||||
|
||||
nsIFrame* currFrame = nullptr;
|
||||
if (aStart)
|
||||
currFrame = aStart->GetNextSibling();
|
||||
else
|
||||
if (aStart) {
|
||||
if (aStart->GetNextSibling())
|
||||
currFrame = aStart->GetNextSibling();
|
||||
else if (aStart->GetParent()->GetContent()->IsXUL(nsGkAtoms::menugroup))
|
||||
currFrame = aStart->GetParent()->GetNextSibling();
|
||||
}
|
||||
else
|
||||
currFrame = immediateParent->GetFirstPrincipalChild();
|
||||
|
||||
|
||||
while (currFrame) {
|
||||
// See if it's a menu item.
|
||||
if (IsValidMenuItem(presContext, currFrame->GetContent(), aIsPopup)) {
|
||||
nsIContent* currFrameContent = currFrame->GetContent();
|
||||
if (IsValidMenuItem(presContext, currFrameContent, aIsPopup)) {
|
||||
return do_QueryFrame(currFrame);
|
||||
}
|
||||
currFrame = currFrame->GetNextSibling();
|
||||
if (currFrameContent->IsXUL(nsGkAtoms::menugroup))
|
||||
currFrame = currFrame->GetFirstPrincipalChild();
|
||||
else if (!currFrame->GetNextSibling() &&
|
||||
currFrame->GetParent()->GetContent()->IsXUL(nsGkAtoms::menugroup))
|
||||
currFrame = currFrame->GetParent()->GetNextSibling();
|
||||
else
|
||||
currFrame = currFrame->GetNextSibling();
|
||||
}
|
||||
|
||||
currFrame = immediateParent->GetFirstPrincipalChild();
|
||||
|
@ -2173,11 +2191,17 @@ nsXULPopupManager::GetNextMenuItem(nsContainerFrame* aParent,
|
|||
// Still don't have anything. Try cycling from the beginning.
|
||||
while (currFrame && currFrame != aStart) {
|
||||
// See if it's a menu item.
|
||||
if (IsValidMenuItem(presContext, currFrame->GetContent(), aIsPopup)) {
|
||||
nsIContent* currFrameContent = currFrame->GetContent();
|
||||
if (IsValidMenuItem(presContext, currFrameContent, aIsPopup)) {
|
||||
return do_QueryFrame(currFrame);
|
||||
}
|
||||
|
||||
currFrame = currFrame->GetNextSibling();
|
||||
if (currFrameContent->IsXUL(nsGkAtoms::menugroup))
|
||||
currFrame = currFrame->GetFirstPrincipalChild();
|
||||
else if (!currFrame->GetNextSibling() &&
|
||||
currFrame->GetParent()->GetContent()->IsXUL(nsGkAtoms::menugroup))
|
||||
currFrame = currFrame->GetParent()->GetNextSibling();
|
||||
else
|
||||
currFrame = currFrame->GetNextSibling();
|
||||
}
|
||||
|
||||
// No luck. Just return our start value.
|
||||
|
@ -2198,17 +2222,30 @@ nsXULPopupManager::GetPreviousMenuItem(nsContainerFrame* aParent,
|
|||
const nsFrameList& frames(immediateParent->PrincipalChildList());
|
||||
|
||||
nsIFrame* currFrame = nullptr;
|
||||
if (aStart)
|
||||
currFrame = aStart->GetPrevSibling();
|
||||
if (aStart) {
|
||||
if (aStart->GetPrevSibling())
|
||||
currFrame = aStart->GetPrevSibling();
|
||||
else if (aStart->GetParent()->GetContent()->IsXUL(nsGkAtoms::menugroup))
|
||||
currFrame = aStart->GetParent()->GetPrevSibling();
|
||||
}
|
||||
else
|
||||
currFrame = frames.LastChild();
|
||||
|
||||
while (currFrame) {
|
||||
// See if it's a menu item.
|
||||
if (IsValidMenuItem(presContext, currFrame->GetContent(), aIsPopup)) {
|
||||
nsIContent* currFrameContent = currFrame->GetContent();
|
||||
if (IsValidMenuItem(presContext, currFrameContent, aIsPopup)) {
|
||||
return do_QueryFrame(currFrame);
|
||||
}
|
||||
currFrame = currFrame->GetPrevSibling();
|
||||
if (currFrameContent->IsXUL(nsGkAtoms::menugroup)) {
|
||||
const nsFrameList& menugroupFrames(currFrame->PrincipalChildList());
|
||||
currFrame = menugroupFrames.LastChild();
|
||||
}
|
||||
else if (!currFrame->GetPrevSibling() &&
|
||||
currFrame->GetParent()->GetContent()->IsXUL(nsGkAtoms::menugroup))
|
||||
currFrame = currFrame->GetParent()->GetPrevSibling();
|
||||
else
|
||||
currFrame = currFrame->GetPrevSibling();
|
||||
}
|
||||
|
||||
currFrame = frames.LastChild();
|
||||
|
@ -2216,11 +2253,19 @@ nsXULPopupManager::GetPreviousMenuItem(nsContainerFrame* aParent,
|
|||
// Still don't have anything. Try cycling from the end.
|
||||
while (currFrame && currFrame != aStart) {
|
||||
// See if it's a menu item.
|
||||
if (IsValidMenuItem(presContext, currFrame->GetContent(), aIsPopup)) {
|
||||
nsIContent* currFrameContent = currFrame->GetContent();
|
||||
if (IsValidMenuItem(presContext, currFrameContent, aIsPopup)) {
|
||||
return do_QueryFrame(currFrame);
|
||||
}
|
||||
|
||||
currFrame = currFrame->GetPrevSibling();
|
||||
if (currFrameContent->IsXUL(nsGkAtoms::menugroup)) {
|
||||
const nsFrameList& menugroupFrames(currFrame->PrincipalChildList());
|
||||
currFrame = menugroupFrames.LastChild();
|
||||
}
|
||||
else if (!currFrame->GetPrevSibling() &&
|
||||
currFrame->GetParent()->GetContent()->IsXUL(nsGkAtoms::menugroup))
|
||||
currFrame = currFrame->GetParent()->GetPrevSibling();
|
||||
else
|
||||
currFrame = currFrame->GetPrevSibling();
|
||||
}
|
||||
|
||||
// No luck. Just return our start value.
|
||||
|
|
|
@ -25,6 +25,9 @@ public interface TelemetryContract {
|
|||
// Cancel a state, action, etc.
|
||||
public static final String CANCEL = "cancel.1";
|
||||
|
||||
// Editing an item.
|
||||
public static final String EDIT = "edit.1";
|
||||
|
||||
// Launching (opening) an external application.
|
||||
// Note: Only used in JavaScript for now, but here for completeness.
|
||||
public static final String LAUNCH = "launch.1";
|
||||
|
@ -39,6 +42,9 @@ public interface TelemetryContract {
|
|||
// Set default panel.
|
||||
public static final String PANEL_SET_DEFAULT = "setdefault.1";
|
||||
|
||||
// Pinning an item.
|
||||
public static final String PIN = "pin.1";
|
||||
|
||||
// Outcome of data policy notification: can be true or false.
|
||||
public static final String POLICY_NOTIFICATION_SUCCESS = "policynotification.success.1:";
|
||||
|
||||
|
@ -52,14 +58,8 @@ public interface TelemetryContract {
|
|||
// Sharing content.
|
||||
public static final String SHARE = "share.1";
|
||||
|
||||
// Top site edited.
|
||||
public static final String TOP_SITES_EDIT = "edit.1";
|
||||
|
||||
// Top site pinned.
|
||||
public static final String TOP_SITES_PIN = "pin.1";
|
||||
|
||||
// Top site un-pinned.
|
||||
public static final String TOP_SITES_UNPIN = "unpin.1";
|
||||
// Unpinning an item.
|
||||
public static final String UNPIN = "unpin.1";
|
||||
|
||||
// Stop holding a resource (reader, bookmark, etc) for viewing later.
|
||||
// Note: Only used in JavaScript for now, but here for completeness.
|
||||
|
@ -69,11 +69,10 @@ public interface TelemetryContract {
|
|||
/**
|
||||
* Holds event methods. Intended for use in
|
||||
* Telemetry.sendUIEvent() as the "method" parameter.
|
||||
*
|
||||
* Please keep this list sorted.
|
||||
*/
|
||||
public interface Method {
|
||||
// Action triggered from a list.
|
||||
public static final String LIST = "list";
|
||||
|
||||
// Action triggered from the action bar (including the toolbar).
|
||||
public static final String ACTIONBAR = "actionbar";
|
||||
|
||||
|
@ -83,40 +82,51 @@ public interface TelemetryContract {
|
|||
// Action triggered from a button.
|
||||
public static final String BUTTON = "button";
|
||||
|
||||
// Action triggered from a dialog.
|
||||
public static final String DIALOG = "dialog";
|
||||
|
||||
// Action occurred via an intent.
|
||||
public static final String INTENT = "intent";
|
||||
|
||||
// Action occurred via the main menu.
|
||||
public static final String MENU = "menu";
|
||||
|
||||
// Action occurred via a context menu.
|
||||
public static final String CONTEXT_MENU = "contextmenu";
|
||||
|
||||
// Action triggered from a dialog.
|
||||
public static final String DIALOG = "dialog";
|
||||
|
||||
// Action triggered from a view grid item, like a thumbnail.
|
||||
public static final String GRID_ITEM = "griditem";
|
||||
|
||||
// Action occurred via an intent.
|
||||
public static final String INTENT = "intent";
|
||||
|
||||
// Action triggered from a list.
|
||||
public static final String LIST = "list";
|
||||
|
||||
// Action triggered from a view list item, like a row of a list.
|
||||
public static final String LIST_ITEM = "listitem";
|
||||
|
||||
// Action triggered from a suggestion provided to the user.
|
||||
public static final String SUGGESTION = "suggestion";
|
||||
// Action occurred via the main menu.
|
||||
public static final String MENU = "menu";
|
||||
|
||||
// Action triggered from a pageaction in the URLBar.
|
||||
// Note: Only used in JavaScript for now, but here for completeness.
|
||||
public static final String PAGEACTION = "pageaction";
|
||||
|
||||
// Action triggered from a suggestion provided to the user.
|
||||
public static final String SUGGESTION = "suggestion";
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds session names. Intended for use with
|
||||
* Telemetry.startUISession() as the "sessionName" parameter.
|
||||
*
|
||||
* Please keep this list sorted.
|
||||
*/
|
||||
public interface Session {
|
||||
// Awesomescreen (including frecency search) is active.
|
||||
public static final String AWESOMESCREEN = "awesomescreen.1";
|
||||
|
||||
// Started the very first time we believe the application has been launched.
|
||||
public static final String FIRSTRUN = "firstrun.1";
|
||||
|
||||
// Awesomescreen frecency search is active.
|
||||
public static final String FRECENCY = "frecency.1";
|
||||
|
||||
// Started when a user enters about:home.
|
||||
public static final String HOME = "home.1";
|
||||
|
||||
|
@ -127,17 +137,13 @@ public interface TelemetryContract {
|
|||
// Started when a Reader viewer becomes active in the foreground.
|
||||
// Note: Only used in JavaScript for now, but here for completeness.
|
||||
public static final String READER = "reader.1";
|
||||
|
||||
// Awesomescreen frecency search is active.
|
||||
public static final String FRECENCY = "frecency.1";
|
||||
|
||||
// Started the very first time we believe the application has been launched.
|
||||
public static final String FIRSTRUN = "firstrun.1";
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds reasons for stopping a session. Intended for use in
|
||||
* Telemetry.stopUISession() as the "reason" parameter.
|
||||
*
|
||||
* Please keep this list sorted.
|
||||
*/
|
||||
public interface Reason {
|
||||
// Changes were committed.
|
||||
|
|
|
@ -328,7 +328,7 @@ public class TopSitesPanel extends HomeFragment {
|
|||
}
|
||||
});
|
||||
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.TOP_SITES_PIN);
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.PIN);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -343,7 +343,7 @@ public class TopSitesPanel extends HomeFragment {
|
|||
}
|
||||
});
|
||||
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.TOP_SITES_UNPIN);
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.UNPIN);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -352,7 +352,7 @@ public class TopSitesPanel extends HomeFragment {
|
|||
// Decode "user-entered" URLs before showing them.
|
||||
mEditPinnedSiteListener.onEditPinnedSite(info.position, decodeUserEnteredUrl(info.url));
|
||||
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.TOP_SITES_EDIT);
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.EDIT);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -36,9 +36,7 @@ skip-if = android_version == "10" || processor == "x86"
|
|||
# disabled on 2.3; bug 986172
|
||||
skip-if = android_version == "10"
|
||||
[testFilterOpenTab]
|
||||
[testFindInPage]
|
||||
# disabled on Android 2.3; bug 975155
|
||||
skip-if = android_version == "10"
|
||||
# [testFindInPage] # see bug 975155, bug 1014708
|
||||
[testFlingCorrectness]
|
||||
# disabled on x86 only; bug 927476
|
||||
skip-if = processor == "x86"
|
||||
|
|
|
@ -15,11 +15,9 @@ public class testFindInPage extends PixelTest {
|
|||
String url = getAbsoluteUrl("/robocop/robocop_text_page.html");
|
||||
loadAndPaint(url);
|
||||
|
||||
// Select the upper left corner of the screen
|
||||
height = mDriver.getGeckoHeight()/8;
|
||||
width = mDriver.getGeckoWidth()/8;
|
||||
width = mDriver.getGeckoWidth()/2;
|
||||
|
||||
/* Disabled by bug 958111.
|
||||
// Search that does not find the term and therefor should not pan the page
|
||||
Actions.RepeatedEventExpecter paintExpecter = mActions.expectPaint();
|
||||
findText("Robocoop", 3); // This will be close enough to existing text to test that search finds just what it should
|
||||
|
@ -30,12 +28,11 @@ public class testFindInPage extends PixelTest {
|
|||
} finally {
|
||||
painted.close();
|
||||
}
|
||||
*/
|
||||
|
||||
// Search that finds matches and therefor pans the page
|
||||
Actions.RepeatedEventExpecter paintExpecter = mActions.expectPaint();
|
||||
paintExpecter = mActions.expectPaint();
|
||||
findText("Robocop", 3);
|
||||
PaintedSurface painted = waitForPaint(paintExpecter);
|
||||
painted = waitForPaint(paintExpecter);
|
||||
paintExpecter.unregisterListener();
|
||||
try {
|
||||
mAsserter.isnotpixel(painted.getPixelAt(width,height), 255, 0, 0, "Pixel at " + String.valueOf(width) + "," + String.valueOf(height));
|
||||
|
|
|
@ -77,7 +77,8 @@ var FindHelper = {
|
|||
this._targetTab.sendViewportUpdate();
|
||||
}
|
||||
} else {
|
||||
ZoomHelper.zoomToRect(aData.rect, -1, false, true);
|
||||
// Disabled until bug 1014113 is fixed
|
||||
//ZoomHelper.zoomToRect(aData.rect, -1, false, true);
|
||||
this._viewportChanged = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -247,6 +247,9 @@ var Addons = {
|
|||
let list = document.getElementById("addons-list");
|
||||
list.innerHTML = "";
|
||||
|
||||
aAddons.sort(function(a,b) {
|
||||
return a.name.localeCompare(b.name);
|
||||
});
|
||||
for (let i=0; i<aAddons.length; i++) {
|
||||
let item = self._createItemForAddon(aAddons[i]);
|
||||
list.appendChild(item);
|
||||
|
|
|
@ -3883,9 +3883,12 @@ Tab.prototype = {
|
|||
|
||||
// Once document is fully loaded, parse it
|
||||
Reader.parseDocumentFromTab(this.id, function (article) {
|
||||
// The loaded page may have changed while we were parsing the document.
|
||||
// Make sure we've got the current one.
|
||||
let uri = this.browser.currentURI;
|
||||
let tabURL = uri.specIgnoringRef;
|
||||
// Do nothing if there's no article or the page in this tab has
|
||||
// changed
|
||||
let tabURL = uri.specIgnoringRef;
|
||||
if (article == null || (article.url != tabURL)) {
|
||||
// Don't clear the article for about:reader pages since we want to
|
||||
// use the article from the previous page
|
||||
|
|
|
@ -77,7 +77,7 @@ this.BookmarkJSONUtils = Object.freeze({
|
|||
* before executing the restore.
|
||||
*
|
||||
* @param aFilePath
|
||||
* OS.File path string of bookmarks in JSON format to be restored.
|
||||
* OS.File path string of bookmarks in JSON or JSONlz4 format to be restored.
|
||||
* @param aReplace
|
||||
* Boolean if true, replace existing bookmarks, else merge.
|
||||
*
|
||||
|
@ -101,8 +101,11 @@ this.BookmarkJSONUtils = Object.freeze({
|
|||
throw new Error("Cannot restore from nonexisting json file");
|
||||
|
||||
let importer = new BookmarkImporter(aReplace);
|
||||
yield importer.importFromURL(OS.Path.toFileURI(aFilePath));
|
||||
|
||||
if (aFilePath.endsWith("jsonlz4")) {
|
||||
yield importer.importFromCompressedFile(aFilePath);
|
||||
} else {
|
||||
yield importer.importFromURL(OS.Path.toFileURI(aFilePath));
|
||||
}
|
||||
notifyObservers(PlacesUtils.TOPIC_BOOKMARKS_RESTORE_SUCCESS);
|
||||
} catch(ex) {
|
||||
Cu.reportError("Failed to restore bookmarks from " + aFilePath + ": " + ex);
|
||||
|
@ -116,11 +119,12 @@ this.BookmarkJSONUtils = Object.freeze({
|
|||
* Serializes bookmarks using JSON, and writes to the supplied file path.
|
||||
*
|
||||
* @param aFilePath
|
||||
* OS.File path string for the "bookmarks.json" file to be created.
|
||||
* OS.File path string for the bookmarks file to be created.
|
||||
* @param [optional] aOptions
|
||||
* Object containing options for the export:
|
||||
* - failIfHashIs: if the generated file would have the same hash
|
||||
* defined here, will reject with ex.becauseSameHash
|
||||
* - compress: if true, writes file using lz4 compression
|
||||
* @return {Promise}
|
||||
* @resolves once the file has been created, to an object with the
|
||||
* following properties:
|
||||
|
@ -169,8 +173,11 @@ this.BookmarkJSONUtils = Object.freeze({
|
|||
// Do not write to the tmp folder, otherwise if it has a different
|
||||
// filesystem writeAtomic will fail. Eventual dangling .tmp files should
|
||||
// be cleaned up by the caller.
|
||||
yield OS.File.writeAtomic(aFilePath, jsonString,
|
||||
{ tmpPath: OS.Path.join(aFilePath + ".tmp") });
|
||||
let writeOptions = { tmpPath: OS.Path.join(aFilePath + ".tmp") };
|
||||
if (aOptions.compress)
|
||||
writeOptions.compression = "lz4";
|
||||
|
||||
yield OS.File.writeAtomic(aFilePath, jsonString, writeOptions);
|
||||
return { count: count, hash: hash };
|
||||
});
|
||||
}
|
||||
|
@ -226,6 +233,25 @@ BookmarkImporter.prototype = {
|
|||
return deferred.promise;
|
||||
},
|
||||
|
||||
/**
|
||||
* Import bookmarks from a compressed file.
|
||||
*
|
||||
* @param aFilePath
|
||||
* OS.File path string of the bookmark data.
|
||||
*
|
||||
* @return {Promise}
|
||||
* @resolves When the new bookmarks have been created.
|
||||
* @rejects JavaScript exception.
|
||||
*/
|
||||
importFromCompressedFile: function* BI_importFromCompressedFile(aFilePath) {
|
||||
let aResult = yield OS.File.read(aFilePath, { compression: "lz4" });
|
||||
let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].
|
||||
createInstance(Ci.nsIScriptableUnicodeConverter);
|
||||
converter.charset = "UTF-8";
|
||||
let jsonString = converter.convertFromByteArray(aResult, aResult.length);
|
||||
yield this.importFromJSON(jsonString);
|
||||
},
|
||||
|
||||
/**
|
||||
* Import bookmarks from a JSON string.
|
||||
*
|
||||
|
|
|
@ -29,7 +29,7 @@ XPCOMUtils.defineLazyGetter(this, "localFileCtor",
|
|||
"nsILocalFile", "initWithPath"));
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "filenamesRegex",
|
||||
() => new RegExp("^bookmarks-([0-9\-]+)(?:_([0-9]+)){0,1}(?:_([a-z0-9=\+\-]{24})){0,1}\.(json|html)", "i")
|
||||
() => new RegExp("^bookmarks-([0-9\-]+)(?:_([0-9]+)){0,1}(?:_([a-z0-9=\+\-]{24})){0,1}\.(json(lz4)?)$", "i")
|
||||
);
|
||||
|
||||
/**
|
||||
|
@ -225,13 +225,17 @@ this.PlacesBackups = {
|
|||
* @param [optional] aDateObj
|
||||
* Date object used to build the filename.
|
||||
* Will use current date if empty.
|
||||
* @param [optional] bool - aCompress
|
||||
* Determines if file extension is json or jsonlz4
|
||||
Default is json
|
||||
* @return A bookmarks backup filename.
|
||||
*/
|
||||
getFilenameForDate: function PB_getFilenameForDate(aDateObj) {
|
||||
getFilenameForDate: function PB_getFilenameForDate(aDateObj, aCompress) {
|
||||
let dateObj = aDateObj || new Date();
|
||||
// Use YYYY-MM-DD (ISO 8601) as it doesn't contain illegal characters
|
||||
// and makes the alphabetical order of multiple backup files more useful.
|
||||
return "bookmarks-" + dateObj.toLocaleFormat("%Y-%m-%d") + ".json";
|
||||
return "bookmarks-" + dateObj.toLocaleFormat("%Y-%m-%d") + ".json" +
|
||||
(aCompress ? "lz4" : "");
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -262,7 +266,7 @@ this.PlacesBackups = {
|
|||
"https://bugzilla.mozilla.org/show_bug.cgi?id=859695");
|
||||
|
||||
for (let i = 0; i < this._entries.length; i++) {
|
||||
let rx = new RegExp("\.json$");
|
||||
let rx = new RegExp("\.json(lz4)?$");
|
||||
if (this._entries[i].leafName.match(rx))
|
||||
return this._entries[i];
|
||||
}
|
||||
|
@ -279,7 +283,7 @@ this.PlacesBackups = {
|
|||
return Task.spawn(function* () {
|
||||
let entries = yield this.getBackupFiles();
|
||||
for (let entry of entries) {
|
||||
let rx = new RegExp("\.json$");
|
||||
let rx = new RegExp("\.json(lz4)?$");
|
||||
if (OS.Path.basename(entry).match(rx)) {
|
||||
return entry;
|
||||
}
|
||||
|
@ -321,13 +325,13 @@ this.PlacesBackups = {
|
|||
this._backupFiles.unshift(aFilePath);
|
||||
} else {
|
||||
// If we are saving to a folder different than our backups folder, then
|
||||
// we also want to copy this new backup to it.
|
||||
// we also want to create a new compressed version in it.
|
||||
// This way we ensure the latest valid backup is the same saved by the
|
||||
// user. See bug 424389.
|
||||
let mostRecentBackupFile = yield this.getMostRecentBackup();
|
||||
if (!mostRecentBackupFile ||
|
||||
hash != getHashFromFilename(OS.Path.basename(mostRecentBackupFile))) {
|
||||
let name = this.getFilenameForDate();
|
||||
let name = this.getFilenameForDate(undefined, true);
|
||||
let newFilename = appendMetaDataToFilename(name,
|
||||
{ count: nodeCount,
|
||||
hash: hash });
|
||||
|
@ -348,8 +352,8 @@ this.PlacesBackups = {
|
|||
yield this.getBackupFiles();
|
||||
this._backupFiles.unshift(newFilePath);
|
||||
}
|
||||
|
||||
yield OS.File.copy(aFilePath, newFilePath);
|
||||
let jsonString = yield OS.File.read(aFilePath);
|
||||
yield OS.File.writeAtomic(newFilePath, jsonString, { compression: "lz4" });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -359,7 +363,7 @@ this.PlacesBackups = {
|
|||
|
||||
/**
|
||||
* Creates a dated backup in <profile>/bookmarkbackups.
|
||||
* Stores the bookmarks using JSON.
|
||||
* Stores the bookmarks using a lz4 compressed JSON file.
|
||||
* Note: any item that should not be backed up must be annotated with
|
||||
* "places/excludeFromBackup".
|
||||
*
|
||||
|
@ -396,7 +400,7 @@ this.PlacesBackups = {
|
|||
// Ensure to initialize _backupFiles
|
||||
if (!this._backupFiles)
|
||||
yield this.getBackupFiles();
|
||||
let newBackupFilename = this.getFilenameForDate();
|
||||
let newBackupFilename = this.getFilenameForDate(undefined, true);
|
||||
// If we already have a backup for today we should do nothing, unless we
|
||||
// were required to enforce a new backup.
|
||||
let backupFile = yield getBackupFileForSameDate(newBackupFilename);
|
||||
|
@ -423,7 +427,8 @@ this.PlacesBackups = {
|
|||
try {
|
||||
let { count: nodeCount, hash: hash } =
|
||||
yield BookmarkJSONUtils.exportToFile(newBackupFile,
|
||||
{ failIfHashIs: mostRecentHash });
|
||||
{ compress: true,
|
||||
failIfHashIs: mostRecentHash });
|
||||
newFilenameWithMetaData = appendMetaDataToFilename(newBackupFilename,
|
||||
{ count: nodeCount,
|
||||
hash: hash });
|
||||
|
|
|
@ -11,13 +11,12 @@ add_task(function check_max_backups_is_respected() {
|
|||
// Get bookmarkBackups directory
|
||||
let backupFolder = yield PlacesBackups.getBackupFolder();
|
||||
|
||||
// Create an html dummy backup in the past.
|
||||
let htmlPath = OS.Path.join(backupFolder, "bookmarks-2008-01-01.html");
|
||||
let htmlFile = yield OS.File.open(htmlPath, { truncate: true });
|
||||
htmlFile.close();
|
||||
do_check_true(yield OS.File.exists(htmlPath));
|
||||
// Create 2 json dummy backups in the past.
|
||||
let oldJsonPath = OS.Path.join(backupFolder, "bookmarks-2008-01-01.json");
|
||||
let oldJsonFile = yield OS.File.open(oldJsonPath, { truncate: true });
|
||||
oldJsonFile.close();
|
||||
do_check_true(yield OS.File.exists(oldJsonPath));
|
||||
|
||||
// Create a json dummy backup in the past.
|
||||
let jsonPath = OS.Path.join(backupFolder, "bookmarks-2008-01-31.json");
|
||||
let jsonFile = yield OS.File.open(jsonPath, { truncate: true });
|
||||
jsonFile.close();
|
||||
|
@ -43,7 +42,7 @@ add_task(function check_max_backups_is_respected() {
|
|||
|
||||
do_check_eq(count, 2);
|
||||
do_check_neq(lastBackupPath, null);
|
||||
do_check_false(yield OS.File.exists(htmlPath));
|
||||
do_check_false(yield OS.File.exists(oldJsonPath));
|
||||
do_check_true(yield OS.File.exists(jsonPath));
|
||||
});
|
||||
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
function run_test() {
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_task(function* compress_bookmark_backups_test() {
|
||||
let backupFolder = yield PlacesBackups.getBackupFolder();
|
||||
|
||||
// Check for jsonlz4 extension
|
||||
let todayFilename = PlacesBackups.getFilenameForDate(new Date(2014, 04, 15), true);
|
||||
do_check_eq(todayFilename, "bookmarks-2014-05-15.jsonlz4");
|
||||
|
||||
yield PlacesBackups.create();
|
||||
|
||||
// Check that a backup for today has been created and the regex works fine for lz4.
|
||||
do_check_eq((yield PlacesBackups.getBackupFiles()).length, 1);
|
||||
let mostRecentBackupFile = yield PlacesBackups.getMostRecentBackup();
|
||||
do_check_neq(mostRecentBackupFile, null);
|
||||
do_check_true(PlacesBackups.filenamesRegex.test(OS.Path.basename(mostRecentBackupFile)));
|
||||
|
||||
// The most recent backup file has to be removed since saveBookmarksToJSONFile
|
||||
// will otherwise over-write the current backup, since it will be made on the
|
||||
// same date
|
||||
yield OS.File.remove(mostRecentBackupFile);
|
||||
do_check_false((yield OS.File.exists(mostRecentBackupFile)));
|
||||
|
||||
// Check that, if the user created a custom backup out of the default
|
||||
// backups folder, it gets copied (compressed) into it.
|
||||
let jsonFile = OS.Path.join(OS.Constants.Path.profileDir, "bookmarks.json");
|
||||
yield PlacesBackups.saveBookmarksToJSONFile(jsonFile);
|
||||
do_check_eq((yield PlacesBackups.getBackupFiles()).length, 1);
|
||||
|
||||
// Check if import works from lz4 compressed json
|
||||
let uri = NetUtil.newURI("http://www.mozilla.org/en-US/");
|
||||
let bm = PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
|
||||
uri,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
"bookmark");
|
||||
|
||||
// Force create a compressed backup, Remove the bookmark, the restore the backup
|
||||
yield PlacesBackups.create(undefined, true);
|
||||
let recentBackup = yield PlacesBackups.getMostRecentBackup();
|
||||
PlacesUtils.bookmarks.removeItem(bm);
|
||||
yield BookmarkJSONUtils.importFromFile(recentBackup, true);
|
||||
let root = PlacesUtils.getFolderContents(PlacesUtils.unfiledBookmarksFolderId).root;
|
||||
let node = root.getChild(0);
|
||||
do_check_eq(node.uri, uri.spec);
|
||||
|
||||
root.containerOpen = false;
|
||||
PlacesUtils.bookmarks.removeFolderChildren(PlacesUtils.unfiledBookmarksFolderId);
|
||||
|
||||
// Cleanup.
|
||||
yield OS.File.remove(jsonFile);
|
||||
});
|
|
@ -30,5 +30,6 @@ tail =
|
|||
[test_protectRoots.js]
|
||||
[test_818593-store-backup-metadata.js]
|
||||
[test_818584-discard-duplicate-backups.js]
|
||||
[test_818587_compress-bookmarks-backups.js]
|
||||
[test_992901-backup-unsorted-hierarchy.js]
|
||||
[test_997030-bookmarks-html-encode.js]
|
||||
|
|
|
@ -5,6 +5,7 @@ support-files =
|
|||
window_menubar.xul
|
||||
|
||||
[test_contextmenu_nested.xul]
|
||||
[test_contextmenu_menugroup.xul]
|
||||
[test_editor_currentURI.xul]
|
||||
[test_menubar.xul]
|
||||
skip-if = os == 'mac'
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||
<?xml-stylesheet href="/tests/SimpleTest/test.css" type="text/css"?>
|
||||
|
||||
<window title="Context menugroup Tests"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="application/javascript" src="popup_shared.js"></script>
|
||||
|
||||
<menupopup id="context">
|
||||
<menugroup>
|
||||
<menuitem id="a"/>
|
||||
<menuitem id="b"/>
|
||||
</menugroup>
|
||||
<menuitem id="c" label="c"/>
|
||||
</menupopup>
|
||||
|
||||
<button label="Check"/>
|
||||
|
||||
<vbox id="popuparea" popup="context" width="20" height="20"/>
|
||||
|
||||
<script type="application/javascript">
|
||||
<![CDATA[
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var gMenuPopup = $("context");
|
||||
ok(gMenuPopup, "Got the reference to the context menu");
|
||||
|
||||
var popupTests = [
|
||||
{
|
||||
testname: "one-down-key",
|
||||
condition: function() { return (navigator.platform.indexOf("Mac") == -1); },
|
||||
events: [ "popupshowing context", "popupshown context", "DOMMenuItemActive a" ],
|
||||
test: function () {
|
||||
synthesizeMouse($("popuparea"), 4, 4, {});
|
||||
synthesizeKey("VK_DOWN", {});
|
||||
},
|
||||
result: function (testname) {
|
||||
checkActive(gMenuPopup, "a", testname);
|
||||
}
|
||||
},
|
||||
{
|
||||
testname: "two-down-keys",
|
||||
condition: function() { return (navigator.platform.indexOf("Mac") == -1); },
|
||||
events: [ "DOMMenuItemInactive a", "DOMMenuItemActive b" ],
|
||||
test: function () synthesizeKey("VK_DOWN", {}),
|
||||
result: function (testname) {
|
||||
checkActive(gMenuPopup, "b", testname);
|
||||
}
|
||||
},
|
||||
{
|
||||
testname: "three-down-keys",
|
||||
condition: function() { return (navigator.platform.indexOf("Mac") == -1); },
|
||||
events: [ "DOMMenuItemInactive b", "DOMMenuItemActive c" ],
|
||||
test: function () synthesizeKey("VK_DOWN", {}),
|
||||
result: function (testname) {
|
||||
checkActive(gMenuPopup, "c", testname);
|
||||
}
|
||||
},
|
||||
{
|
||||
testname: "three-down-keys-one-up-key",
|
||||
condition: function() { return (navigator.platform.indexOf("Mac") == -1); },
|
||||
events: [ "DOMMenuItemInactive c", "DOMMenuItemActive b" ],
|
||||
test: function () synthesizeKey("VK_UP", {}),
|
||||
result: function (testname) {
|
||||
checkActive(gMenuPopup, "b", testname);
|
||||
}
|
||||
},
|
||||
{
|
||||
testname: "three-down-keys-two-up-keys",
|
||||
condition: function() { return (navigator.platform.indexOf("Mac") == -1); },
|
||||
events: [ "DOMMenuItemInactive b", "DOMMenuItemActive a" ],
|
||||
test: function () synthesizeKey("VK_UP", {}),
|
||||
result: function (testname) {
|
||||
checkActive(gMenuPopup, "a", testname);
|
||||
}
|
||||
},
|
||||
{
|
||||
testname: "three-down-keys-three-up-key",
|
||||
condition: function() { return (navigator.platform.indexOf("Mac") == -1); },
|
||||
events: [ "DOMMenuItemInactive a", "DOMMenuItemActive c" ],
|
||||
test: function () synthesizeKey("VK_UP", {}),
|
||||
result: function (testname) {
|
||||
checkActive(gMenuPopup, "c", testname);
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
SimpleTest.waitForFocus(function runTest() startPopupTests(popupTests));
|
||||
|
||||
]]>
|
||||
</script>
|
||||
|
||||
<body xmlns="http://www.w3.org/1999/xhtml"><p id="display"/></body>
|
||||
|
||||
</window>
|
|
@ -15,8 +15,8 @@ textbox {
|
|||
cursor: text;
|
||||
margin: 2px 4px;
|
||||
border: 1px solid #555555;
|
||||
padding: 2px 3px 3px;
|
||||
-moz-padding-start: 5px;
|
||||
padding: 2px 2px 3px;
|
||||
-moz-padding-start: 4px;
|
||||
background-color: white;
|
||||
color: black;
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ html|*.textbox-input,
|
|||
html|*.textbox-textarea {
|
||||
margin: 0px !important;
|
||||
border: none !important;
|
||||
padding: 0px !important;
|
||||
padding: 0px 1px !important;
|
||||
background-color: inherit;
|
||||
color: inherit;
|
||||
font: inherit;
|
||||
|
@ -59,6 +59,11 @@ textbox.plain {
|
|||
border: none !important;
|
||||
}
|
||||
|
||||
textbox.plain html|*.textbox-input,
|
||||
textbox.plain html|*.textbox-textarea {
|
||||
padding: 0px !important;
|
||||
}
|
||||
|
||||
/* ::::: search textbox ::::: */
|
||||
|
||||
.textbox-search-icon {
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
/* .padded is used by autocomplete widgets that don't have an icon. Gross. -dwh */
|
||||
textbox:not(.padded) {
|
||||
cursor: default;
|
||||
padding: 0 1px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
textbox[enablehistory="true"] {
|
||||
|
|
|
@ -30,7 +30,7 @@ html|*.numberbox-input {
|
|||
-moz-border-right-colors: ThreeDHighlight ThreeDLightShadow;
|
||||
-moz-border-bottom-colors: ThreeDHighlight ThreeDLightShadow;
|
||||
-moz-border-left-colors: ThreeDShadow ThreeDDarkShadow;
|
||||
padding: 3px 4px;
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
textbox[hidespinbuttons="true"] > .numberbox-input-box {
|
||||
|
|
|
@ -20,8 +20,8 @@ textbox {
|
|||
-moz-border-right-colors: ThreeDHighlight ThreeDLightShadow;
|
||||
-moz-border-bottom-colors: ThreeDHighlight ThreeDLightShadow;
|
||||
-moz-border-left-colors: ThreeDShadow ThreeDDarkShadow;
|
||||
padding: 2px 3px 3px;
|
||||
-moz-padding-start: 5px;
|
||||
padding: 2px 2px 3px;
|
||||
-moz-padding-start: 4px;
|
||||
background-color: -moz-Field;
|
||||
color: -moz-FieldText;
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ html|*.textbox-input,
|
|||
html|*.textbox-textarea {
|
||||
margin: 0px !important;
|
||||
border: none !important;
|
||||
padding: 0px !important;
|
||||
padding: 0px 1px !important;
|
||||
background-color: inherit;
|
||||
color: inherit;
|
||||
font: inherit;
|
||||
|
@ -65,6 +65,11 @@ textbox.plain {
|
|||
border: none !important;
|
||||
}
|
||||
|
||||
textbox.plain html|*.textbox-input,
|
||||
textbox.plain html|*.textbox-textarea {
|
||||
padding: 0px !important;
|
||||
}
|
||||
|
||||
/* ::::: search textbox ::::: */
|
||||
|
||||
.textbox-search-icon {
|
||||
|
|
|
@ -16,7 +16,7 @@ textbox {
|
|||
-moz-border-left-colors: transparent #888888 #000000;
|
||||
border-top-right-radius: 2px;
|
||||
border-bottom-left-radius: 2px;
|
||||
padding: 0px 1px;
|
||||
padding: 0px;
|
||||
background-color: -moz-Field;
|
||||
color: -moz-FieldText;
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ html|*.textbox-input,
|
|||
html|*.textbox-textarea {
|
||||
margin: 0px !important;
|
||||
border: none !important;
|
||||
padding: 0px !important;
|
||||
padding: 0px 1px !important;
|
||||
background-color: inherit;
|
||||
color: inherit;
|
||||
font: inherit;
|
||||
|
@ -65,11 +65,16 @@ textbox.plain {
|
|||
border: none !important;
|
||||
}
|
||||
|
||||
textbox.plain html|*.textbox-input,
|
||||
textbox.plain html|*.textbox-textarea {
|
||||
padding: 0px !important;
|
||||
}
|
||||
|
||||
/* ::::: search box ::::: */
|
||||
|
||||
textbox[type="search"] {
|
||||
-moz-appearance: searchfield;
|
||||
padding: 1px 2px;
|
||||
padding: 1px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
|
@ -84,7 +89,7 @@ textbox[type="search"] {
|
|||
}
|
||||
|
||||
textbox[type="search"].compact {
|
||||
padding: 0 1px;
|
||||
padding: 0;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,8 +20,8 @@ textbox {
|
|||
-moz-border-right-colors: ThreeDHighlight ThreeDLightShadow;
|
||||
-moz-border-bottom-colors: ThreeDHighlight ThreeDLightShadow;
|
||||
-moz-border-left-colors: ThreeDShadow ThreeDDarkShadow;
|
||||
padding: 2px 3px 3px;
|
||||
-moz-padding-start: 5px;
|
||||
padding: 2px 2px 3px;
|
||||
-moz-padding-start: 4px;
|
||||
background-color: -moz-Field;
|
||||
color: -moz-FieldText;
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ html|*.textbox-input,
|
|||
html|*.textbox-textarea {
|
||||
margin: 0px !important;
|
||||
border: none !important;
|
||||
padding: 0px !important;
|
||||
padding: 0px 1px !important;
|
||||
background-color: inherit;
|
||||
color: inherit;
|
||||
font: inherit;
|
||||
|
@ -65,6 +65,11 @@ textbox.plain {
|
|||
border: none !important;
|
||||
}
|
||||
|
||||
textbox.plain html|*.textbox-input,
|
||||
textbox.plain html|*.textbox-textarea {
|
||||
padding: 0px !important;
|
||||
}
|
||||
|
||||
/* ::::: search textbox ::::: */
|
||||
|
||||
.textbox-search-icon {
|
||||
|
|
Загрузка…
Ссылка в новой задаче