Merge m-c to b-i

This commit is contained in:
Phil Ringnalda 2014-03-15 21:24:58 -07:00
commit b7eed23b92
38 changed files with 483 additions and 185 deletions

View File

@ -203,20 +203,22 @@
align="start"
orient="vertical"
role="alert">
<hbox>
<vbox>
<vbox>
<hbox pack="end">
<toolbarbutton id="UITourTooltipClose" class="close-icon"
tooltiptext="&uiTour.infoPanel.close;"/>
</hbox>
<hbox id="UITourTooltipBody">
<vbox id="UITourTooltipIconContainer">
<image id="UITourTooltipIcon"/>
</vbox>
<vbox flex="1">
<label id="UITourTooltipTitle" flex="1"/>
<description id="UITourTooltipDescription" flex="1"/>
<hbox id="UITourTooltipButtons" flex="1" align="center"/>
</vbox>
<vbox align="start">
<toolbarbutton id="UITourTooltipClose" class="close-icon"
tooltiptext="&uiTour.infoPanel.close;"/>
</vbox>
</hbox>
<hbox id="UITourTooltipButtons" flex="1" align="center"/>
</vbox>
</panel>
<!-- type="default" forces frames to be created so that the panel's size can be determined -->
<panel id="UITourHighlightContainer"

View File

