diff --git a/browser/devtools/animationinspector/components.js b/browser/devtools/animationinspector/components.js index 57e38613f04..462963c388a 100644 --- a/browser/devtools/animationinspector/components.js +++ b/browser/devtools/animationinspector/components.js @@ -908,6 +908,23 @@ AnimationsTimeline.prototype = { } }, + getAnimationTooltipText: function(state) { + let getTime = time => L10N.getFormatStr("player.timeLabel", + L10N.numberWithDecimals(time / 1000, 2)); + + let title = L10N.getFormatStr("timeline." + state.type + ".nameLabel", + state.name); + let delay = L10N.getStr("player.animationDelayLabel") + " " + + getTime(state.delay); + let duration = L10N.getStr("player.animationDurationLabel") + " " + + getTime(state.duration); + let iterations = L10N.getStr("player.animationIterationCountLabel") + " " + + (state.iterationCount || + L10N.getStr("player.infiniteIterationCountText")); + + return [title, duration, iterations, delay].join("\n"); + }, + drawTimeBlock: function({state}, el) { let width = el.offsetWidth; @@ -940,8 +957,7 @@ AnimationsTimeline.prototype = { parent: iterations, attributes: { "class": "name", - "title": L10N.getFormatStr("timeline." + state.type + ".nameLabel", - state.name) + "title": this.getAnimationTooltipText(state) }, textContent: state.name }); diff --git a/browser/devtools/animationinspector/test/browser.ini b/browser/devtools/animationinspector/test/browser.ini index ce858c966f6..a6e2ade4e27 100644 --- a/browser/devtools/animationinspector/test/browser.ini +++ b/browser/devtools/animationinspector/test/browser.ini @@ -42,6 +42,7 @@ support-files = [browser_animation_timeline_scrubber_moves.js] [browser_animation_timeline_shows_delay.js] [browser_animation_timeline_shows_iterations.js] +[browser_animation_timeline_shows_time_info.js] [browser_animation_timeline_takes_rate_into_account.js] [browser_animation_timeline_ui.js] [browser_animation_toggle_button_resets_on_navigate.js] diff --git a/browser/devtools/animationinspector/test/browser_animation_timeline_shows_time_info.js b/browser/devtools/animationinspector/test/browser_animation_timeline_shows_time_info.js new file mode 100644 index 00000000000..9d6142c7dfc --- /dev/null +++ b/browser/devtools/animationinspector/test/browser_animation_timeline_shows_time_info.js @@ -0,0 +1,29 @@ +/* vim: set ts=2 et sw=2 tw=80: */ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Check that the timeline-based UI displays animations' duration, delay and +// iteration counts in tooltips. + +add_task(function*() { + yield addTab(TEST_URL_ROOT + "doc_simple_animation.html"); + let {panel} = yield openAnimationInspectorNewUI(); + yield waitForAllAnimationTargets(panel); + + info("Getting the animation element from the panel"); + let timelineEl = panel.animationsTimelineComponent.rootWrapperEl; + let timeBlockNameEls = timelineEl.querySelectorAll(".time-block .name"); + + // Verify that each time-block's name element has a tooltip that looks sort of + // ok. We don't need to test the actual content. + for (let el of timeBlockNameEls) { + ok(el.hasAttribute("title"), "The tooltip is defined"); + + let title = el.getAttribute("title"); + ok(title.match(/Delay: [\d.]+s/), "The tooltip shows the delay"); + ok(title.match(/Duration: [\d.]+s/), "The tooltip shows the delay"); + ok(title.match(/Repeats: /), "The tooltip shows the iterations"); + } +}); diff --git a/browser/devtools/performance/test/browser_perf-loading-01.js b/browser/devtools/performance/test/browser_perf-loading-01.js index 5f4ff29531f..205cb20f2d5 100644 --- a/browser/devtools/performance/test/browser_perf-loading-01.js +++ b/browser/devtools/performance/test/browser_perf-loading-01.js @@ -7,6 +7,9 @@ */ let test = Task.async(function*() { + // This test seems to take a long time to cleanup. + requestLongerTimeout(2); + let { target, panel, toolbox } = yield initPerformance(SIMPLE_URL); let { RecordingsView, PerformanceController, PerformanceView, EVENTS, $, L10N } = panel.panelWin; diff --git a/browser/devtools/performance/test/browser_perf-loading-02.js b/browser/devtools/performance/test/browser_perf-loading-02.js index b045058fbc9..bbe94cc9c03 100644 --- a/browser/devtools/performance/test/browser_perf-loading-02.js +++ b/browser/devtools/performance/test/browser_perf-loading-02.js @@ -9,6 +9,9 @@ */ let test = Task.async(function*() { + // This test seems to take a long time to cleanup. + requestLongerTimeout(2); + let { panel } = yield initPerformance(SIMPLE_URL); let { PerformanceController, PerformanceView, RecordingsView, EVENTS, $ } = panel.panelWin; diff --git a/browser/locales/en-US/chrome/browser/devtools/animationinspector.properties b/browser/locales/en-US/chrome/browser/devtools/animationinspector.properties index 15be119ae6b..1704212ee48 100644 --- a/browser/locales/en-US/chrome/browser/devtools/animationinspector.properties +++ b/browser/locales/en-US/chrome/browser/devtools/animationinspector.properties @@ -41,6 +41,12 @@ player.animationIterationCountLabel=Repeats: # player.animationIterationCountLabel string, instead of a number. player.infiniteIterationCount=∞ +# LOCALIZATION NOTE (player.infiniteIterationCountText): +# See player.infiniteIterationCount for a description of what this is. +# Unlike player.infiniteIterationCount, this string isn't used in HTML, but in +# a tooltip. +player.infiniteIterationCountText=∞ + # LOCALIZATION NOTE (player.timeLabel): # This string is displayed in each animation player widget, to indicate either # how long (in seconds) the animation lasts, or what is the animation's current diff --git a/browser/themes/shared/notification-icons.inc.css b/browser/themes/shared/notification-icons.inc.css index 54c55ae707a..6505c744d60 100644 --- a/browser/themes/shared/notification-icons.inc.css +++ b/browser/themes/shared/notification-icons.inc.css @@ -106,11 +106,20 @@ padding-left: 7px; } +/* This changes the direction of the main notification box on the url bar. */ #notification-popup-box:-moz-locale-dir(rtl), +/* This adds a second flip for the notification anchors, as they don't switch direction + for RTL mode. */ .notification-anchor-icon:-moz-locale-dir(rtl) { transform: scaleX(-1); } +/* For the anchor icons in the chat window, we don't have the notification popup box, + so we need to cancel the RTL transform. */ +.notification-anchor-icon.chat-toolbarbutton:-moz-locale-dir(rtl) { + transform: none; +} + .notification-anchor-icon { %ifdef MOZ_WIDGET_GTK list-style-image: url(moz-icon://stock/gtk-dialog-info?size=16); diff --git a/mobile/android/base/home/HomeConfig.java b/mobile/android/base/home/HomeConfig.java index 4676548e17c..db253142b0b 100644 --- a/mobile/android/base/home/HomeConfig.java +++ b/mobile/android/base/home/HomeConfig.java @@ -27,6 +27,7 @@ import android.content.Context; import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; +import android.util.Log; public final class HomeConfig { /** @@ -1218,7 +1219,7 @@ public final class HomeConfig { private void findNewDefault() { // Pick the first panel that is neither disabled nor currently // set as default. - for (PanelConfig panelConfig : mConfigMap.values()) { + for (PanelConfig panelConfig : makeOrderedCopy(false)) { if (!panelConfig.isDefault() && !panelConfig.isDisabled()) { setDefault(panelConfig.getId()); return; diff --git a/mobile/android/base/home/TopSitesPanel.java b/mobile/android/base/home/TopSitesPanel.java index c9a4999cc9a..00672d2840c 100644 --- a/mobile/android/base/home/TopSitesPanel.java +++ b/mobile/android/base/home/TopSitesPanel.java @@ -345,13 +345,17 @@ public class TopSitesPanel extends HomeFragment { return; } + final Context context = view.getContext(); + // Long pressed item was a Top Sites GridView item, handle it. - MenuInflater inflater = new MenuInflater(view.getContext()); + MenuInflater inflater = new MenuInflater(context); inflater.inflate(R.menu.home_contextmenu, menu); // Hide unused menu items. menu.findItem(R.id.home_edit_bookmark).setVisible(false); + menu.findItem(R.id.home_remove).setVisible(RestrictedProfiles.isAllowed(context, Restriction.DISALLOW_CLEAR_HISTORY)); + TopSitesGridContextMenuInfo info = (TopSitesGridContextMenuInfo) menuInfo; menu.setHeaderTitle(info.getDisplayTitle()); @@ -372,9 +376,13 @@ public class TopSitesPanel extends HomeFragment { menu.findItem(R.id.home_share).setVisible(false); } - if (!RestrictedProfiles.isAllowed(view.getContext(), Restriction.DISALLOW_PRIVATE_BROWSING)) { + if (!RestrictedProfiles.isAllowed(context, Restriction.DISALLOW_PRIVATE_BROWSING)) { menu.findItem(R.id.home_open_private_tab).setVisible(false); } + + // We only show these menu items on the reading list panel: + menu.findItem(R.id.mark_read).setVisible(false); + menu.findItem(R.id.mark_unread).setVisible(false); } @Override diff --git a/mobile/android/base/preferences/GeckoPreferences.java b/mobile/android/base/preferences/GeckoPreferences.java index c6c146eaef4..9e936d4c8ed 100644 --- a/mobile/android/base/preferences/GeckoPreferences.java +++ b/mobile/android/base/preferences/GeckoPreferences.java @@ -132,6 +132,7 @@ OnSharedPreferenceChangeListener public static final String PREFS_VOICE_INPUT_ENABLED = NON_PREF_PREFIX + "voice_input_enabled"; public static final String PREFS_QRCODE_ENABLED = NON_PREF_PREFIX + "qrcode_enabled"; private static final String PREFS_DEVTOOLS = NON_PREF_PREFIX + "devtools.enabled"; + private static final String PREFS_DISPLAY = NON_PREF_PREFIX + "display.enabled"; private static final String PREFS_CUSTOMIZE_HOME = NON_PREF_PREFIX + "customize_home"; private static final String PREFS_TRACKING_PROTECTION_PRIVATE_BROWSING = "privacy.trackingprotection.pbmode.enabled"; private static final String PREFS_TRACKING_PROTECTION_LEARN_MORE = NON_PREF_PREFIX + "trackingprotection.learn_more"; @@ -706,12 +707,16 @@ OnSharedPreferenceChangeListener } } if (PREFS_DEVTOOLS.equals(key) && - RestrictedProfiles.isUserRestricted(this)) { + !RestrictedProfiles.isAllowed(this, Restriction.DISALLOW_DEVELOPER_TOOLS)) { + preferences.removePreference(pref); + i--; + continue; + } + if (PREFS_DISPLAY.equals(key) && !RestrictedProfiles.isAllowed(this, Restriction.DISALLOW_DISPLAY_SETTINGS)) { preferences.removePreference(pref); i--; continue; } - if (PREFS_CUSTOMIZE_HOME.equals(key)) { if (!RestrictedProfiles.isAllowed(this, Restriction.DISALLOW_CUSTOMIZE_HOME)) { preferences.removePreference(pref); diff --git a/mobile/android/base/resources/values-v21/themes.xml b/mobile/android/base/resources/values-v21/themes.xml index b278270b0db..d3d2aedcd3e 100644 --- a/mobile/android/base/resources/values-v21/themes.xml +++ b/mobile/android/base/resources/values-v21/themes.xml @@ -23,4 +23,16 @@ + + diff --git a/mobile/android/base/resources/xml-v11/preferences.xml b/mobile/android/base/resources/xml-v11/preferences.xml index 4cfde717290..3497d456924 100644 --- a/mobile/android/base/resources/xml-v11/preferences.xml +++ b/mobile/android/base/resources/xml-v11/preferences.xml @@ -26,7 +26,8 @@ + android:fragment="org.mozilla.gecko.preferences.GeckoPreferenceFragment" + android:key="android.not_a_preference.display.enabled" > diff --git a/mobile/android/base/restrictions/GuestProfileConfiguration.java b/mobile/android/base/restrictions/GuestProfileConfiguration.java index 850fe709ad6..18caf5358a1 100644 --- a/mobile/android/base/restrictions/GuestProfileConfiguration.java +++ b/mobile/android/base/restrictions/GuestProfileConfiguration.java @@ -25,7 +25,8 @@ public class GuestProfileConfiguration implements RestrictionConfiguration { Restriction.DISALLOW_SET_IMAGE, Restriction.DISALLOW_MODIFY_ACCOUNTS, Restriction.DISALLOW_REMOTE_DEBUGGING, - Restriction.DISALLOW_IMPORT_SETTINGS + Restriction.DISALLOW_IMPORT_SETTINGS, + Restriction.DISALLOW_DEVELOPER_TOOLS ); @SuppressWarnings("serial") @@ -38,7 +39,8 @@ public class GuestProfileConfiguration implements RestrictionConfiguration { ); private static final List BANNED_URLS = Arrays.asList( - "about:config" + "about:config", + "about:addons" ); @Override @@ -59,6 +61,7 @@ public class GuestProfileConfiguration implements RestrictionConfiguration { return false; } + url = url.toLowerCase(); for (String banned : BANNED_URLS) { if (url.startsWith(banned)) { return false; diff --git a/mobile/android/base/restrictions/RestrictedProfileConfiguration.java b/mobile/android/base/restrictions/RestrictedProfileConfiguration.java index a75af7d5c39..b23f8a71027 100644 --- a/mobile/android/base/restrictions/RestrictedProfileConfiguration.java +++ b/mobile/android/base/restrictions/RestrictedProfileConfiguration.java @@ -30,7 +30,8 @@ public class RestrictedProfileConfiguration implements RestrictionConfiguration Restriction.DISALLOW_DISPLAY_SETTINGS, Restriction.DISALLOW_CLEAR_HISTORY, Restriction.DISALLOW_MASTER_PASSWORD, - Restriction.DISALLOW_GUEST_BROWSING + Restriction.DISALLOW_GUEST_BROWSING, + Restriction.DISALLOW_DEFAULT_THEME ); private Context context; diff --git a/mobile/android/base/restrictions/Restriction.java b/mobile/android/base/restrictions/Restriction.java index f53c8b3c0e1..c073baad44a 100644 --- a/mobile/android/base/restrictions/Restriction.java +++ b/mobile/android/base/restrictions/Restriction.java @@ -54,8 +54,9 @@ public enum Restriction { DISALLOW_MASTER_PASSWORD(18, "no_master_password", R.string.restriction_disallow_master_password_title), - DISALLOW_GUEST_BROWSING(19, "no_guest_browsing", R.string.restriction_disallow_guest_browsing_title); + DISALLOW_GUEST_BROWSING(19, "no_guest_browsing", R.string.restriction_disallow_guest_browsing_title), + DISALLOW_DEFAULT_THEME(20, "no_default_theme", 0); public final int id; public final String name; diff --git a/mobile/android/base/restrictions/RestrictionProvider.java b/mobile/android/base/restrictions/RestrictionProvider.java index d69427576e3..c21f8477e94 100644 --- a/mobile/android/base/restrictions/RestrictionProvider.java +++ b/mobile/android/base/restrictions/RestrictionProvider.java @@ -58,6 +58,11 @@ public class RestrictionProvider extends BroadcastReceiver { continue; } + if (restriction == Restriction.DISALLOW_DEFAULT_THEME) { + // This restriction is not configurable + continue; + } + RestrictionEntry entry = createRestrictionEntryWithDefaultValue(context, restriction, oldRestrictions.getBoolean(restriction.name, true)); entries.add(entry); diff --git a/mobile/android/chrome/content/browser.js b/mobile/android/chrome/content/browser.js index 7e7b2445c00..215432959fe 100644 --- a/mobile/android/chrome/content/browser.js +++ b/mobile/android/chrome/content/browser.js @@ -3080,7 +3080,10 @@ var LightWeightThemeWebInstaller = { BrowserApp.deck.addEventListener("PreviewBrowserTheme", this, false, true); BrowserApp.deck.addEventListener("ResetBrowserThemePreview", this, false, true); - if (ParentalControls.parentalControlsEnabled && !this._manager.currentTheme) { + if (ParentalControls.parentalControlsEnabled && + !this._manager.currentTheme && + !ParentalControls.isAllowed(ParentalControls.DEFAULT_THEME)) { + // We are using the DEFAULT_THEME restriction to differentiate between restricted profiles & guest mode - Bug 1199596 this._installParentalControlsTheme(); } }, @@ -5562,7 +5565,12 @@ var FormAssistant = { if (this._showValidationMessage(focused)) break; - this._showAutoCompleteSuggestions(focused, function () {}); + let checkResultsClick = hasResults => { + if (!hasResults) { + this._hideFormAssistPopup(); + } + }; + this._showAutoCompleteSuggestions(focused, checkResultsClick); } else { // temporarily hide the form assist popup while we're panning or zooming the page this._hideFormAssistPopup(); diff --git a/toolkit/components/parentalcontrols/nsIParentalControlsService.idl b/toolkit/components/parentalcontrols/nsIParentalControlsService.idl index 0c4f413394a..c0b071db7b0 100644 --- a/toolkit/components/parentalcontrols/nsIParentalControlsService.idl +++ b/toolkit/components/parentalcontrols/nsIParentalControlsService.idl @@ -11,7 +11,7 @@ interface nsIFile; interface nsIInterfaceRequestor; interface nsIArray; -[scriptable, uuid(ed14d186-e902-4d41-86cb-8949fd7b53d7)] +[scriptable, uuid(f9962e65-5369-4346-8c44-84d5319abfc2)] interface nsIParentalControlsService : nsISupports { /** @@ -36,6 +36,7 @@ interface nsIParentalControlsService : nsISupports const short CLEAR_HISTORY = 17; // Clear browsing history const short MASTER_PASSWORD = 18; // Setting master password for logins const short GUEST_BROWSING = 19; // Disallow usage of guest browsing + const short DEFAULT_THEME = 20; // Use default theme or a special parental controls theme /** * @returns true if the current user account has parental controls