@ -334,15 +334,17 @@ const DownloadsIndicatorView = {
let anchor = DownloadsButton._placeholder;
let widgetGroup = CustomizableUI.getWidget("downloads-button");
let widgetInWindow = widgetGroup.forWindow(window);
if (widgetInWindow.overflowed || widgetGroup.areaType == CustomizableUI.TYPE_MENU_PANEL) {
let widget = widgetGroup.forWindow(window);
if (widget.overflowed || widgetGroup.areaType == CustomizableUI.TYPE_MENU_PANEL) {
if (anchor && this._isAncestorPanelOpen(anchor)) {
// If the containing panel is open, don't do anything:
// If the containing panel is open, don't do anything, because the
// notification would appear under the open panel. See
// https://bugzilla.mozilla.org/show_bug.cgi?id=984023
return;
}
// Otherwise, try to use the anchor of the panel:
anchor = widgetInWindow.anchor;
anchor = widget.anchor;
}
if (!anchor || !isElementVisible(anchor.parentNode)) {
// Our container isn't visible, so can't show the animation:

View File

@ -766,6 +766,12 @@ PlacesViewBase.prototype = {
hasMultipleURIs = numURINodes > 1;
}
if (!hasMultipleURIs) {
aPopup.setAttribute("singleitempopup", "true");
} else {
aPopup.removeAttribute("singleitempopup");
}
if (!hasMultipleURIs) {
// We don't have to show any option.
if (aPopup._endOptOpenAllInTabs) {

View File

@ -124,11 +124,38 @@ PlacesController.prototype = {
},
isCommandEnabled: function PC_isCommandEnabled(aCommand) {
if (PlacesUIUtils.useAsyncTransactions) {
switch (aCommand) {
case "cmd_cut":
case "placesCmd_cut":
case "cmd_copy":
case "cmd_paste":
case "cmd_delete":
case "placesCmd_delete":
case "placesCmd_moveBookmarks":
case "cmd_paste":
case "placesCmd_paste":
case "placesCmd_new:folder":
case "placesCmd_new:livemark":
case "placesCmd_new:bookmark":
case "placesCmd_new:separator":
case "placesCmd_sortBy:name":
case "placesCmd_createBookmark":
return false;
}
}
switch (aCommand) {
case "cmd_undo":
return PlacesUtils.transactionManager.numberOfUndoItems > 0;
if (!PlacesUIUtils.useAsyncTransactions)
return PlacesUtils.transactionManager.numberOfUndoItems > 0;
return PlacesTransactions.topUndoEntry != null;
case "cmd_redo":
return PlacesUtils.transactionManager.numberOfRedoItems > 0;
if (!PlacesUIUtils.useAsyncTransactions)
return PlacesUtils.transactionManager.numberOfRedoItems > 0;
return PlacesTransactions.topRedoEntry != null;
case "cmd_cut":
case "placesCmd_cut":
var nodes = this._view.selectedNodes;

View File

@ -1022,6 +1022,14 @@ XPCOMUtils.defineLazyGetter(PlacesUIUtils, "ellipsis", function() {
Ci.nsIPrefLocalizedString).data;
});
XPCOMUtils.defineLazyGetter(PlacesUIUtils, "useAsyncTransactions", function() {
try {
return Services.prefs.getBoolPref("browser.places.useAsyncTransactions");
}
catch(ex) { }
return false;
});
XPCOMUtils.defineLazyServiceGetter(this, "URIFixup",
"@mozilla.org/docshell/urifixup;1",
"nsIURIFixup");

View File

@ -4,7 +4,8 @@
const Cu = Components.utils;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource:///modules/devtools/gDevTools.jsm");
Cu.import("resource://gre/modules/devtools/dbg-client.jsm");
const {gDevTools} = Cu.import("resource:///modules/devtools/gDevTools.jsm", {});
const {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
const {require} = devtools;
@ -17,6 +18,7 @@ const {getTargetForApp, launchApp, closeApp}
const DeviceStore = require("devtools/app-manager/device-store");
const WebappsStore = require("devtools/app-manager/webapps-store");
const promise = require("sdk/core/promise");
const DEFAULT_APP_ICON = "chrome://browser/skin/devtools/app-manager/default-app-icon.png";
window.addEventListener("message", function(event) {
try {
@ -141,7 +143,7 @@ let UI = {
if (panel) panel.classList.add("selected");
},
openToolbox: function(manifest) {
openToolboxForApp: function(manifest) {
if (!this.connected) {
return;
}
@ -155,6 +157,31 @@ let UI = {
}, console.error);
},
_getTargetForTab: function (form) {
let options = {
form: form,
client: this.connection.client,
chrome: false
};
let deferred = promise.defer();
return devtools.TargetFactory.forRemoteTab(options);
},
openToolboxForTab: function (aNode) {
let index = Array.prototype.indexOf.apply(
aNode.parentNode.parentNode.parentNode.children,
[aNode.parentNode.parentNode]);
this.connection.client.listTabs(
response => {
let tab = response.tabs[index];
this._getTargetForTab(tab).then(target => {
top.UI.openAndShowToolboxForTarget(
target, tab.title, DEFAULT_APP_ICON);
}, console.error);
}
);
},
startApp: function(manifest) {
if (!this.connected) {
return promise.reject();

View File

@ -44,6 +44,7 @@
<button class="help">&device.help;</button>
</a>
</div>
<div onclick="UI.setTab('browser-tabs')" class="tab sidebar-item browser-tabs" title="&device.browserTabsTooltip;">&device.browserTabs;</div>
</div>
</div>
</aside>
@ -68,6 +69,9 @@
<div class="deny-label" title="&device.denyTooltip;">&device.deny;</div>
</div>
</div>
<div class="tabpanel browser-tabs">
<section template-loop='{"arrayPath":"device.tabs","childSelector":"#browser-tab-template"}'></section>
</div>
</div>
</section>
</section>
@ -83,12 +87,24 @@
</div>
</template>
<template id="browser-tab-template">
<div class="browser-tab">
<div class="browser-tab-details">
<p template='{"type":"textContent","path":"title"}'></p>
<p class="browser-tab-url-subheading" template='{"type":"textContent","path":"url"}'></p>
</div>
<div class="browser-tab-buttons">
<button class="button-debug" template='{"type":"attribute","path":"actor","name":"data-actor"}' onclick="UI.openToolboxForTab(this)" style="display: inline-block;" title="&device.debugBrowserTabTooltip;">&device.debugBrowserTab;</button>
</div>
</div>
</template>
<template id="app-template">
<div class="app" template='{"type":"attribute","path":"running","name":"running"}'>
<img class="app-icon" template='{"type":"attribute","path":"iconURL","name":"src"}'></img>
<span class="app-name" template='{"type":"textContent","path":"name"}'></span>
<div class="app-buttons">
<button class="button-debug" template='{"type":"attribute","path":"manifestURL","name":"data-manifest"}' onclick="UI.openToolbox(this.dataset.manifest)" title="&device.debugAppTooltip;">&device.debugApp;</button>
<button class="button-debug" template='{"type":"attribute","path":"manifestURL","name":"data-manifest"}' onclick="UI.openToolboxForApp(this.dataset.manifest)" title="&device.debugAppTooltip;">&device.debugApp;</button>
<button class="button-start" template='{"type":"attribute","path":"manifestURL","name":"data-manifest"}' onclick="UI.startApp(this.dataset.manifest)" title="&device.startAppTooltip;">&device.startApp;</button>
<button class="button-stop" template='{"type":"attribute","path":"manifestURL","name":"data-manifest"}' onclick="UI.stopApp(this.dataset.manifest)" title="&device.stopAppTooltip;">&device.stopApp;</button>
</div>

View File

@ -31,6 +31,7 @@ module.exports = DeviceStore = function(connection) {
this._connection = connection;
this._connection.once(Connection.Events.DESTROYED, this.destroy);
this._connection.on(Connection.Events.STATUS_CHANGED, this._onStatusChanged);
this._onTabListChanged = this._onTabListChanged.bind(this);
this._onStatusChanged();
return this;
}
@ -51,6 +52,7 @@ DeviceStore.prototype = {
_resetStore: function() {
this.object.description = {};
this.object.permissions = [];
this.object.tabs = [];
},
_onStatusChanged: function() {
@ -61,9 +63,23 @@ DeviceStore.prototype = {
}
},
_onTabListChanged: function() {
this._listTabs();
},
_listTabs: function() {
this._connection.client.listTabs((resp) => {
if (resp.error) {
this._connection.disconnect();
return;
}
this._deviceFront = getDeviceFront(this._connection.client, resp);
// Save remote browser's tabs
this.object.tabs = resp.tabs;
// Add listener to update remote browser's tabs list in app-manager
// when it changes
this._connection.client.addListener(
'tabListChanged', this._onTabListChanged);
this._feedStore();
});
},
@ -96,5 +112,5 @@ DeviceStore.prototype = {
}
this.object.permissions = permissionsArray;
});
},
}
}

View File

@ -67,13 +67,13 @@ Bug 901520 - [app manager] data store for device
});
connection.once("disconnected", function() {
compare(store.object, {description:{},permissions:[]}, "empty store after disconnect")
compare(store.object, {description:{},permissions:[],tabs:[]}, "empty store after disconnect")
connection.destroy();
DebuggerServer.destroy();
SimpleTest.finish();
});
compare(store.object, {description:{},permissions:[]}, "empty store before disconnect")
compare(store.object, {description:{},permissions:[],tabs:[]}, "empty store before disconnect")
connection.connect();

View File

@ -22,7 +22,7 @@
<link rel="stylesheet" href="view.css" type="text/css"/>
</head>
<body class="theme-body devtools-monospace">
<body class="theme-sidebar devtools-monospace">
<p id="header">
<span id="element-size"></span><span id="element-position"></span>

View File

@ -686,7 +686,6 @@ just addresses the organization to follow, e.g. "This site is run by " -->
<!ENTITY customizeMode.tabTitle "Customize &brandShortName;">
<!ENTITY customizeMode.menuAndToolbars.label "Menu and toolbars">
<!ENTITY customizeMode.menuAndToolbars.header2 "Additional Tools and Features">
<!ENTITY customizeMode.menuAndToolbars.empty "Want more tools?">
<!ENTITY customizeMode.menuAndToolbars.emptyLink "Choose from thousands of add-ons">

View File

@ -32,6 +32,10 @@
<!ENTITY device.permissions "Permissions">
<!ENTITY device.permissionsTooltip "View a table of the permissions accessible to the different types of apps">
<!ENTITY device.permissionsHelpLink "https://developer.mozilla.org/docs/Web/Apps/App_permissions">
<!ENTITY device.browserTabs "Browser Tabs">
<!ENTITY device.browserTabsTooltip "View a list of tabs in the browser of the connected device">
<!ENTITY device.debugBrowserTab "Debug">
<!ENTITY device.debugBrowserTabTooltip "Open the Developer Tools connected to this browser tab on the device">
<!ENTITY device.help "Help">
<!ENTITY connection.connectTooltip "Connect to the device">

View File

@ -553,8 +553,8 @@ this.UITour = {
if (!aWindowClosing) {
this.hideHighlight(aWindow);
this.hideInfo(aWindow);
aWindow.PanelUI.panel.removeAttribute("noautohide");
this.recreatePopup(aWindow.PanelUI.panel);
// Ensure the menu panel is hidden before calling recreatePopup so popup events occur.
this.hideMenu(aWindow, "appMenu");
}
this.endUrlbarCapture(aWindow);
@ -912,6 +912,9 @@ this.UITour = {
if (button.style == "link")
el.setAttribute("class", "button-link");
if (button.style == "primary")
el.setAttribute("class", "button-primary");
let callbackID = button.callbackID;
el.addEventListener("command", event => {
tooltip.hidePopup();

View File

@ -251,4 +251,10 @@ let tests = [
gContentAPI.showInfo("urlbar", "urlbar title", "urlbar text");
},
// Make sure this test is last in the file so the appMenu gets left open and done will confirm it got tore down.
function cleanupMenus(done) {
gContentAPI.showMenu("appMenu");
done();
},
];

View File

@ -128,6 +128,9 @@ function UITourTest() {
is_element_hidden(tooltip, "Tooltip should be closed/hidden after UITour tab is closed");
ok(!PanelUI.panel.hasAttribute("noautohide"), "@noautohide on the menu panel should have been cleaned up");
ok(!PanelUI.panel.hasAttribute("panelopen"), "The panel shouldn't have @panelopen");
isnot(PanelUI.panel.state, "open", "The panel shouldn't be open");
is(document.getElementById("PanelUI-menu-button").hasAttribute("open"), false, "Menu button should know that the menu is closed");
is(UITour.pinnedTabs.get(window), null, "Any pinned tab should be closed after UITour tab is closed");

View File

@ -81,13 +81,13 @@
}
/* Places toolbar */
toolbarbutton.bookmark-item,
toolbarbutton.bookmark-item:not(.subviewbutton),
#personal-bookmarks[cui-areatype="toolbar"]:not([overflowedItem=true]) > #bookmarks-toolbar-placeholder {
margin: 0;
padding: 2px 3px;
}
toolbarbutton.bookmark-item:hover:active,
toolbarbutton.bookmark-item:not(.subviewbutton):hover:active,
toolbarbutton.bookmark-item[open="true"] {
padding-top: 3px;
padding-bottom: 1px;
@ -188,7 +188,7 @@ menuitem.bookmark-item {
max-width: 32em;
}
.bookmark-item > .menu-iconic-left {
.bookmark-item:not(.subviewbutton) > .menu-iconic-left {
margin-top: 0;
margin-bottom: 0;
}
@ -2235,14 +2235,11 @@ chatbox {
}
#UITourTooltipClose {
-moz-appearance: toolbarbutton;
list-style-image: url("moz-icon://stock/gtk-close?size=menu");
}
#UITourTooltipClose > .toolbarbutton-icon {
margin: -4px;
-moz-margin-end: -4px;
height: 16px;
width: 16px;
}
#UITourTooltipButtons {
margin-bottom: 0;
margin-bottom: -10px;
}

View File

@ -4,10 +4,29 @@
%include ../../shared/customizableui/panelUIOverlay.inc.css
.panel-subviews {
background-color: -moz-dialog;
}
#BMB_bookmarksPopup > menuitem[type="checkbox"] {
-moz-appearance: none !important; /* important, to override toolkit rule */
}
#BMB_bookmarksPopup menupopup[placespopup=true] {
margin-top: -6px;
padding-top: 2px;
}
/* Add some space at the top because there are no headers: */
#BMB_bookmarksPopup menupopup[placespopup=true] > hbox > .popup-internal-box > .arrowscrollbox-scrollbox > .scrollbox-innerbox {
padding-top: 4px;
}
.subviewbutton > .toolbarbutton-text {
padding-top: 3px;
padding-bottom: 3px;
}
.widget-overflow-list .toolbarbutton-1 > .toolbarbutton-menubutton-button {
-moz-appearance: none;
border: 0;
@ -57,6 +76,18 @@ menu[disabled="true"].subviewbutton > .menu-right {
-moz-image-region: rect(0, 32px, 16px, 16px);
}
.subviewbutton > .toolbarbutton-icon {
-moz-margin-end: 5px !important;
}
.subviewbutton > .menu-right,
.subviewbutton > .menu-iconic-left {
padding-top: 1px;
/* These need !important to override menu.css */
margin-top: 1px !important;
margin-bottom: 2px !important;
}
.PanelUI-subView toolbarseparator,
.PanelUI-subView menuseparator,
.cui-widget-panelview menuseparator,

View File

@ -2,15 +2,11 @@
* 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/. */
.theme-dark .theme-body {
.theme-dark .theme-sidebar {
background-image: url(layout-background-grid.png);
}
.theme-light .theme-body {
background-image: url(layout-background-grid.png), radial-gradient(circle at 50% 70%, hsl(210,53%,45%) 0%, hsl(210,54%,33%) 100%);
}
.theme-body {
.theme-sidebar {
color: hsl(210,53%,45%) !important;
box-sizing: border-box;
}

View File

@ -4363,16 +4363,18 @@ window > chatbox {
%include ../shared/UITour.inc.css
#UITourTooltipIcon {
-moz-margin-start: 0;
}
#UITourTooltipDescription {
font-size: 1.1rem;
line-height: 1.9rem;
font-size: 1.18rem;
line-height: 2rem;
}
#UITourTooltipClose {
-moz-margin-end: -15px;
margin-top: -12px;
-moz-margin-end: -10px;
margin-top: -14px;
}
@media (min-resolution: 2dppx) {
#UITourTooltipClose > .toolbarbutton-icon {
width: 16px;
}
}

View File

@ -98,8 +98,8 @@
menu.subviewbutton,
menuitem.subviewbutton:not(.panel-subview-footer) {
padding-top: 5px;
padding-bottom: 5px;
padding-top: 2px;
padding-bottom: 2px;
}
/* Override OSX-specific toolkit styles for the bookmarks panel */

View File

@ -2,15 +2,11 @@
* 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/. */
.theme-dark .theme-body {
.theme-dark .theme-sidebar {
background-image: url(layout-background-grid.png);
}
.theme-light .theme-body {
background-image: url(layout-background-grid.png), radial-gradient(circle at 50% 70%, hsl(210,53%,45%) 0%, hsl(210,54%,33%) 100%);
}
.theme-body {
.theme-sidebar {
color: hsl(210,53%,45%) !important;
box-sizing: border-box;
}

View File

@ -23,11 +23,23 @@
min-width: 32px;
}
#UITourTooltipBody {
-moz-margin-end: 14px;
}
#UITourTooltipBody > vbox {
padding-top: 4px;
}
#UITourTooltipIconContainer {
-moz-margin-start: -16px;
}
#UITourTooltipIcon {
width: 48px;
height: 48px;
-moz-margin-start: 8px;
-moz-margin-end: 18px;
-moz-margin-start: 28px;
-moz-margin-end: 28px;
}
#UITourTooltipTitle,
@ -36,11 +48,11 @@
}
#UITourTooltipTitle {
font-size: 1.3rem;
font-size: 1.45rem;
font-weight: bold;
-moz-margin-start: 0;
-moz-margin-end: 0;
margin: 10px 0 19px 0;
margin: 0 0 9px 0;
}
#UITourTooltipDescription {
@ -48,6 +60,7 @@
-moz-margin-end: 0;
font-size: 1.15rem;
line-height: 1.8rem;
margin-bottom: 0; /* Override global.css */
}
#UITourTooltipClose {
@ -56,27 +69,29 @@
background-color: transparent;
min-width: 0;
-moz-margin-start: 4px;
-moz-margin-end: -10px;
margin-top: -8px;
margin-top: -2px;
}
#UITourTooltipClose > .toolbarbutton-text {
display: none;
}
#UITourTooltipButtons {
margin: 1.5em 0 .9em 0;
-moz-box-pack: end;
background-color: hsla(210,4%,10%,.07);
border-top: 1px solid hsla(210,4%,10%,.14);
margin: 24px -16px -16px;
padding: 2em 15px;
}
#UITourTooltipButtons > button {
margin-left: 6px;
margin-right: 6px;
margin: 0 15px;
}
#UITourTooltipButtons > button:first-child {
-moz-margin-start: 0;
}
#UITourTooltipButtons > button:last-child {
-moz-margin-end: 24px;
}
#UITourTooltipButtons > button[image] > .button-box > .button-icon {
width: 16px;
height: 16px;
@ -89,11 +104,12 @@
#UITourTooltipButtons > button:not(.button-link) {
-moz-appearance: none;
padding: 2px 10px;
background-color: hsla(210,4%,10%,.08);
border-radius: 2px;
background-color: rgb(251,251,251);
border-radius: 3px;
border: 1px solid;
border-color: hsla(210,4%,10%,.1);
border-color: rgb(192,192,192);
color: rgb(71,71,71);
padding: 4px 30px;
transition-property: background-color, border-color;
transition-duration: 150ms;
}
@ -117,3 +133,15 @@
#UITourTooltipButtons > button.button-link:hover {
color: black;
}
/* The primary button gets the same color as the customize button. */
#UITourTooltipButtons > button.button-primary {
background-color: rgb(116,191,67);
color: white;
padding-left: 30px;
padding-right: 30px;
}
#UITourTooltipButtons > button.button-primary:not(:active):hover {
background-color: rgb(105,173,61);
}

View File

@ -101,7 +101,7 @@
#PanelUI-popup .panel-subview-body {
margin: -4px;
padding: 2px 4px;
padding: 4px 4px;
}
.panel-subview-header,
@ -586,13 +586,11 @@ panelview .toolbarbutton-1,
.panelUI-grid .toolbarbutton-1 > .toolbarbutton-menubutton-button,
.toolbaritem-combined-buttons@inAnyPanel@ > toolbarbutton {
-moz-appearance: none;
padding: 2px 6px;
padding: 0 6px;
background-color: hsla(210,4%,10%,0);
border-radius: 2px;
border-style: solid;
border-color: hsla(210,4%,10%,0);
transition-property: background-color, border-color;
transition-duration: 150ms;
}
panelview .toolbarbutton-1,
@ -615,14 +613,20 @@ panelview .toolbarbutton-1,
}
.subviewbutton:not(.panel-subview-footer) {
margin: 2px 0;
margin: 0;
}
.subviewbutton:not(.panel-subview-footer) > .toolbarbutton-text,
/* Bookmark items need a more specific selector. */
.PanelUI-subView .subviewbutton:not(.panel-subview-footer) > .menu-text,
.PanelUI-subView .subviewbutton:not(.panel-subview-footer) > .menu-iconic-text {
font-size: 1.1em;
font: menu;
}
/* This is a <label> but it should fit in with the menu font- and colorwise. */
#PanelUI-characterEncodingView-autodetect-label {
font: menu;
color: inherit;
}
.cui-widget-panelview .subviewbutton:not(.panel-subview-footer) {
@ -680,7 +684,7 @@ menuitem.subviewbutton@menuStateActive@,
}
#BMB_bookmarksPopup .subviewbutton {
font: inherit;
font: menu;
font-weight: normal;
}
@ -700,22 +704,32 @@ menuitem.subviewbutton@menuStateActive@,
padding-bottom: 0px;
}
#BMB_bookmarksPopup menupopup {
padding-top: 2px;
}
#BMB_bookmarksPopup menupopup > .bookmarks-actions-menuseparator {
/* Hide bottom separator as the styled footer includes a top border serving the same purpose */
display: none;
}
/* Popups with only one item don't have a footer */
menupopup[placespopup=true][singleitempopup=true] > hbox > .popup-internal-box > .arrowscrollbox-scrollbox > .scrollbox-innerbox,
/* These popups never have a footer */
#BMB_bookmarksToolbarPopup > hbox > .popup-internal-box > .arrowscrollbox-scrollbox > .scrollbox-innerbox,
#BMB_unsortedBookmarksPopup > hbox > .popup-internal-box > .arrowscrollbox-scrollbox > .scrollbox-innerbox {
/* And so they need some bottom padding: */
padding-bottom: 4px;
}
/* Disabled (empty) item is always alone and never has an icon, so fix its left padding */
#BMB_bookmarksPopup menupopup[emptyplacesresult] .bookmark-item.subviewbutton {
padding-left: 6px;
}
.PanelUI-subView menuseparator,
.PanelUI-subView toolbarseparator,
.cui-widget-panelview menuseparator {
-moz-appearance: none;
min-height: 0;
border-top: 1px solid hsla(210,4%,10%,.15);
margin: 2px 0;
margin: 6px 0;
padding: 0;
}
@ -949,14 +963,14 @@ toolbaritem[overflowedItem=true],
}
.subviewbutton[checked="true"] {
background: url("chrome://global/skin/menu/shared-menu-check.png") top 7px left 7px / 11px 11px no-repeat transparent;
background: url("chrome://global/skin/menu/shared-menu-check.png") center left 7px / 11px 11px no-repeat transparent;
}
.PanelUI-subView .menu-iconic-left {
.subviewbutton > .menu-iconic-left {
-moz-appearance: none;
-moz-margin-end: 3px;
}
.PanelUI-subView menuitem[checked="true"] > .menu-iconic-left {
menuitem[checked="true"].subviewbutton > .menu-iconic-left {
visibility: hidden;
}

View File

@ -308,34 +308,34 @@ header {
/***************** APPS *****************/
/***************** APPS & BROWSER TABS *****************/
.apps {
.apps, .browser-tabs {
display: flex;
flex-direction: column;
overflow: auto;
}
.app {
.app, .browser-tab {
display: flex;
align-items: center;
order: 1;
}
.app-name {
.app-name, .browser-tab-details {
flex-grow: 1;
font-weight: bold;
}
.app {
.app, .browser-tab {
padding: 10px 20px;
border-bottom: 1px solid #CCC;
}
.app:hover {
.app:hover, .browser-tab:hover {
background-color: #EFEFEF;
}
@ -345,6 +345,10 @@ header {
margin-right: 10px;
}
.browser-tab-url-subheading {
font-size: 10px;
}
/***************** NOT CONNECTED *****************/

View File

@ -328,13 +328,13 @@
/* ::::: bookmark buttons ::::: */
toolbarbutton.bookmark-item,
toolbarbutton.bookmark-item:not(.subviewbutton),
#personal-bookmarks[cui-areatype="toolbar"]:not([overflowedItem=true]) > #bookmarks-toolbar-placeholder {
margin: 0;
padding: 2px 3px;
}
toolbarbutton.bookmark-item:hover:active:not([disabled="true"]),
toolbarbutton.bookmark-item:not([disabled="true"]):not(.subviewbutton):hover:active,
toolbarbutton.bookmark-item[open="true"] {
padding-top: 3px;
padding-bottom: 1px;
@ -420,7 +420,7 @@ menuitem.bookmark-item {
max-width: 32em;
}
.bookmark-item > .menu-iconic-left {
.bookmark-item:not(.subviewbutton) > .menu-iconic-left {
margin-top: 0;
margin-bottom: 0;
}
@ -2194,6 +2194,10 @@ toolbarbutton.bookmark-item[dragover="true"][open="true"] {
margin-top: -10px;
}
#notification-popup .panel-promo-box {
margin: 10px -10px -10px;
}
#notification-popup-box {
position: relative;
background-color: #fff;
@ -2757,3 +2761,7 @@ chatbox {
}
%include ../shared/UITour.inc.css
#UITourTooltipButtons {
margin: 24px -4px -4px;
}

View File

@ -16,14 +16,14 @@
/* bookmark panel submenus */
#BMB_bookmarksPopup menupopup {
#BMB_bookmarksPopup menupopup[placespopup=true] {
-moz-appearance: none;
background: transparent;
border: none;
padding: 6px;
}
#BMB_bookmarksPopup menupopup > hbox {
#BMB_bookmarksPopup menupopup[placespopup=true] > hbox {
/* emulating chrome://browser/content/places/menu.xml#places-popup-arrow but without the arrow */
box-shadow: 0 0 4px rgba(0,0,0,0.2);
background: #FFF;
@ -32,16 +32,50 @@
margin-top: -4px;
}
#BMB_bookmarksPopup menupopup {
padding-top: 2px;
}
/* Add some space at the top because there are no headers: */
#BMB_bookmarksPopup menupopup[placespopup=true] > hbox > .popup-internal-box > .arrowscrollbox-scrollbox > .scrollbox-innerbox {
padding-top: 4px;
}
#BMB_bookmarksPopup .menu-text {
color: #000;
}
#BMB_bookmarksPopup .subviewbutton[disabled=true] > .menu-text {
color: #6d6d6d;
}
/* bookmark panel separator */
#BMB_bookmarksPopup menuseparator {
padding-top: 0;
padding-bottom: 0;
}
.subviewbutton > .menu-right,
.subviewbutton > .menu-iconic-left {
padding-top: 1px;
margin-top: 1px;
margin-bottom: 2px;
}
/* Disabled empty item looks too small otherwise, because it has no icon. */
menuitem.subviewbutton[disabled]:not(.menuitem-iconic),
/* Same for checkbox menu items, whose icons lose size due to -moz-appearance: none: */
menuitem[type="checkbox"].subviewbutton {
/* This is 16px for an icon + 3px for its margins + 1px for its padding +
* 2px for its border, see above */
min-height: 22px;
}
.subviewbutton > .toolbarbutton-text {
padding-top: 3px;
padding-bottom: 3px;
}
.widget-overflow-list .toolbarbutton-1 > .toolbarbutton-menubutton-button {
-moz-appearance: none;
border: 0;

View File

@ -2,15 +2,11 @@
* 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/. */
.theme-dark .theme-body {
.theme-dark .theme-sidebar {
background-image: url(layout-background-grid.png);
}
.theme-light .theme-body {
background-image: url(layout-background-grid.png), radial-gradient(circle at 50% 70%, hsl(210,53%,45%) 0%, hsl(210,54%,33%) 100%);
}
.theme-body {
.theme-sidebar {
color: hsl(210,53%,45%) !important;
box-sizing: border-box;
}

View File

@ -293,7 +293,7 @@ case "$target" in
# The build tools got moved around to different directories in
# SDK Tools r22. Try to locate them.
android_build_tools=""
for suffix in android-4.4 android-4.3 android-4.2.2 19.0.2 19.0.0 18.1.0 18.0.1 18.0.0 17.0.0; do
for suffix in android-4.4 android-4.3 android-4.2.2 19.0.3 19.0.2 19.0.0 18.1.0 18.0.1 18.0.0 17.0.0; do
tools_directory="$android_sdk_root/build-tools/$suffix"
if test -d "$tools_directory" ; then
android_build_tools="$tools_directory"

View File

@ -674,7 +674,7 @@ pref("ui.scrolling.axis_lock_mode", "standard");
pref("ui.scrolling.negate_wheel_scrollY", true);
// Determine the dead zone for gamepad joysticks. Higher values result in larger dead zones; use a negative value to
// auto-detect based on reported hardware values
pref("ui.scrolling.gamepad_dead_zone", 10);
pref("ui.scrolling.gamepad_dead_zone", 115);
// Enable accessibility mode if platform accessibility is enabled.

View File

@ -392,7 +392,7 @@ public class Prompt implements OnClickListener, OnCancelListener, OnItemClickLis
ret.put("button", -1);
} catch(Exception ex) { }
addInputValues(ret);
finishDialog(ret);
notifyClosing(ret);
}
/* Called any time we're closing the dialog to cleanup and notify listeners that the dialog
@ -406,16 +406,13 @@ public class Prompt implements OnClickListener, OnCancelListener, OnItemClickLis
addListResult(ret, which);
addInputValues(ret);
finishDialog(ret);
notifyClosing(ret);
}
/* Called any time we're closing the dialog to cleanup and notify listeners that the dialog
* is closing.
*/
public void finishDialog(JSONObject aReturn) {
mInputs = null;
mButtons = null;
mDialog = null;
private void notifyClosing(JSONObject aReturn) {
try {
aReturn.put("guid", mGuid);
} catch(JSONException ex) { }
@ -426,7 +423,6 @@ public class Prompt implements OnClickListener, OnCancelListener, OnItemClickLis
if (mCallback != null) {
mCallback.onPromptFinished(aReturn.toString());
}
mGuid = null;
}
/* Handles parsing the initial JSON sent to show dialogs

View File

@ -6,6 +6,10 @@ import com.jayway.android.robotium.solo.Solo;
import org.mozilla.gecko.*;
import org.mozilla.gecko.GeckoThread.LaunchState;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.Activity;
import android.app.Instrumentation;
import android.content.ContentResolver;
@ -59,9 +63,11 @@ abstract class BaseTest extends ActivityInstrumentationTestCase2<Activity> {
public static final int MAX_WAIT_MS = 4500;
public static final int LONG_PRESS_TIME = 6000;
private static final int GECKO_READY_WAIT_MS = 180000;
public static final int MAX_WAIT_BLOCK_FOR_EVENT_DATA_MS = 90000;
private static Class<Activity> mLauncherActivityClass;
private Activity mActivity;
private int mPreferenceRequestID = 0;
protected Solo mSolo;
protected Driver mDriver;
protected Assert mAsserter;
@ -897,4 +903,63 @@ abstract class BaseTest extends ActivityInstrumentationTestCase2<Activity> {
}
}
}
/**
* Set the preference and wait for it to change before proceeding with the test.
*/
public void setPreferenceAndWaitForChange(final JSONObject jsonPref) {
mActions.sendGeckoEvent("Preferences:Set", jsonPref.toString());
// Get the preference name from the json and store it in an array. This array
// will be used later while fetching the preference data.
String[] prefNames = new String[1];
try {
prefNames[0] = jsonPref.getString("name");
} catch (JSONException e) {
mAsserter.ok(false, "Exception in setPreferenceAndWaitForChange", getStackTraceString(e));
}
// Wait for confirmation of the pref change before proceeding with the test.
final int ourRequestID = mPreferenceRequestID--;
final Actions.RepeatedEventExpecter eventExpecter = mActions.expectGeckoEvent("Preferences:Data");
mActions.sendPreferencesGetEvent(ourRequestID, prefNames);
// Wait until we get the correct "Preferences:Data" event
waitForCondition(new Condition() {
final long endTime = SystemClock.elapsedRealtime() + MAX_WAIT_BLOCK_FOR_EVENT_DATA_MS;
@Override
public boolean isSatisfied() {
try {
long timeout = endTime - SystemClock.elapsedRealtime();
if (timeout < 0) {
timeout = 0;
}
JSONObject data = new JSONObject(eventExpecter.blockForEventDataWithTimeout(timeout));
int requestID = data.getInt("requestId");
if (requestID != ourRequestID) {
return false;
}
JSONArray preferences = data.getJSONArray("preferences");
mAsserter.is(preferences.length(), 1, "Expecting preference array to have one element");
JSONObject prefs = (JSONObject) preferences.get(0);
mAsserter.is(prefs.getString("name"), jsonPref.getString("name"),
"Expecting returned preference name to be the same as the set name");
mAsserter.is(prefs.getString("type"), jsonPref.getString("type"),
"Expecting returned preference type to be the same as the set type");
mAsserter.is(prefs.get("value"), jsonPref.get("value"),
"Expecting returned preference value to be the same as the set value");
return true;
} catch(JSONException e) {
mAsserter.ok(false, "Exception in setPreferenceAndWaitForChange", getStackTraceString(e));
// Please the java compiler
return false;
}
}
}, MAX_WAIT_BLOCK_FOR_EVENT_DATA_MS);
eventExpecter.unregisterListener();
}
}

View File

@ -55,23 +55,7 @@ public class testAddonManager extends PixelTest {
jsonPref.put("name", "extensions.getAddons.browseAddons");
jsonPref.put("type", "string");
jsonPref.put("value", getAbsoluteUrl("/robocop/robocop_blank_01.html"));
mActions.sendGeckoEvent("Preferences:Set", jsonPref.toString());
// Wait for confirmation of the pref change before proceeding with the test.
final String[] prefNames = { "extensions.getAddons.browseAddons" };
final int ourRequestId = 0x7357;
Actions.RepeatedEventExpecter eventExpecter = mActions.expectGeckoEvent("Preferences:Data");
mActions.sendPreferencesGetEvent(ourRequestId, prefNames);
JSONObject data = null;
int requestId = -1;
// Wait until we get the correct "Preferences:Data" event
while (requestId != ourRequestId) {
data = new JSONObject(eventExpecter.blockForEventData());
requestId = data.getInt("requestId");
}
eventExpecter.unregisterListener();
setPreferenceAndWaitForChange(jsonPref);
} catch (Exception ex) {
mAsserter.ok(false, "exception in testAddonManager", ex.toString());

View File

@ -31,23 +31,7 @@ public class testAdobeFlash extends PixelTest {
jsonPref.put("name", "plugin.enable");
jsonPref.put("type", "string");
jsonPref.put("value", "1");
mActions.sendGeckoEvent("Preferences:Set", jsonPref.toString());
// Wait for confirmation of the pref change before proceeding with the test.
final String[] prefNames = { "plugin.default.state" };
final int ourRequestId = 0x7358;
Actions.RepeatedEventExpecter eventExpecter = mActions.expectGeckoEvent("Preferences:Data");
mActions.sendPreferencesGetEvent(ourRequestId, prefNames);
JSONObject data = null;
int requestId = -1;
// Wait until we get the correct "Preferences:Data" event
while (requestId != ourRequestId) {
data = new JSONObject(eventExpecter.blockForEventData());
requestId = data.getInt("requestId");
}
eventExpecter.unregisterListener();
setPreferenceAndWaitForChange(jsonPref);
} catch (Exception ex) {
mAsserter.ok(false, "exception in testAdobeFlash", ex.toString());
}

View File

@ -77,14 +77,12 @@ public class testDoorHanger extends BaseTest {
boolean offlineAllowedByDefault = true;
// Save offline-allow-by-default preferences first
final String[] prefNames = { "offline-apps.allow_by_default" };
final int ourRequestId = 0x7357;
final Actions.RepeatedEventExpecter eventExpecter = mActions.expectGeckoEvent("Preferences:Data");
mActions.sendPreferencesGetEvent(ourRequestId, prefNames);
try {
// Save offline-allow-by-default preferences first
final String[] prefNames = { "offline-apps.allow_by_default" };
final int ourRequestId = 0x7357;
Actions.RepeatedEventExpecter eventExpecter = mActions.expectGeckoEvent("Preferences:Data");
mActions.sendPreferencesGetEvent(ourRequestId, prefNames);
JSONObject data = null;
int requestId = -1;
@ -106,7 +104,7 @@ public class testDoorHanger extends BaseTest {
jsonPref.put("name", "offline-apps.allow_by_default");
jsonPref.put("type", "bool");
jsonPref.put("value", false);
mActions.sendGeckoEvent("Preferences:Set", jsonPref.toString());
setPreferenceAndWaitForChange(jsonPref);
} catch (JSONException e) {
mAsserter.ok(false, "exception getting preference", e.toString());
}
@ -134,9 +132,9 @@ public class testDoorHanger extends BaseTest {
// Revert offline setting
JSONObject jsonPref = new JSONObject();
jsonPref.put("name", "offline-apps.allow_by_default");
jsonPref.put("type", "boolean");
jsonPref.put("type", "bool");
jsonPref.put("value", offlineAllowedByDefault);
mActions.sendGeckoEvent("Preferences:Set", jsonPref.toString());
setPreferenceAndWaitForChange(jsonPref);
} catch (JSONException e) {
mAsserter.ok(false, "exception setting preference", e.toString());
}

View File

@ -113,22 +113,7 @@ public class testPasswordEncrypt extends BaseTest {
jsonPref.put("name", "privacy.masterpassword.enabled");
jsonPref.put("type", "string");
jsonPref.put("value", passwd);
mActions.sendGeckoEvent("Preferences:Set", jsonPref.toString());
// Wait for confirmation of the pref change before proceeding with the test.
final String[] prefNames = { "privacy.masterpassword.enabled" };
final int ourRequestId = 0x73577;
Actions.RepeatedEventExpecter eventExpecter = mActions.expectGeckoEvent("Preferences:Data");
mActions.sendPreferencesGetEvent(ourRequestId, prefNames);
JSONObject data = null;
int requestId = -1;
// Wait until we get the correct "Preferences:Data" event
while (requestId != ourRequestId) {
data = new JSONObject(eventExpecter.blockForEventData());
requestId = data.getInt("requestId");
}
setPreferenceAndWaitForChange(jsonPref);
} catch (Exception ex) {
mAsserter.ok(false, "exception in toggleMasterPassword", ex.toString());
}

View File

@ -176,8 +176,18 @@ PromiseWorker.prototype = {
let id = ++this._id;
let message = {fun: fun, args: array, id: id};
this._log("Posting message", message);
try {
this._worker.postMessage(message);
} catch (ex if typeof ex == "number") {
this._log("Could not post message", message, "due to xpcom error", ex);
// handle raw xpcom errors (see eg bug 961317)
return Promise.reject(new Components.Exception("Error in postMessage", ex));
} catch (ex) {
this._log("Could not post message", message, "due to error", ex);
return Promise.reject(ex);
}
this._queue.push({deferred:deferred, closure: closure, id: id});
this._worker.postMessage(message);
this._log("Message posted");
return deferred.promise;
}

View File

@ -121,6 +121,7 @@ this.EXPORTED_SYMBOLS = ["PlacesTransactions"];
*/
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
Components.utils.import("resource://gre/modules/Services.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
"resource://gre/modules/Promise.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Task",
@ -132,6 +133,18 @@ XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
XPCOMUtils.defineLazyModuleGetter(this, "console",
"resource://gre/modules/devtools/Console.jsm");
// Updates commands in the undo group of the active window commands.
// Inactive windows commands will be updated on focus.
function updateCommandsOnActiveWindow() {
// Updating "undo" will cause a group update including "redo".
try {
let win = Services.focus.activeWindow;
if (win)
win.updateCommands("undo");
}
catch(ex) { console.error(ex, "Couldn't update undo commands"); }
}
// The internal object for managing the transactions history.
// The public API is included in PlacesTransactions.
// TODO bug 982099: extending the array "properly" makes it painful to implement
@ -173,6 +186,7 @@ TransactionsHistory.__proto__ = {
}
}
this._undoPosition++;
updateCommandsOnActiveWindow();
},
/**
@ -201,6 +215,7 @@ TransactionsHistory.__proto__ = {
}
}
this._undoPosition--;
updateCommandsOnActiveWindow();
},
/**
@ -222,6 +237,7 @@ TransactionsHistory.__proto__ = {
else {
this[this.undoPosition].unshift(aTransaction);
}
updateCommandsOnActiveWindow();
},
/**
@ -411,7 +427,7 @@ let PlacesTransactions = {
* @note the returned array is a clone of the history entry and is not
* kept in sync with the original entry if it changes.
*/
item: function (aIndex) {
entry: function (aIndex) {
if (!Number.isInteger(aIndex) || aIndex < 0 || aIndex >= this.length)
throw new Error("Invalid index");
@ -425,6 +441,16 @@ let PlacesTransactions = {
* Entries at and past this point are redo entries.
*/
get undoPosition() TransactionsHistory.undoPosition,
/**
* Shortcut for accessing the top undo entry in the transaction history.
*/
get topUndoEntry() TransactionsHistory.topUndoEntry,
/**
* Shortcut for accessing the top redo entry in the transaction history.
*/
get topRedoEntry() TransactionsHistory.topRedoEntry
};
/**

View File

@ -116,18 +116,43 @@ function run_test() {
run_next_test();
}
function ensureUndoState(aEntries = [], aUndoPosition = 0) {
do_check_eq(PT.length, aEntries.length);
do_check_eq(PT.undoPosition, aUndoPosition);
function sanityCheckTransactionHistory() {
do_check_true(PT.undoPosition <= PT.length);
for (let i = 0; i < aEntries.length; i++) {
let testEntry = aEntries[i];
let undoEntry = PT.item(i);
do_check_eq(testEntry.length, undoEntry.length);
for (let j = 0; j < testEntry.length; j++) {
do_check_eq(testEntry[j], undoEntry[j]);
}
let check_entry_throws = f => {
try {
f();
do_throw("PT.entry should throw for invalid input");
} catch(ex) {}
};
check_entry_throws( () => PT.entry(-1) );
check_entry_throws( () => PT.entry({}) );
check_entry_throws( () => PT.entry(PT.length) );
if (PT.undoPosition < PT.length)
do_check_eq(PT.topUndoEntry, PT.entry(PT.undoPosition));
else
do_check_null(PT.topUndoEntry);
if (PT.undoPosition > 0)
do_check_eq(PT.topRedoEntry, PT.entry(PT.undoPosition - 1));
else
do_check_null(PT.topRedoEntry);
}
function ensureUndoState(aExpectedEntries = [], aExpectedUndoPosition = 0) {
// ensureUndoState is called in various places during this test, so it's
// a good places to sanity-check the transaction-history APIs in all
// cases.
sanityCheckTransactionHistory();
do_check_eq(PT.length, aExpectedEntries.length);
do_check_eq(PT.undoPosition, aExpectedUndoPosition);
function checkEqualEntries(aExpectedEntry, aActualEntry) {
do_check_eq(aExpectedEntry.length, aActualEntry.length);
aExpectedEntry.forEach( (t, i) => do_check_eq(t, aActualEntry[i]) );
}
aExpectedEntries.forEach( (e, i) => checkEqualEntries(e, PT.entry(i)) );
}
function ensureItemsAdded(...items) {