This commit is contained in:
Phil Ringnalda 2016-02-20 17:25:14 -08:00
Родитель 9f638a1e8e 693a23497c
Коммит 1a1ec5b8bb
115 изменённых файлов: 4365 добавлений и 3673 удалений

Просмотреть файл

@ -141,16 +141,6 @@ function initResponsiveDesign() {
// Enable touch events // Enable touch events
responsive.enableTouch(); responsive.enableTouch();
// Automatically toggle responsive design mode
let width = 320, height = 480;
// We have to take into account padding and border introduced with the
// device look'n feel:
width += 15*2; // Horizontal padding
width += 1*2; // Vertical border
height += 60; // Top Padding
height += 1; // Top border
responsive.setSize(width, height);
}); });

Просмотреть файл

@ -1359,7 +1359,7 @@ var BookmarkingUI = {
PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase) PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase)
.asyncExecuteLegacyQueries([query], 1, options, { .asyncExecuteLegacyQueries([query], 1, options, {
handleResult: function (aResultSet) { handleResult: function (aResultSet) {
let onItemClick = function (aEvent) { let onItemCommand = function (aEvent) {
let item = aEvent.target; let item = aEvent.target;
openUILink(item.getAttribute("targetURI"), aEvent); openUILink(item.getAttribute("targetURI"), aEvent);
CustomizableUI.hidePanelForNode(item); CustomizableUI.hidePanelForNode(item);
@ -1379,7 +1379,7 @@ var BookmarkingUI = {
item.setAttribute("targetURI", uri); item.setAttribute("targetURI", uri);
item.setAttribute("class", "menuitem-iconic menuitem-with-favicon bookmark-item " + item.setAttribute("class", "menuitem-iconic menuitem-with-favicon bookmark-item " +
extraCSSClass); extraCSSClass);
item.addEventListener("click", onItemClick); item.addEventListener("command", onItemCommand);
if (icon) { if (icon) {
let iconURL = "moz-anno:favicon:" + icon; let iconURL = "moz-anno:favicon:" + icon;
item.setAttribute("image", iconURL); item.setAttribute("image", iconURL);

Просмотреть файл

@ -259,8 +259,6 @@ SocialUI = {
// called on tab/urlbar/location changes and after customization. Update // called on tab/urlbar/location changes and after customization. Update
// anything that is tab specific. // anything that is tab specific.
updateState: function() { updateState: function() {
if (location == "about:customizing")
return;
goSetCommandEnabled("Social:PageShareOrMark", this.canShareOrMarkPage(gBrowser.currentURI)); goSetCommandEnabled("Social:PageShareOrMark", this.canShareOrMarkPage(gBrowser.currentURI));
if (!SocialUI.enabled) if (!SocialUI.enabled)
return; return;

Просмотреть файл

@ -183,9 +183,6 @@ if (AppConstants.MOZ_SAFE_BROWSING) {
"resource://gre/modules/SafeBrowsing.jsm"); "resource://gre/modules/SafeBrowsing.jsm");
} }
XPCOMUtils.defineLazyModuleGetter(this, "gCustomizationTabPreloader",
"resource:///modules/CustomizationTabPreloader.jsm", "CustomizationTabPreloader");
XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils", XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
"resource://gre/modules/PrivateBrowsingUtils.jsm"); "resource://gre/modules/PrivateBrowsingUtils.jsm");
@ -2344,10 +2341,12 @@ function URLBarSetURI(aURI) {
// 2. if remote newtab is enabled and it's the default remote newtab page // 2. if remote newtab is enabled and it's the default remote newtab page
let defaultRemoteURL = gAboutNewTabService.remoteEnabled && let defaultRemoteURL = gAboutNewTabService.remoteEnabled &&
uri.spec === gAboutNewTabService.newTabURL; uri.spec === gAboutNewTabService.newTabURL;
if (gInitialPages.includes(uri.spec) || defaultRemoteURL) if ((gInitialPages.includes(uri.spec) || defaultRemoteURL) &&
value = gBrowser.selectedBrowser.hasContentOpener ? uri.spec : ""; checkEmptyPageOrigin(gBrowser.selectedBrowser, uri)) {
else value = "";
} else {
value = losslessDecodeURI(uri); value = losslessDecodeURI(uri);
}
valid = !isBlankPageURL(uri.spec); valid = !isBlankPageURL(uri.spec);
} }
@ -4327,7 +4326,7 @@ var XULBrowserWindow = {
// Do not update urlbar if there was a subframe navigation // Do not update urlbar if there was a subframe navigation
if (aWebProgress.isTopLevel) { if (aWebProgress.isTopLevel) {
if ((location == "about:blank" && !gBrowser.selectedBrowser.hasContentOpener) || if ((location == "about:blank" && checkEmptyPageOrigin()) ||
location == "") { // Second condition is for new tabs, otherwise location == "") { // Second condition is for new tabs, otherwise
// reload function is enabled until tab is refreshed. // reload function is enabled until tab is refreshed.
this.reloadCommand.setAttribute("disabled", "true"); this.reloadCommand.setAttribute("disabled", "true");
@ -4339,7 +4338,7 @@ var XULBrowserWindow = {
URLBarSetURI(aLocationURI); URLBarSetURI(aLocationURI);
BookmarkingUI.onLocationChange(); BookmarkingUI.onLocationChange();
SocialUI.updateState(location); SocialUI.updateState();
UITour.onLocationChange(location); UITour.onLocationChange(location);
gTabletModePageCounter.inc(); gTabletModePageCounter.inc();
} }
@ -4387,12 +4386,11 @@ var XULBrowserWindow = {
// Try not to instantiate gCustomizeMode as much as possible, // Try not to instantiate gCustomizeMode as much as possible,
// so don't use CustomizeMode.jsm to check for URI or customizing. // so don't use CustomizeMode.jsm to check for URI or customizing.
let customizingURI = "about:customizing"; if (location == "about:blank" &&
if (location == customizingURI) { gBrowser.selectedTab.hasAttribute("customizemode")) {
gCustomizeMode.enter(); gCustomizeMode.enter();
} else if (location != customizingURI && } else if (CustomizationHandler.isEnteringCustomizeMode ||
(CustomizationHandler.isEnteringCustomizeMode || CustomizationHandler.isCustomizing()) {
CustomizationHandler.isCustomizing())) {
gCustomizeMode.exit(); gCustomizeMode.exit();
} }
} }
@ -6390,11 +6388,14 @@ function isTabEmpty(aTab) {
if (aTab.hasAttribute("busy")) if (aTab.hasAttribute("busy"))
return false; return false;
if (aTab.hasAttribute("customizemode"))
return false;
let browser = aTab.linkedBrowser; let browser = aTab.linkedBrowser;
if (!isBlankPageURL(browser.currentURI.spec)) if (!isBlankPageURL(browser.currentURI.spec))
return false; return false;
if (browser.hasContentOpener) if (!checkEmptyPageOrigin(browser))
return false; return false;
if (browser.canGoForward || browser.canGoBack) if (browser.canGoForward || browser.canGoBack)
@ -6403,6 +6404,56 @@ function isTabEmpty(aTab) {
return true; return true;
} }
/**
* Check whether a page can be considered as 'empty', that its URI
* reflects its origin, and that if it's loaded in a tab, that tab
* could be considered 'empty' (e.g. like the result of opening
* a 'blank' new tab).
*
* We have to do more than just check the URI, because especially
* for things like about:blank, it is possible that the opener or
* some other page has control over the contents of the page.
*
* @param browser {Browser}
* The browser whose page we're checking (the selected browser
* in this window if omitted).
* @param uri {nsIURI}
* The URI against which we're checking (the browser's currentURI
* if omitted).
*
* @return false if the page was opened by or is controlled by arbitrary web
* content, unless that content corresponds with the URI.
* true if the page is blank and controlled by a principal matching
* that URI (or the system principal if the principal has no URI)
*/
function checkEmptyPageOrigin(browser = gBrowser.selectedBrowser,
uri = browser.currentURI) {
// If another page opened this page with e.g. window.open, this page might
// be controlled by its opener - return false.
if (browser.hasContentOpener) {
return false;
}
let contentPrincipal = browser.contentPrincipal;
if (gMultiProcessBrowser && browser.isRemoteBrowser &&
!contentPrincipal && uri.spec == "about:blank") {
// Need to specialcase this because of how stopping an about:blank
// load from chrome on e10s causes a permanently null contentPrincipal,
// see bug 1249362.
return true;
}
// Not all principals have URIs...
if (contentPrincipal.URI) {
if (uri.spec == "about:blank" && contentPrincipal.isNullPrincipal) {
return true;
}
return contentPrincipal.URI.equals(uri);
}
// ... so for those that don't have them, enforce that the page has the
// system principal (this matches e.g. on about:home).
let ssm = Services.scriptSecurityManager;
return ssm.isSystemPrincipal(contentPrincipal);
}
function BrowserOpenSyncTabs() { function BrowserOpenSyncTabs() {
if (Services.prefs.getBoolPref("services.sync.syncedTabsUIRefresh")) { if (Services.prefs.getBoolPref("services.sync.syncedTabsUIRefresh")) {
gSyncUI.openSyncedTabsPanel(); gSyncUI.openSyncedTabsPanel();
@ -7292,7 +7343,6 @@ function switchToTabHavingURI(aURI, aOpenNew, aOpenParams={}) {
// window being in private browsing mode: // window being in private browsing mode:
const kPrivateBrowsingWhitelist = new Set([ const kPrivateBrowsingWhitelist = new Set([
"about:addons", "about:addons",
"about:customizing",
]); ]);
let ignoreFragment = aOpenParams.ignoreFragment; let ignoreFragment = aOpenParams.ignoreFragment;

Просмотреть файл

@ -1398,6 +1398,11 @@
crop = "center"; crop = "center";
} else if (aTab.hasAttribute("customizemode")) {
let brandBundle = document.getElementById("bundle_brand");
let brandShortName = brandBundle.getString("brandShortName");
title = gNavigatorBundle.getFormattedString("customizeMode.tabTitle",
[ brandShortName ]);
} else // Still no title? Fall back to our untitled string. } else // Still no title? Fall back to our untitled string.
title = this.mStringBundle.getString("tabs.emptyTabTitle"); title = this.mStringBundle.getString("tabs.emptyTabTitle");
} }
@ -1926,11 +1931,6 @@
b.droppedLinkHandler = handleDroppedLink; b.droppedLinkHandler = handleDroppedLink;
// Swap in a preloaded customize tab, if available.
if (aURI == "about:customizing") {
usingPreloadedContent = gCustomizationTabPreloader.newTab(t);
}
// Dispatch a new tab notification. We do this once we're // Dispatch a new tab notification. We do this once we're
// entirely done, so that things are in a consistent state // entirely done, so that things are in a consistent state
// even if the event listener opens or closes tabs. // even if the event listener opens or closes tabs.
@ -2474,33 +2474,6 @@
</body> </body>
</method> </method>
<method name="swapNewTabWithBrowser">
<parameter name="aNewTab"/>
<parameter name="aBrowser"/>
<body>
<![CDATA[
// The browser must be standalone.
if (aBrowser.getTabBrowser())
throw Cr.NS_ERROR_INVALID_ARG;
// The tab is definitely not loading.
aNewTab.removeAttribute("busy");
if (aNewTab.selected) {
this.mIsBusy = false;
}
this._swapBrowserDocShells(aNewTab, aBrowser);
// Update the new tab's title.
this.setTabTitle(aNewTab);
if (aNewTab.selected) {
this.updateCurrentBrowser(true);
}
]]>
</body>
</method>
<method name="swapBrowsersAndCloseOther"> <method name="swapBrowsersAndCloseOther">
<parameter name="aOurTab"/> <parameter name="aOurTab"/>
<parameter name="aOtherTab"/> <parameter name="aOtherTab"/>

Просмотреть файл

@ -0,0 +1,3 @@
[browser_urlbar_blanking.js]
support-files =
file_blank_but_not_blank.html

Просмотреть файл

@ -0,0 +1,35 @@
"use strict";
add_task(function*() {
for (let page of gInitialPages) {
if (page == "about:newtab") {
// New tab preloading makes this a pain to test, so skip
continue;
}
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, page);
ok(!gURLBar.value, "The URL bar should be empty if we load a plain " + page + " page.");
yield BrowserTestUtils.removeTab(tab);
}
});
add_task(function*() {
const URI = "http://www.example.com/browser/browser/base/content/test/urlbar/file_blank_but_not_blank.html";
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, URI);
is(gURLBar.value, URI, "The URL bar should match the URI");
let browserLoaded = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
ContentTask.spawn(tab.linkedBrowser, null, function() {
content.document.querySelector('a').click();
});
yield browserLoaded;
ok(gURLBar.value.startsWith("javascript"), "The URL bar should have the JS URI");
// When reloading, the javascript: uri we're using will throw an exception.
// That's deliberate, so we need to tell mochitest to ignore it:
SimpleTest.expectUncaughtException(true);
yield ContentTask.spawn(tab.linkedBrowser, null, function*() {
// This is sync, so by the time we return we should have changed the URL bar.
content.location.reload();
});
ok(!!gURLBar.value, "URL bar should not be blank.");
yield BrowserTestUtils.removeTab(tab);
SimpleTest.expectUncaughtException(false);
});

Просмотреть файл

@ -0,0 +1,2 @@
<script>var q = 1;</script>
<a href="javascript:q">Click me</a>

Просмотреть файл

@ -23,6 +23,7 @@ BROWSER_CHROME_MANIFESTS += [
'content/test/popupNotifications/browser.ini', 'content/test/popupNotifications/browser.ini',
'content/test/referrer/browser.ini', 'content/test/referrer/browser.ini',
'content/test/social/browser.ini', 'content/test/social/browser.ini',
'content/test/urlbar/browser.ini',
] ]
DEFINES['MOZ_APP_VERSION'] = CONFIG['MOZ_APP_VERSION'] DEFINES['MOZ_APP_VERSION'] = CONFIG['MOZ_APP_VERSION']

Просмотреть файл

@ -99,8 +99,6 @@ static RedirEntry kRedirMap[] = {
#endif #endif
{ "accounts", "chrome://browser/content/aboutaccounts/aboutaccounts.xhtml", { "accounts", "chrome://browser/content/aboutaccounts/aboutaccounts.xhtml",
nsIAboutModule::ALLOW_SCRIPT }, nsIAboutModule::ALLOW_SCRIPT },
{ "customizing", "chrome://browser/content/customizableui/aboutCustomizing.xul",
nsIAboutModule::ALLOW_SCRIPT },
{ "loopconversation", "chrome://loop/content/panels/conversation.html", { "loopconversation", "chrome://loop/content/panels/conversation.html",
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT | nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::ALLOW_SCRIPT |

Просмотреть файл

@ -107,7 +107,6 @@ static const mozilla::Module::ContractIDEntry kBrowserContracts[] = {
#ifdef MOZ_SERVICES_HEALTHREPORT #ifdef MOZ_SERVICES_HEALTHREPORT
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "healthreport", &kNS_BROWSER_ABOUT_REDIRECTOR_CID }, { NS_ABOUT_MODULE_CONTRACTID_PREFIX "healthreport", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
#endif #endif
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "customizing", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "looppanel", &kNS_BROWSER_ABOUT_REDIRECTOR_CID }, { NS_ABOUT_MODULE_CONTRACTID_PREFIX "looppanel", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "loopconversation", &kNS_BROWSER_ABOUT_REDIRECTOR_CID }, { NS_ABOUT_MODULE_CONTRACTID_PREFIX "loopconversation", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "reader", &kNS_BROWSER_ABOUT_REDIRECTOR_CID }, { NS_ABOUT_MODULE_CONTRACTID_PREFIX "reader", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },

Просмотреть файл

@ -203,7 +203,7 @@ const CustomizableWidgets = [
PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase) PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase)
.asyncExecuteLegacyQueries([query], 1, options, { .asyncExecuteLegacyQueries([query], 1, options, {
handleResult: function (aResultSet) { handleResult: function (aResultSet) {
let onItemClick = function (aEvent) { let onItemCommand = function (aEvent) {
let item = aEvent.target; let item = aEvent.target;
win.openUILink(item.getAttribute("targetURI"), aEvent); win.openUILink(item.getAttribute("targetURI"), aEvent);
CustomizableUI.hidePanelForNode(item); CustomizableUI.hidePanelForNode(item);
@ -219,7 +219,7 @@ const CustomizableWidgets = [
item.setAttribute("label", title || uri); item.setAttribute("label", title || uri);
item.setAttribute("targetURI", uri); item.setAttribute("targetURI", uri);
item.setAttribute("class", "subviewbutton"); item.setAttribute("class", "subviewbutton");
item.addEventListener("click", onItemClick); item.addEventListener("command", onItemCommand);
if (icon) { if (icon) {
let iconURL = "moz-anno:favicon:" + icon; let iconURL = "moz-anno:favicon:" + icon;
item.setAttribute("image", iconURL); item.setAttribute("image", iconURL);

Просмотреть файл

@ -11,7 +11,6 @@ const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
const kPrefCustomizationDebug = "browser.uiCustomization.debug"; const kPrefCustomizationDebug = "browser.uiCustomization.debug";
const kPrefCustomizationAnimation = "browser.uiCustomization.disableAnimation"; const kPrefCustomizationAnimation = "browser.uiCustomization.disableAnimation";
const kPaletteId = "customization-palette"; const kPaletteId = "customization-palette";
const kAboutURI = "about:customizing";
const kDragDataTypePrefix = "text/toolbarwrapper-id/"; const kDragDataTypePrefix = "text/toolbarwrapper-id/";
const kPlaceholderClass = "panel-customization-placeholder"; const kPlaceholderClass = "panel-customization-placeholder";
const kSkipSourceNodePref = "browser.uiCustomization.skipSourceNodeCheck"; const kSkipSourceNodePref = "browser.uiCustomization.skipSourceNodeCheck";
@ -36,6 +35,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "BrowserUITelemetry",
"resource:///modules/BrowserUITelemetry.jsm"); "resource:///modules/BrowserUITelemetry.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "LightweightThemeManager", XPCOMUtils.defineLazyModuleGetter(this, "LightweightThemeManager",
"resource://gre/modules/LightweightThemeManager.jsm"); "resource://gre/modules/LightweightThemeManager.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "SessionStore",
"resource:///modules/sessionstore/SessionStore.jsm");
let gDebug; let gDebug;
XPCOMUtils.defineLazyGetter(this, "log", () => { XPCOMUtils.defineLazyGetter(this, "log", () => {
@ -56,6 +57,23 @@ var gDisableAnimation = null;
var gDraggingInToolbars; var gDraggingInToolbars;
var gTab;
function closeGlobalTab() {
let win = gTab.ownerGlobal;
if (win.gBrowser.browsers.length == 1) {
win.BrowserOpenTab();
}
win.gBrowser.removeTab(gTab);
}
function unregisterGlobalTab() {
gTab.removeEventListener("TabClose", unregisterGlobalTab);
gTab.ownerGlobal.removeEventListener("unload", unregisterGlobalTab);
gTab.removeAttribute("customizemode");
gTab = null;
}
function CustomizeMode(aWindow) { function CustomizeMode(aWindow) {
if (gDisableAnimation === null) { if (gDisableAnimation === null) {
gDisableAnimation = Services.prefs.getPrefType(kPrefCustomizationAnimation) == Ci.nsIPrefBranch.PREF_BOOL && gDisableAnimation = Services.prefs.getPrefType(kPrefCustomizationAnimation) == Ci.nsIPrefBranch.PREF_BOOL &&
@ -140,6 +158,36 @@ CustomizeMode.prototype = {
lwthemeIcon.style.backgroundImage = "url(" + imageURL + ")"; lwthemeIcon.style.backgroundImage = "url(" + imageURL + ")";
}, },
setTab: function(aTab) {
if (gTab == aTab) {
return;
}
if (gTab) {
closeGlobalTab();
}
gTab = aTab;
gTab.setAttribute("customizemode", "true");
SessionStore.persistTabAttribute("customizemode");
gTab.linkedBrowser.stop();
let win = gTab.ownerGlobal;
win.gBrowser.setTabTitle(gTab);
win.gBrowser.setIcon(gTab,
"chrome://browser/skin/customizableui/customizeFavicon.ico");
gTab.addEventListener("TabClose", unregisterGlobalTab);
win.addEventListener("unload", unregisterGlobalTab);
if (gTab.selected) {
win.gCustomizeMode.enter();
}
},
enter: function() { enter: function() {
this._wantToBeInCustomizeMode = true; this._wantToBeInCustomizeMode = true;
@ -154,13 +202,18 @@ CustomizeMode.prototype = {
return; return;
} }
if (!gTab) {
// We don't need to switch to kAboutURI, or open a new tab at this.setTab(this.browser.loadOneTab("about:blank",
// kAboutURI if we're already on it. { inBackground: false,
if (this.browser.selectedBrowser.currentURI.spec != kAboutURI) { forceNotRemote: true,
this.window.switchToTabHavingURI(kAboutURI, true, { skipAnimation: true }));
skipTabAnimation: true, return;
}); }
if (!gTab.selected) {
gTab.ownerGlobal.gBrowser.selectedTab = gTab;
}
gTab.ownerGlobal.focus();
if (gTab.ownerDocument != this.document) {
return; return;
} }
@ -313,10 +366,6 @@ CustomizeMode.prototype = {
delete this._enableOutlinesTimeout; delete this._enableOutlinesTimeout;
}, 0); }, 0);
// It's possible that we didn't enter customize mode via the menu panel,
// meaning we didn't kick off about:customizing preloading. If that's
// the case, let's kick it off for the next time we load this mode.
window.gCustomizationTabPreloader.ensurePreloading();
if (!this._wantToBeInCustomizeMode) { if (!this._wantToBeInCustomizeMode) {
this.exit(); this.exit();
} }
@ -402,31 +451,14 @@ CustomizeMode.prototype = {
Services.obs.removeObserver(this, "lightweight-theme-window-updated", false); Services.obs.removeObserver(this, "lightweight-theme-window-updated", false);
let browser = document.getElementById("browser"); if (this.browser.selectedTab == gTab) {
if (this.browser.selectedBrowser.currentURI.spec == kAboutURI) { if (gTab.linkedBrowser.currentURI.spec == "about:blank") {
let custBrowser = this.browser.selectedBrowser; closeGlobalTab();
if (custBrowser.canGoBack) {
// If there's history to this tab, just go back.
// Note that this throws an exception if the previous document has a
// problematic URL (e.g. about:idontexist)
try {
custBrowser.goBack();
} catch (ex) {
log.error(ex);
}
} else { } else {
// If we can't go back, we're removing the about:customization tab. unregisterGlobalTab();
// We only do this if we're the top window for this window (so not
// a dialog window, for example).
if (window.getTopWin(true) == window) {
let customizationTab = this.browser.selectedTab;
if (this.browser.browsers.length == 1) {
window.BrowserOpenTab();
}
this.browser.removeTab(customizationTab);
}
} }
} }
let browser = document.getElementById("browser");
browser.parentNode.selectedPanel = browser; browser.parentNode.selectedPanel = browser;
let customizer = document.getElementById("customization-container"); let customizer = document.getElementById("customization-container");
customizer.hidden = true; customizer.hidden = true;

Просмотреть файл

@ -1,22 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- 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/. -->
<!DOCTYPE window [
<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
%brandDTD;
<!ENTITY % browserDTD SYSTEM "chrome://browser/locale/browser.dtd">
%browserDTD;
]>
<window id="aboutCustomizingWindow"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:html="http://www.w3.org/1999/xhtml"
title="&customizeMode.tabTitle;">
<html:head>
<html:link rel="icon" type="image/x-icon"
href="chrome://browser/skin/customizableui/customizeFavicon.ico"/>
</html:head>
</window>

Просмотреть файл

@ -3,7 +3,6 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/. # file, You can obtain one at http://mozilla.org/MPL/2.0/.
browser.jar: browser.jar:
content/browser/customizableui/aboutCustomizing.xul
content/browser/customizableui/panelUI.css content/browser/customizableui/panelUI.css
content/browser/customizableui/panelUI.js content/browser/customizableui/panelUI.js
content/browser/customizableui/panelUI.xml content/browser/customizableui/panelUI.xml

Просмотреть файл

@ -157,10 +157,6 @@ const PanelUI = {
this.panel.addEventListener("popupshown", function onPopupShown() { this.panel.addEventListener("popupshown", function onPopupShown() {
this.removeEventListener("popupshown", onPopupShown); this.removeEventListener("popupshown", onPopupShown);
// As an optimization for the customize mode transition, we preload
// about:customizing in the background once the menu panel is first
// shown.
gCustomizationTabPreloader.ensurePreloading();
deferred.resolve(); deferred.resolve();
}); });

Просмотреть файл

@ -25,7 +25,6 @@ skip-if = os == "mac"
[browser_886323_buildArea_removable_nodes.js] [browser_886323_buildArea_removable_nodes.js]
[browser_887438_currentset_shim.js] [browser_887438_currentset_shim.js]
[browser_888817_currentset_updating.js] [browser_888817_currentset_updating.js]
[browser_889120_customize_tab_merging.js]
[browser_890140_orphaned_placeholders.js] [browser_890140_orphaned_placeholders.js]
[browser_890262_destroyWidget_after_add_to_panel.js] [browser_890262_destroyWidget_after_add_to_panel.js]
[browser_892955_isWidgetRemovable_for_removed_widgets.js] [browser_892955_isWidgetRemovable_for_removed_widgets.js]

Просмотреть файл

@ -1,44 +0,0 @@
/* 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/. */
"use strict";
const kTestToolbarId = "test-empty-drag";
// Attempting to switch quickly from one tab to another to see whether the state changes
// correctly.
add_task(function* CheckBasicCustomizeMode() {
yield startCustomizing();
ok(CustomizationHandler.isCustomizing(), "We should be in customize mode");
yield endCustomizing();
ok(!CustomizationHandler.isCustomizing(), "We should not be in customize mode");
});
add_task(function* CheckQuickCustomizeModeSwitch() {
let tab1 = gBrowser.addTab("about:newtab");
gBrowser.selectedTab = tab1;
let tab2 = gBrowser.addTab("about:customizing");
let tab3 = gBrowser.addTab("about:newtab");
gBrowser.selectedTab = tab2;
try {
yield waitForCondition(() => CustomizationHandler.isEnteringCustomizeMode);
} catch (ex) {
Cu.reportError(ex);
}
ok(CustomizationHandler.isEnteringCustomizeMode, "Should be entering customize mode");
gBrowser.selectedTab = tab3;
try {
yield waitForCondition(() => !CustomizationHandler.isEnteringCustomizeMode && !CustomizationHandler.isCustomizing());
} catch (ex) {
Cu.reportError(ex);
}
ok(!CustomizationHandler.isCustomizing(), "Should not be entering customize mode");
gBrowser.removeTab(tab1);
gBrowser.removeTab(tab2);
gBrowser.removeTab(tab3);
});
add_task(function* asyncCleanup() {
yield endCustomizing();
});

Просмотреть файл

@ -199,7 +199,7 @@ function endCustomizing(aWindow=window) {
newTabBrowser.stop(); newTabBrowser.stop();
// If we stop early enough, this might actually be about:blank. // If we stop early enough, this might actually be about:blank.
if (newTabBrowser.contentDocument.location.href == "about:blank") { if (newTabBrowser.currentURI.spec == "about:blank") {
return null; return null;
} }
@ -209,7 +209,7 @@ function endCustomizing(aWindow=window) {
deferredLoadNewTab.resolve(); deferredLoadNewTab.resolve();
} }
newTabBrowser.addEventListener("load", onNewTabLoaded, true); newTabBrowser.addEventListener("load", onNewTabLoaded, true);
newTabBrowser.contentDocument.location.replace("about:blank"); newTabBrowser.loadURI("about:blank");
return deferredLoadNewTab.promise; return deferredLoadNewTab.promise;
}); });
} }

Просмотреть файл

@ -70,6 +70,12 @@ DistributionCustomizer.prototype = {
return this._locale; return this._locale;
}, },
get _language() {
let language = this._locale.split("-")[0];
this.__defineGetter__("_language", () => language);
return this._language;
},
get _prefSvc() { get _prefSvc() {
let svc = Cc["@mozilla.org/preferences-service;1"]. let svc = Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefService); getService(Ci.nsIPrefService);
@ -112,6 +118,8 @@ DistributionCustomizer.prototype = {
if (keys.indexOf(key + "." + this._locale) >= 0) { if (keys.indexOf(key + "." + this._locale) >= 0) {
key += "." + this._locale; key += "." + this._locale;
} else if (keys.indexOf(key + "." + this._language) >= 0) {
key += "." + this._language;
} }
if (!items[itemIndex]) if (!items[itemIndex])
@ -323,6 +331,8 @@ DistributionCustomizer.prototype = {
try { try {
if (globalPrefs["about." + this._locale]) { if (globalPrefs["about." + this._locale]) {
partnerAbout.data = this._ini.getString("Global", "about." + this._locale); partnerAbout.data = this._ini.getString("Global", "about." + this._locale);
} else if (globalPrefs["about." + this._language]) {
partnerAbout.data = this._ini.getString("Global", "about." + this._language);
} else { } else {
partnerAbout.data = this._ini.getString("Global", "about"); partnerAbout.data = this._ini.getString("Global", "about");
} }
@ -367,6 +377,17 @@ DistributionCustomizer.prototype = {
try { try {
let value = eval(this._ini.getString("LocalizablePreferences", key)); let value = eval(this._ini.getString("LocalizablePreferences", key));
value = value.replace(/%LOCALE%/g, this._locale); value = value.replace(/%LOCALE%/g, this._locale);
value = value.replace(/%LANGUAGE%/g, this._language);
localizedStr.data = "data:text/plain," + key + "=" + value;
defaults.setComplexValue(key, Ci.nsIPrefLocalizedString, localizedStr);
} catch (e) { /* ignore bad prefs and move on */ }
}
}
if (sections["LocalizablePreferences-" + this._language]) {
for (let key of enumerate(this._ini.getKeys("LocalizablePreferences-" + this._language))) {
try {
let value = eval(this._ini.getString("LocalizablePreferences-" + this._language, key));
localizedStr.data = "data:text/plain," + key + "=" + value; localizedStr.data = "data:text/plain," + key + "=" + value;
defaults.setComplexValue(key, Ci.nsIPrefLocalizedString, localizedStr); defaults.setComplexValue(key, Ci.nsIPrefLocalizedString, localizedStr);
} catch (e) { /* ignore bad prefs and move on */ } } catch (e) { /* ignore bad prefs and move on */ }

Просмотреть файл

@ -632,7 +632,7 @@ global.WindowManager = {
convert(extension, window, getInfo) { convert(extension, window, getInfo) {
let result = { let result = {
id: this.getId(window), id: this.getId(window),
focused: window == WindowManager.topWindow, focused: window.document.hasFocus(),
top: window.screenY, top: window.screenY,
left: window.screenX, left: window.screenX,
width: window.outerWidth, width: window.outerWidth,

Просмотреть файл

@ -58,9 +58,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "WebappManager",
XPCOMUtils.defineLazyModuleGetter(this, "PageThumbs", XPCOMUtils.defineLazyModuleGetter(this, "PageThumbs",
"resource://gre/modules/PageThumbs.jsm"); "resource://gre/modules/PageThumbs.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "CustomizationTabPreloader",
"resource:///modules/CustomizationTabPreloader.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PdfJs", XPCOMUtils.defineLazyModuleGetter(this, "PdfJs",
"resource://pdf.js/PdfJs.jsm"); "resource://pdf.js/PdfJs.jsm");
@ -1072,7 +1069,6 @@ BrowserGlue.prototype = {
SelfSupportBackend.uninit(); SelfSupportBackend.uninit();
CustomizationTabPreloader.uninit();
WebappManager.uninit(); WebappManager.uninit();
NewTabPrefsProvider.prefs.uninit(); NewTabPrefsProvider.prefs.uninit();
@ -1812,10 +1808,16 @@ BrowserGlue.prototype = {
_migrateUI: function BG__migrateUI() { _migrateUI: function BG__migrateUI() {
const UI_VERSION = 36; const UI_VERSION = 36;
const BROWSER_DOCURL = "chrome://browser/content/browser.xul"; const BROWSER_DOCURL = "chrome://browser/content/browser.xul";
let currentUIVersion = 0;
try { let currentUIVersion;
if (Services.prefs.prefHasUserValue("browser.migration.version")) {
currentUIVersion = Services.prefs.getIntPref("browser.migration.version"); currentUIVersion = Services.prefs.getIntPref("browser.migration.version");
} catch(ex) {} } else {
// This is a new profile, nothing to migrate.
Services.prefs.setIntPref("browser.migration.version", UI_VERSION);
return;
}
if (currentUIVersion >= UI_VERSION) if (currentUIVersion >= UI_VERSION)
return; return;

Просмотреть файл

@ -7,6 +7,10 @@ Components.utils.import("resource://gre/modules/FileUtils.jsm");
Components.utils.import("resource://gre/modules/Task.jsm"); Components.utils.import("resource://gre/modules/Task.jsm");
Components.utils.import("resource:///modules/ShellService.jsm"); Components.utils.import("resource:///modules/ShellService.jsm");
Components.utils.import("resource:///modules/TransientPrefs.jsm"); Components.utils.import("resource:///modules/TransientPrefs.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "OS",
"resource://gre/modules/osfile.jsm");
#ifdef E10S_TESTING_ONLY #ifdef E10S_TESTING_ONLY
XPCOMUtils.defineLazyModuleGetter(this, "UpdateUtils", XPCOMUtils.defineLazyModuleGetter(this, "UpdateUtils",
"resource://gre/modules/UpdateUtils.jsm"); "resource://gre/modules/UpdateUtils.jsm");
@ -101,7 +105,6 @@ var gMainPane = {
#endif #endif
#ifdef MOZ_DEV_EDITION #ifdef MOZ_DEV_EDITION
Cu.import("resource://gre/modules/osfile.jsm");
let uAppData = OS.Constants.Path.userApplicationDataDir; let uAppData = OS.Constants.Path.userApplicationDataDir;
let ignoreSeparateProfile = OS.Path.join(uAppData, "ignore-dev-edition-profile"); let ignoreSeparateProfile = OS.Path.join(uAppData, "ignore-dev-edition-profile");
@ -185,6 +188,16 @@ var gMainPane = {
Cu.reportError("Failed to toggle separate profile mode: " + error); Cu.reportError("Failed to toggle separate profile mode: " + error);
} }
} }
function createOrRemoveSpecialDevEditionFile(onSuccess) {
let uAppData = OS.Constants.Path.userApplicationDataDir;
let ignoreSeparateProfile = OS.Path.join(uAppData, "ignore-dev-edition-profile");
if (separateProfileModeCheckbox.checked) {
OS.File.remove(ignoreSeparateProfile).then(onSuccess, revertCheckbox);
} else {
OS.File.writeAtomic(ignoreSeparateProfile, new Uint8Array()).then(onSuccess, revertCheckbox);
}
}
const Cc = Components.classes, Ci = Components.interfaces; const Cc = Components.classes, Ci = Components.interfaces;
let separateProfileModeCheckbox = document.getElementById("separateProfileMode"); let separateProfileModeCheckbox = document.getElementById("separateProfileMode");
@ -194,8 +207,25 @@ var gMainPane = {
"featureEnableRequiresRestart" : "featureDisableRequiresRestart", "featureEnableRequiresRestart" : "featureDisableRequiresRestart",
[brandName]); [brandName]);
let title = bundle.getFormattedString("shouldRestartTitle", [brandName]); let title = bundle.getFormattedString("shouldRestartTitle", [brandName]);
let shouldProceed = Services.prompt.confirm(window, title, msg) let check = {value: false};
if (shouldProceed) { let prompts = Services.prompt;
let flags = prompts.BUTTON_POS_0 * prompts.BUTTON_TITLE_IS_STRING +
prompts.BUTTON_POS_1 * prompts.BUTTON_TITLE_CANCEL +
prompts.BUTTON_POS_2 * prompts.BUTTON_TITLE_IS_STRING;
let button0Title = bundle.getString("restartNowButton");
let button2Title = bundle.getString("restartLaterButton");
let button_index = prompts.confirmEx(window, title, msg, flags,
button0Title, null, button2Title, null, check)
let RESTART_NOW_BUTTON_INDEX = 0;
let CANCEL_BUTTON_INDEX = 1;
let RESTART_LATER_BUTTON_INDEX = 2;
switch (button_index) {
case CANCEL_BUTTON_INDEX:
revertCheckbox();
return;
case RESTART_NOW_BUTTON_INDEX:
let shouldProceed = false;
let cancelQuit = Cc["@mozilla.org/supports-PRBool;1"] let cancelQuit = Cc["@mozilla.org/supports-PRBool;1"]
.createInstance(Ci.nsISupportsPRBool); .createInstance(Ci.nsISupportsPRBool);
Services.obs.notifyObservers(cancelQuit, "quit-application-requested", Services.obs.notifyObservers(cancelQuit, "quit-application-requested",
@ -203,21 +233,17 @@ var gMainPane = {
shouldProceed = !cancelQuit.data; shouldProceed = !cancelQuit.data;
if (shouldProceed) { if (shouldProceed) {
Cu.import("resource://gre/modules/osfile.jsm"); createOrRemoveSpecialDevEditionFile(quitApp);
let uAppData = OS.Constants.Path.userApplicationDataDir;
let ignoreSeparateProfile = OS.Path.join(uAppData, "ignore-dev-edition-profile");
if (separateProfileModeCheckbox.checked) {
OS.File.remove(ignoreSeparateProfile).then(quitApp, revertCheckbox);
} else {
OS.File.writeAtomic(ignoreSeparateProfile, new Uint8Array()).then(quitApp, revertCheckbox);
}
return; return;
} }
}
// Revert the checkbox in case we didn't quit // Revert the checkbox in case we didn't quit
revertCheckbox(); revertCheckbox();
return;
case RESTART_LATER_BUTTON_INDEX:
createOrRemoveSpecialDevEditionFile();
return;
}
}, },
onGetStarted: function (aEvent) { onGetStarted: function (aEvent) {

Просмотреть файл

@ -425,19 +425,6 @@ var gSyncPane = {
} }
}, },
// Called whenever one of the sync engine preferences is changed.
onPreferenceChanged: function() {
let prefElts = document.querySelectorAll("#syncEnginePrefs > preference");
let syncEnabled = false;
for (let elt of prefElts) {
if (elt.name.startsWith("services.sync.") && elt.value) {
syncEnabled = true;
break;
}
}
Services.prefs.setBoolPref("services.sync.enabled", syncEnabled);
},
startOver: function (showDialog) { startOver: function (showDialog) {
if (showDialog) { if (showDialog) {
let flags = Services.prompt.BUTTON_POS_0 * Services.prompt.BUTTON_TITLE_IS_STRING + let flags = Services.prompt.BUTTON_POS_0 * Services.prompt.BUTTON_TITLE_IS_STRING +

Просмотреть файл

@ -4,8 +4,7 @@
<!-- Sync panel --> <!-- Sync panel -->
<preferences id="syncEnginePrefs" hidden="true" data-category="paneSync" <preferences id="syncEnginePrefs" hidden="true" data-category="paneSync">
onchange="gSyncPane.onPreferenceChanged();">
<preference id="engine.addons" <preference id="engine.addons"
name="services.sync.engine.addons" name="services.sync.engine.addons"
type="bool"/> type="bool"/>

Просмотреть файл

@ -801,6 +801,8 @@ var SessionStoreInternal = {
tab.label = activePageData.url; tab.label = activePageData.url;
tab.crop = "center"; tab.crop = "center";
} }
} else if (tab.hasAttribute("customizemode")) {
win.gCustomizeMode.setTab(tab);
} }
// Restore the tab icon. // Restore the tab icon.
@ -3299,6 +3301,10 @@ var SessionStoreInternal = {
* optional load arguments used for loadURI() * optional load arguments used for loadURI()
*/ */
restoreTabContent: function (aTab, aLoadArguments = null) { restoreTabContent: function (aTab, aLoadArguments = null) {
if (aTab.hasAttribute("customizemode")) {
return;
}
let browser = aTab.linkedBrowser; let browser = aTab.linkedBrowser;
let window = aTab.ownerDocument.defaultView; let window = aTab.ownerDocument.defaultView;
let tabbrowser = window.gBrowser; let tabbrowser = window.gBrowser;

Просмотреть файл

@ -6,50 +6,138 @@
this.EXPORTED_SYMBOLS = ["LanguageDetector"]; this.EXPORTED_SYMBOLS = ["LanguageDetector"];
Components.utils.import("resource://gre/modules/Timer.jsm");
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Promise", // Since Emscripten can handle heap growth, but not heap shrinkage, we
"resource://gre/modules/Promise.jsm"); // need to refresh the worker after we've processed a particularly large
// string in order to prevent unnecessary resident memory growth.
//
// These values define the cut-off string length and the idle timeout
// (in milliseconds) before destroying a worker. Once a string of the
// maximum size has been processed, the worker is marked for
// destruction, and is terminated as soon as it has been idle for the
// given timeout.
//
// 1.5MB. This is the approximate string length that forces heap growth
// for a 2MB heap.
var LARGE_STRING = 1.5 * 1024 * 1024;
var IDLE_TIMEOUT = 10 * 1000;
const WORKER_URL = "resource:///modules/translation/cld-worker.js"; const WORKER_URL = "resource:///modules/translation/cld-worker.js";
var detectionQueue = []; var workerManager = {
detectionQueue: [],
var workerReady = false; detectLanguage(aParams) {
var pendingStrings = []; return this.workerReady.then(worker => {
return new Promise(resolve => {
XPCOMUtils.defineLazyGetter(this, "worker", () => { this.detectionQueue.push({resolve});
let worker = new Worker(WORKER_URL); worker.postMessage(aParams);
worker.onmessage = function(aMsg) {
if (aMsg.data == "ready") {
workerReady = true;
for (let string of pendingStrings)
worker.postMessage(string);
pendingStrings = [];
}
else
detectionQueue.shift().resolve(aMsg.data);
}
return worker;
}); });
}).then(result => {
// We have our asynchronous result from the worker.
//
// Determine if our input was large enough to trigger heap growth,
// or if we're already waiting to destroy the worker when it's
// idle. If so, schedule termination after the idle timeout.
if (aParams.text.length >= LARGE_STRING || this._idleTimeout != null)
this.flushWorker();
return result;
})
},
_worker: null,
_workerReadyPromise: null,
get workerReady() {
if (!this._workerReadyPromise)
this._workerReadyPromise = new Promise(resolve => {
let worker = new Worker(WORKER_URL);
worker.onmessage = (aMsg) => {
if (aMsg.data == "ready")
resolve(worker);
else
this.detectionQueue.shift().resolve(aMsg.data);
};
this._worker = worker;
});
return this._workerReadyPromise;
},
// Holds the ID of the current pending idle cleanup setTimeout.
_idleTimeout: null,
// Schedule the current worker to be terminated after the idle timeout.
flushWorker() {
if (this._idleTimeout != null)
clearTimeout(this._idleTimeout);
this._idleTimeout = setTimeout(this._flushWorker.bind(this), IDLE_TIMEOUT);
},
// Immediately terminate the worker, as long as there no pending
// results. Otherwise, reschedule termination until after the next
// idle timeout.
_flushWorker() {
if (this.detectionQueue.length)
this.flushWorker();
else {
if (this._worker)
this._worker.terminate();
this._worker = null;
this._workerReadyPromise = null;
this._idleTimeout = null;
}
},
};
this.LanguageDetector = { this.LanguageDetector = {
/** /**
* Detect the language of a given string * Detect the language of a given string.
* *
* @returns {Promise} * The argument may be either a string containing the text to analyze,
* or an object with the following properties:
*
* - 'text' The text to analyze.
*
* - 'isHTML' (optional) A boolean, indicating whether the text
* should be analyzed as HTML rather than plain text.
*
* - 'language' (optional) A string indicating the expected language.
* For text extracted from HTTP documents, this is expected to
* come from the Content-Language header.
*
* - 'tld' (optional) A string indicating the top-level domain of the
* document the text was extracted from.
*
* - 'encoding' (optional) A string describing the encoding of the
* document the string was extracted from. Note that, regardless
* of the value of this property, the 'text' property must be a
* UTF-16 JavaScript string.
*
* @returns {Promise<Object>}
* @resolves When detection is finished, with a object containing * @resolves When detection is finished, with a object containing
* these fields: * these fields:
* - 'language' (string with a language code) * - 'language' (string with a language code)
* - 'confident' (boolean). * - 'confident' (boolean) Whether the detector is confident of the
* result.
* - 'languages' (array) An array of up to three elements, containing
* the most prevalent languages detected. It contains a
* 'languageCode' property, containing the ISO language code of
* the language, and a 'percent' property, describing the
* approximate percentage of the input which is in that language.
* For text of an unknown language, the result may contain an
* entry with the languge code 'un', indicating the percent of
* the text which is unknown.
*/ */
detectLanguage: function(aString) { detectLanguage: function(aParams) {
let deferred = Promise.defer(); if (typeof aParams == "string")
detectionQueue.push(deferred); aParams = { text: aParams };
if (worker && workerReady)
worker.postMessage(aString); return workerManager.detectLanguage(aParams);
else },
pendingStrings.push(aString);
return deferred.promise;
}
}; };

Просмотреть файл

@ -1,8 +1,29 @@
# This Source Code Form is subject to the terms of the Mozilla Public # 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, # 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/. */ # You can obtain one at http://mozilla.org/MPL/2.0/.
CC=emcc PYTHON2 ?= python2
EMSCRIPTEN_ROOT := $(shell if which emcc >/dev/null 2>&1; \
then dirname `which emcc`; \
else echo /usr/lib/emscripten; \
fi)
EMCC ?= $(EMSCRIPTEN_ROOT)/emcc
WEBIDL ?= $(PYTHON2) $(EMSCRIPTEN_ROOT)/tools/webidl_binder.py
# A 2MB heap is to analyze most web pages. For the outliers, we need to either
# allow for heap growth, or allocate an unreasonable amount of memory at the
# outset.
# Unfortunately, once the heap has been enlarged, there is no shrinking, so
# analyzing one 20MB web page gives us a 30-40MB heap for the life of the
# worker.
FLAGS=-s -O3 -s INLINING_LIMIT=1 -s NO_FILESYSTEM=1 -s NO_EXIT_RUNTIME=1 -s INVOKE_RUN=0 \
-s TOTAL_STACK=8192 -s TOTAL_MEMORY=2097152 -s ALLOW_MEMORY_GROWTH=1 \
--llvm-lto 1 --memory-init-file 1 --closure 1
export EMCC_CLOSURE_ARGS = --language_in ECMASCRIPT6 --language_out ES5_STRICT
SOURCES= \ SOURCES= \
internal/cldutil.cc \ internal/cldutil.cc \
@ -32,13 +53,22 @@ SOURCES= \
cldapp.cc \ cldapp.cc \
$(NULL) $(NULL)
%.o: %.cc OBJECTS=$(SOURCES:.cc=.o)
$(CC) -Os -I. -o $@ $<
FLAGS=-s USE_TYPED_ARRAYS=2 -O3 -s INLINING_LIMIT=1 --llvm-lto 1 --memory-init-file 1 --closure 1 default: all
all: $(SOURCES:.cc=.o) %.o: %.cc Makefile
$(CC) $(FLAGS) -I. -o cld-worker.js $^ --post-js post.js -s EXPORTED_FUNCTIONS="['_detectLangCode', '_lastResultReliable']" $(EMCC) -Os -I. -o $@ $<
cldapp.o: cld.cpp
%.cpp %.js: %.idl
$(WEBIDL) $< $*
all: cld-worker.js
cld-worker.js: $(OBJECTS) post.js cld.js
$(EMCC) $(FLAGS) -I. -o cld-worker.js $(OBJECTS) --post-js cld.js --post-js post.js
clean: clean:
rm -rf $(SOURCES:.cc=.o) rm -f $(OBJECTS) cld.cpp cld.js before.js

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Двоичный файл не отображается.

Просмотреть файл

@ -0,0 +1,47 @@
/* 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/. */
// Note: This is a variant of WebIDL, but its semantics differ from our
// internal WebIDL implementation. Some particular differences that are
// relevent here include:
//
// - Attribute declarations refer directly to member variables of the
// underlying class, and are not forwarded to explicit getter methods.
//
// - Attribute declarations also do not create getters on the JavaScript
// wrapper object, but instead generate "get_foo()" and "set_foo()"
// methods, which must be called in order to access the value. In the case
// of array attributes, the callers must also pass the index they wish to
// access.
//
// - Method overloading is fairly crude. Only explicitly declared variants
// are supported, and selection is based entirely on index of the first
// parameter whose value is undefined.
//
// - DOMString attributes are nullable by default. Null values are not
// converted to empty strings, and non-null values are converted to
// null-terminated, UTF-8 byte arrays.
interface Language {
[Const] DOMString getLanguageCode();
};
interface LanguageGuess {
byte getPercent();
};
interface LanguageInfo {
static LanguageInfo detectLanguage(DOMString buffer, boolean isPlainText);
static LanguageInfo detectLanguage(DOMString buffer, boolean isPlainText,
DOMString? tldHint, long encodingHint,
DOMString? languageHint);
boolean getIsReliable();
[BoundsChecked,Const] readonly attribute LanguageGuess[] languages;
};
LanguageGuess implements Language;
LanguageInfo implements Language;

Просмотреть файл

@ -4,20 +4,104 @@
#include "public/compact_lang_det.h" #include "public/compact_lang_det.h"
extern "C" { #define MAX_RESULTS 3
using namespace CLD2; class Language {
public:
Language(CLD2::Language lang) : mLang(lang) {}
bool g_is_reliable; const char* getLanguageCode() const
{
const char* detectLangCode(const char* src) { return CLD2::LanguageCode(mLang);
return LanguageCode(DetectLanguage(src, strlen(src),
true /* is_plain_text */,
&g_is_reliable));
} }
bool lastResultReliable(void) { private:
return g_is_reliable; const CLD2::Language mLang;
};
class LanguageGuess : public Language {
public:
LanguageGuess(CLD2::Language lang, char percent) :
Language(lang), mPercent(percent) {}
char getPercent() const
{
return mPercent;
} }
private:
const char mPercent;
};
class LanguageInfo : public Language {
public:
static LanguageInfo* detectLanguage(const char* buffer, bool isPlainText)
{
CLD2::Language languages[MAX_RESULTS] = {};
int percentages[MAX_RESULTS] = {};
bool isReliable = false;
// This is ignored.
int textBytes;
CLD2::Language bestGuess = DetectLanguageSummary(
buffer, strlen(buffer), isPlainText,
languages, percentages, &textBytes,
&isReliable);
return new LanguageInfo(isReliable, bestGuess, languages, percentages);
} }
static LanguageInfo* detectLanguage(const char* buffer, bool isPlainText,
const char* tldHint, int encodingHint,
const char* languageHint)
{
CLD2::CLDHints hints = {languageHint, tldHint, encodingHint, CLD2::UNKNOWN_LANGUAGE};
CLD2::Language languages[MAX_RESULTS] = {};
int percentages[MAX_RESULTS] = {};
bool isReliable = false;
// These are ignored.
double scores[MAX_RESULTS];
int textBytes;
CLD2::Language bestGuess = ExtDetectLanguageSummary(
buffer, strlen(buffer), isPlainText,
&hints, 0,
languages, percentages, scores,
nullptr, &textBytes, &isReliable);
return new LanguageInfo(isReliable, bestGuess, languages, percentages);
}
~LanguageInfo()
{
for (int i = 0; i < MAX_RESULTS; i++) {
delete languages[i];
}
}
bool getIsReliable() const
{
return mIsReliable;
}
const LanguageGuess* languages[MAX_RESULTS];
private:
LanguageInfo(bool isReliable, CLD2::Language bestGuess,
CLD2::Language languageIDs[MAX_RESULTS],
int percentages[MAX_RESULTS]) :
Language(bestGuess), mIsReliable(isReliable)
{
for (int i = 0; i < MAX_RESULTS; i++) {
languages[i] = new LanguageGuess(languageIDs[i], percentages[i]);
}
}
const bool mIsReliable;
};
#include "cld.cpp"

Просмотреть файл

@ -2,31 +2,170 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file, * 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/. */ * You can obtain one at http://mozilla.org/MPL/2.0/. */
// The WebIDL binder places static methods on the prototype, rather than
// on the constructor, which is a bit clumsy, and is definitely not
// idiomatic.
LanguageInfo.detectLanguage = LanguageInfo.prototype.detectLanguage;
// Closure is overzealous in its function call optimization, and tries
// to turn these singleton methods into unbound function calls.
ensureCache.alloc = ensureCache.alloc.bind(ensureCache);
ensureCache.prepare = ensureCache.prepare.bind(ensureCache);
// From public/encodings.h. Unfortunately, the WebIDL binder doesn't
// allow us to define or automatically derive these in the IDL.
var Encodings = {
'ISO_8859_1' : 0,
'ISO_8859_2' : 1,
'ISO_8859_3' : 2,
'ISO_8859_4' : 3,
'ISO_8859_5' : 4,
'ISO_8859_6' : 5,
'ISO_8859_7' : 6,
'ISO_8859_8' : 7,
'ISO_8859_9' : 8,
'ISO_8859_10' : 9,
'JAPANESE_EUC_JP' : 10,
'EUC_JP' : 10,
'JAPANESE_SHIFT_JIS' : 11,
'SHIFT_JIS' : 11,
'JAPANESE_JIS' : 12,
'JIS' : 12,
'CHINESE_BIG5' : 13,
'BIG5' : 13,
'CHINESE_GB' : 14,
'CHINESE_EUC_CN' : 15,
'EUC_CN' : 15,
'KOREAN_EUC_KR' : 16,
'EUC_KR' : 16,
'UNICODE_UNUSED' : 17,
'CHINESE_EUC_DEC' : 18,
'EUC_DEC' : 18,
'CHINESE_CNS' : 19,
'CNS' : 19,
'CHINESE_BIG5_CP950' : 20,
'BIG5_CP950' : 20,
'JAPANESE_CP932' : 21,
'CP932' : 21,
'UTF8' : 22,
'UNKNOWN_ENCODING' : 23,
'ASCII_7BIT' : 24,
'RUSSIAN_KOI8_R' : 25,
'KOI8_R' : 25,
'RUSSIAN_CP1251' : 26,
'CP1251' : 26,
'MSFT_CP1252' : 27,
'CP1252' : 27,
'RUSSIAN_KOI8_RU' : 28,
'KOI8_RU' : 28,
'MSFT_CP1250' : 29,
'CP1250' : 29,
'ISO_8859_15' : 30,
'MSFT_CP1254' : 31,
'CP1254' : 31,
'MSFT_CP1257' : 32,
'CP1257' : 32,
'ISO_8859_11' : 33,
'MSFT_CP874' : 34,
'CP874' : 34,
'MSFT_CP1256' : 35,
'CP1256' : 35,
'MSFT_CP1255' : 36,
'CP1255' : 36,
'ISO_8859_8_I' : 37,
'HEBREW_VISUAL' : 38,
'CZECH_CP852' : 39,
'CP852' : 39,
'CZECH_CSN_369103' : 40,
'CSN_369103' : 40,
'MSFT_CP1253' : 41,
'CP1253' : 41,
'RUSSIAN_CP866' : 42,
'CP866' : 42,
'ISO_8859_13' : 43,
'ISO_2022_KR' : 44,
'GBK' : 45,
'GB18030' : 46,
'BIG5_HKSCS' : 47,
'ISO_2022_CN' : 48,
'TSCII' : 49,
'TAMIL_MONO' : 50,
'TAMIL_BI' : 51,
'JAGRAN' : 52,
'MACINTOSH_ROMAN' : 53,
'UTF7' : 54,
'BHASKAR' : 55,
'HTCHANAKYA' : 56,
'UTF16BE' : 57,
'UTF16LE' : 58,
'UTF32BE' : 59,
'UTF32LE' : 60,
'BINARYENC' : 61,
'HZ_GB_2312' : 62,
'UTF8UTF8' : 63,
'TAM_ELANGO' : 64,
'TAM_LTTMBARANI' : 65,
'TAM_SHREE' : 66,
'TAM_TBOOMIS' : 67,
'TAM_TMNEWS' : 68,
'TAM_WEBTAMIL' : 69,
'KDDI_SHIFT_JIS' : 70,
'DOCOMO_SHIFT_JIS' : 71,
'SOFTBANK_SHIFT_JIS' : 72,
'KDDI_ISO_2022_JP' : 73,
'ISO_2022_JP' : 73,
'SOFTBANK_ISO_2022_JP' : 74,
};
// Accept forms both with and without underscores/hypens.
for (let code of Object.keys(Encodings)) {
if (code['includes']("_"))
Encodings[code.replace(/_/g, "")] = Encodings[code];
}
addOnPreMain(function() { addOnPreMain(function() {
onmessage = function(aMsg){ onmessage = function(aMsg){
let data = aMsg['data'];
// Convert the string to an array of UTF8 bytes. let langInfo;
var encoder = new TextEncoder(); if (data['tld'] == undefined && data['encoding'] == undefined && data['language'] == undefined) {
encoder['encoding'] = "utf-8"; langInfo = LanguageInfo.detectLanguage(data['text'], !data['isHTML']);
var utf8Array = encoder['encode'](aMsg.data); } else {
// Do our best to find the given encoding in the encodings table.
// Otherwise, just fall back to unknown.
let enc = String(data['encoding']).toUpperCase().replace(/[_-]/g, "");
// Copy the UTF8 byte array to the heap. let encoding;
var strLength = utf8Array.length; if (Encodings.hasOwnProperty(enc))
var ptr = Module['_malloc'](strLength + 1); encoding = Encodings[enc];
var heap = Module['HEAPU8']; else
new Uint8Array(heap.buffer, ptr, strLength).set(utf8Array); encoding = Encodings['UNKNOWN_ENCODING'];
// Add a \0 at the end of the C string.
heap[ptr + strLength] = 0;
var lang = Pointer_stringify(_detectLangCode(ptr)); langInfo = LanguageInfo.detectLanguage(data['text'], !data['isHTML'],
var confident = !!Module['ccall']("lastResultReliable", "number"); data['tld'] || null,
postMessage({'language': lang, encoding,
'confident': confident}); data['language'] || null);
}
Module['_free'](ptr); postMessage({
'language': langInfo.getLanguageCode(),
'confident': langInfo.getIsReliable(),
'languages': new Array(3).fill(0).map((_, index) => {
let lang = langInfo.get_languages(index);
return {
'languageCode': lang.getLanguageCode(),
'percent': lang.getPercent(),
};
}).filter(lang => {
// Ignore empty results.
return lang['languageCode'] != "un" || lang['percent'] > 0;
}),
});
Module.destroy(langInfo);
}; };
postMessage("ready"); postMessage("ready");
}); });

Просмотреть файл

@ -308,7 +308,7 @@ const kTestPairs = [
["bg", "BULGARIAN", kTeststr_bg_Cyrl], ["bg", "BULGARIAN", kTeststr_bg_Cyrl],
["ca", "CATALAN", kTeststr_ca_Latn], ["ca", "CATALAN", kTeststr_ca_Latn],
["ceb", "CEBUANO", kTeststr_ceb_Latn], ["ceb", "CEBUANO", kTeststr_ceb_Latn],
["hr", "CROATIAN", kTeststr_hr_Latn], ["hr", "CROATIAN", kTeststr_hr_Latn, [false, 0, "el", 4]],
["cs", "CZECH", kTeststr_cs_Latn], ["cs", "CZECH", kTeststr_cs_Latn],
["da", "DANISH", kTeststr_da_Latn], ["da", "DANISH", kTeststr_da_Latn],
["nl", "DUTCH", kTeststr_nl_Latn], ["nl", "DUTCH", kTeststr_nl_Latn],
@ -335,7 +335,7 @@ const kTestPairs = [
["mk", "MACEDONIAN", kTeststr_mk_Cyrl], ["mk", "MACEDONIAN", kTeststr_mk_Cyrl],
["ms", "MALAY", kTeststr_ms_Latn], ["ms", "MALAY", kTeststr_ms_Latn],
["mt", "MALTESE", kTeststr_mt_Latn], ["mt", "MALTESE", kTeststr_mt_Latn],
["mr", "MARATHI", kTeststr_mr_Deva], ["mr", "MARATHI", kTeststr_mr_Deva, [false, 0, "te", 3]],
["ne", "NEPALI", kTeststr_ne_Deva], ["ne", "NEPALI", kTeststr_ne_Deva],
["no", "NORWEGIAN", kTeststr_no_Latn], ["no", "NORWEGIAN", kTeststr_no_Latn],
["fa", "PERSIAN", kTeststr_fa_Arab], ["fa", "PERSIAN", kTeststr_fa_Arab],
@ -370,11 +370,11 @@ const kTestPairs = [
["bs", "BOSNIAN", kTeststr_bs_Latn], ["bs", "BOSNIAN", kTeststr_bs_Latn],
// 2 statistically-close languages // 2 statistically-close languages
["id", "INDONESIAN", kTeststr_id_close, true], ["id", "INDONESIAN", kTeststr_id_close, [true, 80], []],
["ms", "MALAY", kTeststr_ms_close], ["ms", "MALAY", kTeststr_ms_close],
// Simple intermixed French/English text // Simple intermixed French/English text
["fr", "FRENCH", kTeststr_fr_en_Latn], ["fr", "FRENCH", kTeststr_fr_en_Latn, [false, 80, "en", 32]],
// Cross-check the main quadgram table build date // Cross-check the main quadgram table build date
// Change the expected language each time it is rebuilt // Change the expected language each time it is rebuilt
@ -382,14 +382,92 @@ const kTestPairs = [
["az", "AZERBAIJANI", kTeststr_version] // 2014.01.31 ["az", "AZERBAIJANI", kTeststr_version] // 2014.01.31
]; ];
Components.utils.import("resource:///modules/translation/LanguageDetector.jsm"); Components.utils.import("resource://gre/modules/Timer.jsm");
let detectorModule = Components.utils.import("resource:///modules/translation/LanguageDetector.jsm");
add_task(function test_pairs() { function check_result(result, langCode, expected) {
for (let pair of kTestPairs) { equal(result.language, langCode, "Expected language code");
let result = yield LanguageDetector.detectLanguage(pair[2]);
do_check_eq(result.language, pair[0]); // Round percentage up to the nearest 5%, since most strings are
do_check_eq(result.confident, !pair[3]); // detected at slightly less than 100%, and we don't want to
// encode each exact value.
let percent = result.languages[0].percent;
percent = Math.ceil(percent / 20) * 20;
equal(result.languages[0].languageCode, langCode, "Expected first guess language code");
equal(percent, expected[1] || 100, "Expected first guess language percent");
if (expected.length < 3) {
// We're not expecting a second language.
equal(result.languages.length, 1, "Expected only one language result");
} else {
equal(result.languages.length, 2, "Expected two language results");
equal(result.languages[1].languageCode, expected[2], "Expected second guess language code");
equal(result.languages[1].percent, expected[3], "Expected second guess language percent");
}
equal(result.confident, !expected[0], "Expected confidence");
}
add_task(function* test_pairs() {
for (let item of kTestPairs) {
let params = [item[2],
{ text: item[2], tld: "com", language: item[0], encoding: "utf-8" }]
for (let [i, param] of params.entries()) {
// For test items with different expected results when using the
// language hint, use those for the hinted version of the API.
// Otherwise, fall back to the first set of expected values.
let expected = item[3 + i] || item[3] || [];
let result = yield LanguageDetector.detectLanguage(param);
check_result(result, item[0], expected);
}
} }
}); });
var run_test = run_next_test; // Test that the worker is flushed shortly after processing a large
// string.
add_task(function* test_worker_flush() {
let test_string = kTeststr_fr_en_Latn;
let test_item = kTestPairs.find(item => item[2] == test_string);
// Set shorter timeouts and lower string lengths to make things easier
// on the test infrastructure.
detectorModule.LARGE_STRING = test_string.length - 1;
detectorModule.IDLE_TIMEOUT = 1000;
equal(detectorModule.workerManager._idleTimeout, null,
"Should have no idle timeout to start with");
let result = yield LanguageDetector.detectLanguage(test_string);
// Make sure the results are still correct.
check_result(result, test_item[0], test_item[3]);
// We should have an idle timeout after processing the string.
ok(detectorModule.workerManager._idleTimeout != null,
"Should have an idle timeout");
ok(detectorModule.workerManager._worker != null,
"Should have a worker instance");
ok(detectorModule.workerManager._workerReadyPromise != null,
"Should have a worker promise");
// Wait for the idle timeout to elapse.
yield new Promise(resolve => setTimeout(resolve, detectorModule.IDLE_TIMEOUT));
equal(detectorModule.workerManager._idleTimeout, null,
"Should have no idle timeout after it has elapsed");
equal(detectorModule.workerManager._worker, null,
"Should have no worker instance after idle timeout");
equal(detectorModule.workerManager._workerReadyPromise, null,
"Should have no worker promise after idle timeout");
// We should still be able to use the language detector after its
// worker has been flushed.
result = yield LanguageDetector.detectLanguage(test_string);
// Make sure the results are still correct.
check_result(result, test_item[0], test_item[3]);
});

Просмотреть файл

@ -1,3 +1,3 @@
This is the pdf.js project output, https://github.com/mozilla/pdf.js This is the pdf.js project output, https://github.com/mozilla/pdf.js
Current extension version is: 1.4.64 Current extension version is: 1.4.83

Просмотреть файл

@ -72,9 +72,15 @@ function getFindBar(domWindow) {
tab = tabbrowser.getTabForBrowser(browser); tab = tabbrowser.getTabForBrowser(browser);
return tabbrowser.getFindBar(tab); return tabbrowser.getFindBar(tab);
} catch (e) { } catch (e) {
try {
// FF22 has no _getTabForBrowser, and FF24 has no getFindBar // FF22 has no _getTabForBrowser, and FF24 has no getFindBar
var chromeWindow = browser.ownerDocument.defaultView; var chromeWindow = browser.ownerDocument.defaultView;
return chromeWindow.gFindBar; return chromeWindow.gFindBar;
} catch (ex) {
// Suppress errors for PDF files opened in the bookmark sidebar, see
// https://bugzilla.mozilla.org/show_bug.cgi?id=1248959.
return null;
}
} }
} }
@ -352,7 +358,7 @@ ChromeActions.prototype = {
// ... or when the new find events code exists. // ... or when the new find events code exists.
var findBar = getFindBar(this.domWindow); var findBar = getFindBar(this.domWindow);
return findBar && ('updateControlState' in findBar); return !!findBar && ('updateControlState' in findBar);
}, },
supportsDocumentFonts: function() { supportsDocumentFonts: function() {
var prefBrowser = getIntPref('browser.display.use_document_fonts', 1); var prefBrowser = getIntPref('browser.display.use_document_fonts', 1);

Просмотреть файл

@ -28,8 +28,8 @@ factory((root.pdfjsDistBuildPdf = {}));
// Use strict in our context only - users might not want it // Use strict in our context only - users might not want it
'use strict'; 'use strict';
var pdfjsVersion = '1.4.64'; var pdfjsVersion = '1.4.83';
var pdfjsBuild = '2f145d8'; var pdfjsBuild = '0629fd0';
var pdfjsFilePath = var pdfjsFilePath =
typeof document !== 'undefined' && document.currentScript ? typeof document !== 'undefined' && document.currentScript ?
@ -1629,7 +1629,7 @@ AnnotationElementFactory.prototype =
return new StrikeOutAnnotationElement(parameters); return new StrikeOutAnnotationElement(parameters);
default: default:
throw new Error('Unimplemented annotation type "' + subtype + '"'); return new AnnotationElement(parameters);
} }
} }
}; };
@ -1639,15 +1639,18 @@ AnnotationElementFactory.prototype =
* @alias AnnotationElement * @alias AnnotationElement
*/ */
var AnnotationElement = (function AnnotationElementClosure() { var AnnotationElement = (function AnnotationElementClosure() {
function AnnotationElement(parameters) { function AnnotationElement(parameters, isRenderable) {
this.isRenderable = isRenderable || false;
this.data = parameters.data; this.data = parameters.data;
this.layer = parameters.layer; this.layer = parameters.layer;
this.page = parameters.page; this.page = parameters.page;
this.viewport = parameters.viewport; this.viewport = parameters.viewport;
this.linkService = parameters.linkService; this.linkService = parameters.linkService;
if (isRenderable) {
this.container = this._createContainer(); this.container = this._createContainer();
} }
}
AnnotationElement.prototype = /** @lends AnnotationElement.prototype */ { AnnotationElement.prototype = /** @lends AnnotationElement.prototype */ {
/** /**
@ -1761,7 +1764,7 @@ var AnnotationElement = (function AnnotationElementClosure() {
*/ */
var LinkAnnotationElement = (function LinkAnnotationElementClosure() { var LinkAnnotationElement = (function LinkAnnotationElementClosure() {
function LinkAnnotationElement(parameters) { function LinkAnnotationElement(parameters) {
AnnotationElement.call(this, parameters); AnnotationElement.call(this, parameters, true);
} }
Util.inherit(LinkAnnotationElement, AnnotationElement, { Util.inherit(LinkAnnotationElement, AnnotationElement, {
@ -1843,7 +1846,9 @@ var LinkAnnotationElement = (function LinkAnnotationElementClosure() {
*/ */
var TextAnnotationElement = (function TextAnnotationElementClosure() { var TextAnnotationElement = (function TextAnnotationElementClosure() {
function TextAnnotationElement(parameters) { function TextAnnotationElement(parameters) {
AnnotationElement.call(this, parameters); var isRenderable = !!(parameters.data.hasPopup ||
parameters.data.title || parameters.data.contents);
AnnotationElement.call(this, parameters, isRenderable);
} }
Util.inherit(TextAnnotationElement, AnnotationElement, { Util.inherit(TextAnnotationElement, AnnotationElement, {
@ -1897,7 +1902,9 @@ var TextAnnotationElement = (function TextAnnotationElementClosure() {
*/ */
var WidgetAnnotationElement = (function WidgetAnnotationElementClosure() { var WidgetAnnotationElement = (function WidgetAnnotationElementClosure() {
function WidgetAnnotationElement(parameters) { function WidgetAnnotationElement(parameters) {
AnnotationElement.call(this, parameters); var isRenderable = !parameters.data.hasAppearance &&
!!parameters.data.fieldValue;
AnnotationElement.call(this, parameters, isRenderable);
} }
Util.inherit(WidgetAnnotationElement, AnnotationElement, { Util.inherit(WidgetAnnotationElement, AnnotationElement, {
@ -1964,7 +1971,8 @@ var WidgetAnnotationElement = (function WidgetAnnotationElementClosure() {
*/ */
var PopupAnnotationElement = (function PopupAnnotationElementClosure() { var PopupAnnotationElement = (function PopupAnnotationElementClosure() {
function PopupAnnotationElement(parameters) { function PopupAnnotationElement(parameters) {
AnnotationElement.call(this, parameters); var isRenderable = !!(parameters.data.title || parameters.data.contents);
AnnotationElement.call(this, parameters, isRenderable);
} }
Util.inherit(PopupAnnotationElement, AnnotationElement, { Util.inherit(PopupAnnotationElement, AnnotationElement, {
@ -2154,7 +2162,7 @@ var PopupElement = (function PopupElementClosure() {
var HighlightAnnotationElement = ( var HighlightAnnotationElement = (
function HighlightAnnotationElementClosure() { function HighlightAnnotationElementClosure() {
function HighlightAnnotationElement(parameters) { function HighlightAnnotationElement(parameters) {
AnnotationElement.call(this, parameters); AnnotationElement.call(this, parameters, true);
} }
Util.inherit(HighlightAnnotationElement, AnnotationElement, { Util.inherit(HighlightAnnotationElement, AnnotationElement, {
@ -2181,7 +2189,7 @@ var HighlightAnnotationElement = (
var UnderlineAnnotationElement = ( var UnderlineAnnotationElement = (
function UnderlineAnnotationElementClosure() { function UnderlineAnnotationElementClosure() {
function UnderlineAnnotationElement(parameters) { function UnderlineAnnotationElement(parameters) {
AnnotationElement.call(this, parameters); AnnotationElement.call(this, parameters, true);
} }
Util.inherit(UnderlineAnnotationElement, AnnotationElement, { Util.inherit(UnderlineAnnotationElement, AnnotationElement, {
@ -2207,7 +2215,7 @@ var UnderlineAnnotationElement = (
*/ */
var SquigglyAnnotationElement = (function SquigglyAnnotationElementClosure() { var SquigglyAnnotationElement = (function SquigglyAnnotationElementClosure() {
function SquigglyAnnotationElement(parameters) { function SquigglyAnnotationElement(parameters) {
AnnotationElement.call(this, parameters); AnnotationElement.call(this, parameters, true);
} }
Util.inherit(SquigglyAnnotationElement, AnnotationElement, { Util.inherit(SquigglyAnnotationElement, AnnotationElement, {
@ -2234,7 +2242,7 @@ var SquigglyAnnotationElement = (function SquigglyAnnotationElementClosure() {
var StrikeOutAnnotationElement = ( var StrikeOutAnnotationElement = (
function StrikeOutAnnotationElementClosure() { function StrikeOutAnnotationElementClosure() {
function StrikeOutAnnotationElement(parameters) { function StrikeOutAnnotationElement(parameters) {
AnnotationElement.call(this, parameters); AnnotationElement.call(this, parameters, true);
} }
Util.inherit(StrikeOutAnnotationElement, AnnotationElement, { Util.inherit(StrikeOutAnnotationElement, AnnotationElement, {
@ -2281,7 +2289,7 @@ var AnnotationLayer = (function AnnotationLayerClosure() {
for (var i = 0, ii = parameters.annotations.length; i < ii; i++) { for (var i = 0, ii = parameters.annotations.length; i < ii; i++) {
var data = parameters.annotations[i]; var data = parameters.annotations[i];
if (!data || !data.hasHtml) { if (!data) {
continue; continue;
} }
@ -2293,8 +2301,10 @@ var AnnotationLayer = (function AnnotationLayerClosure() {
linkService: parameters.linkService linkService: parameters.linkService
}; };
var element = annotationElementFactory.create(properties); var element = annotationElementFactory.create(properties);
if (element.isRenderable) {
parameters.div.appendChild(element.render()); parameters.div.appendChild(element.render());
} }
}
}, },
/** /**
@ -6565,7 +6575,7 @@ var PDFDocumentProxy = (function PDFDocumentProxyClosure() {
* title: string, * title: string,
* bold: boolean, * bold: boolean,
* italic: boolean, * italic: boolean,
* color: rgb array, * color: rgb Uint8Array,
* dest: dest obj, * dest: dest obj,
* url: string, * url: string,
* items: array of more items like this * items: array of more items like this

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -27,12 +27,12 @@ See https://github.com/adobe-type-tools/cmap-resources
<title>PDF.js viewer</title> <title>PDF.js viewer</title>
<!-- This snippet is used in the Firefox extension (included from viewer.html) --> <!-- This snippet is used in the Firefox extension (included from viewer.html) -->
<base href="resource://pdf.js/web/" /> <base href="resource://pdf.js/web/">
<script src="l10n.js"></script> <script src="l10n.js"></script>
<script src="../build/pdf.js"></script> <script src="../build/pdf.js"></script>
<link rel="stylesheet" href="viewer.css"/> <link rel="stylesheet" href="viewer.css">
@ -279,7 +279,7 @@ See https://github.com/adobe-type-tools/cmap-resources
</div> </div>
<div class="row"> <div class="row">
<!-- The type="password" attribute is set via script, to prevent warnings in Firefox for all http:// documents. --> <!-- The type="password" attribute is set via script, to prevent warnings in Firefox for all http:// documents. -->
<input id="password" class="toolbarField" /> <input id="password" class="toolbarField">
</div> </div>
<div class="buttonRow"> <div class="buttonRow">
<button id="passwordCancel" class="overlayButton"><span data-l10n-id="password_cancel">Cancel</span></button> <button id="passwordCancel" class="overlayButton"><span data-l10n-id="password_cancel">Cancel</span></button>

Просмотреть файл

@ -34,6 +34,7 @@ RequestExecutionLevel user
Var TmpVal Var TmpVal
Var InstallType Var InstallType
Var AddStartMenuSC Var AddStartMenuSC
Var AddTaskbarSC
Var AddQuickLaunchSC Var AddQuickLaunchSC
Var AddDesktopSC Var AddDesktopSC
Var InstallMaintenanceService Var InstallMaintenanceService
@ -395,10 +396,12 @@ Section "-Application" APP_IDX
; If we are writing to HKLM and create either the desktop or start menu ; If we are writing to HKLM and create either the desktop or start menu
; shortcuts set IconsVisible to 1 otherwise to 0. ; shortcuts set IconsVisible to 1 otherwise to 0.
; Taskbar shortcuts imply having a start menu shortcut.
${StrFilter} "${FileMainEXE}" "+" "" "" $R9 ${StrFilter} "${FileMainEXE}" "+" "" "" $R9
StrCpy $0 "Software\Clients\StartMenuInternet\$R9\InstallInfo" StrCpy $0 "Software\Clients\StartMenuInternet\$R9\InstallInfo"
${If} $AddDesktopSC == 1 ${If} $AddDesktopSC == 1
${OrIf} $AddStartMenuSC == 1 ${OrIf} $AddStartMenuSC == 1
${OrIf} $AddTaskbarSC == 1
WriteRegDWORD HKLM "$0" "IconsVisible" 1 WriteRegDWORD HKLM "$0" "IconsVisible" 1
${Else} ${Else}
WriteRegDWORD HKLM "$0" "IconsVisible" 0 WriteRegDWORD HKLM "$0" "IconsVisible" 0
@ -412,10 +415,12 @@ Section "-Application" APP_IDX
; If we create either the desktop or start menu shortcuts, then ; If we create either the desktop or start menu shortcuts, then
; set IconsVisible to 1 otherwise to 0. ; set IconsVisible to 1 otherwise to 0.
; Taskbar shortcuts imply having a start menu shortcut.
${StrFilter} "${FileMainEXE}" "+" "" "" $R9 ${StrFilter} "${FileMainEXE}" "+" "" "" $R9
StrCpy $0 "Software\Clients\StartMenuInternet\$R9\InstallInfo" StrCpy $0 "Software\Clients\StartMenuInternet\$R9\InstallInfo"
${If} $AddDesktopSC == 1 ${If} $AddDesktopSC == 1
${OrIf} $AddStartMenuSC == 1 ${OrIf} $AddStartMenuSC == 1
${OrIf} $AddTaskbarSC == 1
WriteRegDWORD HKCU "$0" "IconsVisible" 1 WriteRegDWORD HKCU "$0" "IconsVisible" 1
${Else} ${Else}
WriteRegDWORD HKCU "$0" "IconsVisible" 0 WriteRegDWORD HKCU "$0" "IconsVisible" 0
@ -601,12 +606,10 @@ Section "-InstallEndCleanup"
UAC::ExecCodeSegment $0 UAC::ExecCodeSegment $0
${EndIf} ${EndIf}
${EndIf} ${EndIf}
; Adds a pinned Task Bar shortcut (see MigrateTaskBarShortcut for details).
${MigrateTaskBarShortcut}
${EndUnless} ${EndUnless}
${GetShortcutsLogPath} $0 ; Adds a pinned Task Bar shortcut (see MigrateTaskBarShortcut for details).
WriteIniStr "$0" "TASKBAR" "Migrated" "true" ${MigrateTaskBarShortcut}
; Add the Firewall entries during install ; Add the Firewall entries during install
Call AddFirewallEntries Call AddFirewallEntries

Просмотреть файл

@ -1130,6 +1130,10 @@ ${EndIf}
ClearErrors ClearErrors
WriteIniStr "$0" "TASKBAR" "Migrated" "true" WriteIniStr "$0" "TASKBAR" "Migrated" "true"
${If} ${AtLeastWin7} ${If} ${AtLeastWin7}
; If we didn't run the stub installer, AddTaskbarSC will be empty.
; We determine whether to pin based on whether we're the default
; browser, or if we're on win8 or later, we always pin.
${If} $AddTaskbarSC == ""
; No need to check the default on Win8 and later ; No need to check the default on Win8 and later
${If} ${AtMostWin2008R2} ${If} ${AtMostWin2008R2}
; Check if the Firefox is the http handler for this user ; Check if the Firefox is the http handler for this user
@ -1143,6 +1147,9 @@ ${EndIf}
${OrIf} ${AtLeastWin8} ${OrIf} ${AtLeastWin8}
${PinToTaskBar} ${PinToTaskBar}
${EndIf} ${EndIf}
${ElseIf} $AddTaskbarSC == "1"
${PinToTaskBar}
${EndIf}
${EndIf} ${EndIf}
${EndIf} ${EndIf}
${EndIf} ${EndIf}
@ -1486,7 +1493,7 @@ Function SetAsDefaultAppUserHKCU
${EndUnless} ${EndUnless}
${EndIf} ${EndIf}
${RemoveDeprecatedKeys} ${RemoveDeprecatedKeys}
${PinToTaskBar} ${MigrateTaskBarShortcut}
FunctionEnd FunctionEnd
; Helper for updating the shortcut application model IDs. ; Helper for updating the shortcut application model IDs.

Просмотреть файл

@ -1564,6 +1564,14 @@ Function OnDownload
WriteINIStr "$PLUGINSDIR\${CONFIG_INI}" "Install" "InstallDirectoryPath" "$INSTDIR" WriteINIStr "$PLUGINSDIR\${CONFIG_INI}" "Install" "InstallDirectoryPath" "$INSTDIR"
; Don't create the QuickLaunch or Taskbar shortcut from the launched installer ; Don't create the QuickLaunch or Taskbar shortcut from the launched installer
WriteINIStr "$PLUGINSDIR\${CONFIG_INI}" "Install" "QuickLaunchShortcut" "false" WriteINIStr "$PLUGINSDIR\${CONFIG_INI}" "Install" "QuickLaunchShortcut" "false"
; Either avoid or force adding a taskbar pin based on the checkbox value:
${If} $CheckboxShortcutOnBar == 0
WriteINIStr "$PLUGINSDIR\${CONFIG_INI}" "Install" "TaskbarShortcut" "false"
${Else}
WriteINIStr "$PLUGINSDIR\${CONFIG_INI}" "Install" "TaskbarShortcut" "true"
${EndIf}
${If} $CheckboxShortcutOnDesktop == 1 ${If} $CheckboxShortcutOnDesktop == 1
WriteINIStr "$PLUGINSDIR\${CONFIG_INI}" "Install" "DesktopShortcut" "true" WriteINIStr "$PLUGINSDIR\${CONFIG_INI}" "Install" "DesktopShortcut" "true"
${Else} ${Else}
@ -1586,14 +1594,10 @@ Function OnDownload
WriteINIStr "$PLUGINSDIR\${CONFIG_INI}" "Install" "MaintenanceService" "false" WriteINIStr "$PLUGINSDIR\${CONFIG_INI}" "Install" "MaintenanceService" "false"
!endif !endif
; Write migrated to the shortcuts.ini file to prevent the installer ; Delete the taskbar shortcut history to ensure we do the right thing based on
; from creating a taskbar shortcut (Bug 791613). ; the config file above.
${GetShortcutsLogPath} $0 ${GetShortcutsLogPath} $0
Delete "$0" Delete "$0"
; Workaround to prevent pinning to the taskbar.
${If} $CheckboxShortcutOnBar == 0
WriteIniStr "$0" "TASKBAR" "Migrated" "true"
${EndIf}
GetFunctionAddress $0 RemoveFileProgressCallback GetFunctionAddress $0 RemoveFileProgressCallback
${RemovePrecompleteEntries} $0 ${RemovePrecompleteEntries} $0

Просмотреть файл

@ -844,7 +844,6 @@ you can use these alternative items. Otherwise, their values should be empty. -
<!ENTITY social.directory.introText "Click on a service to add it to &brandShortName;."> <!ENTITY social.directory.introText "Click on a service to add it to &brandShortName;.">
<!ENTITY social.directory.viewmore.text "View More"> <!ENTITY social.directory.viewmore.text "View More">
<!ENTITY customizeMode.tabTitle "Customize &brandShortName;">
<!ENTITY customizeMode.menuAndToolbars.header2 "Additional Tools and Features"> <!ENTITY customizeMode.menuAndToolbars.header2 "Additional Tools and Features">
<!ENTITY customizeMode.menuAndToolbars.empty "Want more tools?"> <!ENTITY customizeMode.menuAndToolbars.empty "Want more tools?">
<!ENTITY customizeMode.menuAndToolbars.emptyLink "Choose from thousands of add-ons"> <!ENTITY customizeMode.menuAndToolbars.emptyLink "Choose from thousands of add-ons">

Просмотреть файл

@ -689,6 +689,9 @@ customizeTips.tip0 = %1$S: You can customize %2$S to work the way you do. Simply
customizeTips.tip0.hint = Hint customizeTips.tip0.hint = Hint
customizeTips.tip0.learnMore = Learn more customizeTips.tip0.learnMore = Learn more
# LOCALIZATION NOTE (customizeMode.tabTitle): %S is brandShortName
customizeMode.tabTitle = Customize %S
# LOCALIZATION NOTE(appmenu.*.description, appmenu.*.label): these are used for # LOCALIZATION NOTE(appmenu.*.description, appmenu.*.label): these are used for
# the appmenu labels and buttons that appear when an update is staged for # the appmenu labels and buttons that appear when an update is staged for
# installation or a background update has failed and a manual download is required. # installation or a background update has failed and a manual download is required.

Просмотреть файл

@ -171,6 +171,9 @@ featureEnableRequiresRestart=%S must restart to enable this feature.
featureDisableRequiresRestart=%S must restart to disable this feature. featureDisableRequiresRestart=%S must restart to disable this feature.
shouldRestartTitle=Restart %S shouldRestartTitle=Restart %S
restartNow=Restart Now
restartLater=Restart Later
#### e10S #### e10S
# LOCALIZATION NOTE (e10sFeedbackAfterRestart): This message appears when the user # LOCALIZATION NOTE (e10sFeedbackAfterRestart): This message appears when the user
# unchecks "Enable multi-process" on the "General" preferences tab. # unchecks "Enable multi-process" on the "General" preferences tab.

Просмотреть файл

@ -1,173 +0,0 @@
/* 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/. */
"use strict";
this.EXPORTED_SYMBOLS = ["CustomizationTabPreloader"];
const Cu = Components.utils;
const Cc = Components.classes;
const Ci = Components.interfaces;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/Promise.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "HiddenFrame",
"resource:///modules/HiddenFrame.jsm");
const HTML_NS = "http://www.w3.org/1999/xhtml";
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
const XUL_PAGE = "data:application/vnd.mozilla.xul+xml;charset=utf-8,<window%20id='win'/>";
const CUSTOMIZATION_URL = "about:customizing";
// The interval between swapping in a preload docShell and kicking off the
// next preload in the background.
const PRELOADER_INTERVAL_MS = 600;
function createTimer(obj, delay) {
let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
timer.init(obj, delay, Ci.nsITimer.TYPE_ONE_SHOT);
return timer;
}
function clearTimer(timer) {
if (timer) {
timer.cancel();
}
return null;
}
this.CustomizationTabPreloader = {
uninit: function () {
CustomizationTabPreloaderInternal.uninit();
},
newTab: function (aTab) {
return CustomizationTabPreloaderInternal.newTab(aTab);
},
/**
* ensurePreloading starts the preloading of the about:customizing
* content page. This function is idempotent (until a call to uninit),
* so multiple calls to it are fine.
*/
ensurePreloading: function() {
CustomizationTabPreloaderInternal.ensurePreloading();
},
};
Object.freeze(CustomizationTabPreloader);
this.CustomizationTabPreloaderInternal = {
_browser: null,
uninit: function () {
if (this._browser) {
this._browser.destroy();
this._browser = null;
}
},
newTab: function (aTab) {
let win = aTab.ownerDocument.defaultView;
if (win.gBrowser && this._browser) {
return this._browser.swapWithNewTab(aTab);
}
return false;
},
ensurePreloading: function () {
if (!this._browser) {
this._browser = new HiddenBrowser();
}
}
};
function HiddenBrowser() {
this._createBrowser();
}
HiddenBrowser.prototype = {
_timer: null,
_hiddenFrame: null,
get isPreloaded() {
return this._browser &&
this._browser.contentDocument &&
this._browser.contentDocument.readyState === "complete" &&
this._browser.currentURI.spec === CUSTOMIZATION_URL;
},
swapWithNewTab: function (aTab) {
if (!this.isPreloaded || this._timer) {
return false;
}
let win = aTab.ownerDocument.defaultView;
let tabbrowser = win.gBrowser;
if (!tabbrowser) {
return false;
}
// Swap docShells.
tabbrowser.swapNewTabWithBrowser(aTab, this._browser);
// Load all default frame scripts attached to the target window.
let mm = aTab.linkedBrowser.messageManager;
let scripts = win.getGroupMessageManager("browsers").getDelayedFrameScripts();
Array.forEach(scripts, ([script, runGlobal]) => mm.loadFrameScript(script, true, runGlobal));
// Remove the browser, it will be recreated by a timer.
this._removeBrowser();
// Start a timer that will kick off preloading the next page.
this._timer = createTimer(this, PRELOADER_INTERVAL_MS);
// Signal that we swapped docShells.
return true;
},
observe: function () {
this._timer = null;
// Start pre-loading the customization page.
this._createBrowser();
},
destroy: function () {
this._removeBrowser();
if (this._hiddenFrame) {
this._hiddenFrame.destroy();
this._hiddenFrame = null;
}
this._timer = clearTimer(this._timer);
},
_createBrowser: function () {
if (!this._hiddenFrame) {
this._hiddenFrame = new HiddenFrame();
}
this._hiddenFrame.get().then(aFrame => {
let doc = aFrame.document;
this._browser = doc.createElementNS(XUL_NS, "browser");
this._browser.permanentKey = {};
this._browser.setAttribute("type", "content");
this._browser.setAttribute("src", CUSTOMIZATION_URL);
this._browser.style.width = "400px";
this._browser.style.height = "400px";
doc.getElementById("win").appendChild(this._browser);
});
},
_removeBrowser: function () {
if (this._browser) {
this._browser.remove();
this._browser = null;
}
}
};

Просмотреть файл

@ -22,7 +22,6 @@ EXTRA_JS_MODULES += [
'ContentObservers.jsm', 'ContentObservers.jsm',
'ContentSearch.jsm', 'ContentSearch.jsm',
'ContentWebRTC.jsm', 'ContentWebRTC.jsm',
'CustomizationTabPreloader.jsm',
'DirectoryLinksProvider.jsm', 'DirectoryLinksProvider.jsm',
'E10SUtils.jsm', 'E10SUtils.jsm',
'Feeds.jsm', 'Feeds.jsm',

Просмотреть файл

@ -75,7 +75,7 @@
--chrome-secondary-background-color: #f5f6f7; --chrome-secondary-background-color: #f5f6f7;
--chrome-navigator-toolbox-separator-color: #cccccc; --chrome-navigator-toolbox-separator-color: #cccccc;
--chrome-nav-bar-separator-color: #B6B6B8; --chrome-nav-bar-separator-color: #B6B6B8;
--chrome-nav-buttons-background: #fcfcfc; --chrome-nav-buttons-background: #ffffff; /* --theme-body-background */
--chrome-nav-buttons-hover-background: #DADBDB; --chrome-nav-buttons-hover-background: #DADBDB;
--chrome-nav-bar-controls-border-color: #ccc; --chrome-nav-bar-controls-border-color: #ccc;
--chrome-selection-color: #f5f7fa; --chrome-selection-color: #f5f7fa;
@ -85,9 +85,7 @@
--tab-hover-background-color: #D7D8DA; --tab-hover-background-color: #D7D8DA;
--tab-selection-color: #f5f7fa; --tab-selection-color: #f5f7fa;
--tab-selection-background-color: #4c9ed9; --tab-selection-background-color: #4c9ed9;
--tab-selection-box-shadow: 0 2px 0 #9FDFFF inset, --tab-selection-box-shadow: none;
0 -2px 0 rgba(0,0,0,.05) inset,
0 -1px 0 rgba(0,0,0,.2) inset;
--pinned-tab-glow: radial-gradient(22px at center calc(100% - 2px), rgba(76,158,217,0.9) 13%, transparent 16%); --pinned-tab-glow: radial-gradient(22px at center calc(100% - 2px), rgba(76,158,217,0.9) 13%, transparent 16%);

Просмотреть файл

@ -54,7 +54,7 @@ function test() {
// Focus the console and add event listener to track whether it loses focus // Focus the console and add event listener to track whether it loses focus
// (Must happen after generateMouseClickInTab() call) // (Must happen after generateMouseClickInTab() call)
let consoleLostFocus = false; let consoleLostFocus = false;
jsterm.inputNode.focus(); jsterm.focus();
jsterm.inputNode.addEventListener('blur', () => {consoleLostFocus = true;}); jsterm.inputNode.addEventListener('blur', () => {consoleLostFocus = true;});
is(gThreadClient.paused, true, is(gThreadClient.paused, true,

Просмотреть файл

@ -1049,7 +1049,7 @@ InspectorPanel.prototype = {
let jsterm = panel.hud.jsterm; let jsterm = panel.hud.jsterm;
jsterm.execute("inspect($0)"); jsterm.execute("inspect($0)");
jsterm.inputNode.focus(); jsterm.focus();
}); });
}, },

Просмотреть файл

@ -27,7 +27,7 @@
max-width: 150px; max-width: 150px;
} }
.inspector-tabpanel { .inspector-tabpanel > * {
/* /*
* Override `-moz-user-focus:ignore;` from toolkit/content/minimal-xul.css * Override `-moz-user-focus:ignore;` from toolkit/content/minimal-xul.css
*/ */

Просмотреть файл

@ -98,6 +98,8 @@ skip-if = e10s # Bug 1039528: "inspect element" contextual-menu doesn't work wit
[browser_rules_edit-property_08.js] [browser_rules_edit-property_08.js]
[browser_rules_edit-property_09.js] [browser_rules_edit-property_09.js]
[browser_rules_edit-selector-click.js] [browser_rules_edit-selector-click.js]
[browser_rules_edit-selector-click-on-scrollbar.js]
skip-if = os == "mac" # Bug 1245996 : click on scrollbar not working on OSX
[browser_rules_edit-selector-commit.js] [browser_rules_edit-selector-commit.js]
[browser_rules_edit-selector_01.js] [browser_rules_edit-selector_01.js]
[browser_rules_edit-selector_02.js] [browser_rules_edit-selector_02.js]

Просмотреть файл

@ -0,0 +1,88 @@
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Testing ruleview inplace-editor is not blurred when clicking on the ruleview
// container scrollbar.
const TEST_URI = `
<style type="text/css">
div.testclass {
color: black;
}
.a {
color: #aaa;
}
.b {
color: #bbb;
}
.c {
color: #ccc;
}
.d {
color: #ddd;
}
.e {
color: #eee;
}
.f {
color: #fff;
}
</style>
<div class="testclass a b c d e f">Styled Node</div>
`;
add_task(function*() {
info("Toolbox height should be small enough to force scrollbars to appear");
yield new Promise(done => {
let options = {"set": [
["devtools.toolbox.footer.height", 200],
]};
SpecialPowers.pushPrefEnv(options, done);
});
yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
let {inspector, view} = yield openRuleView();
yield selectNode(".testclass", inspector);
info("Check we have an overflow on the ruleview container.");
let container = view.element;
let hasScrollbar = container.offsetHeight < container.scrollHeight;
ok(hasScrollbar, "The rule view container should have a vertical scrollbar.");
info("Focusing an existing selector name in the rule-view.");
let ruleEditor = getRuleViewRuleEditor(view, 1);
let editor = yield focusEditableField(view, ruleEditor.selectorText);
is(inplaceEditor(ruleEditor.selectorText), editor,
"The selector editor is focused.");
info("Click on the scrollbar element.");
yield clickOnRuleviewScrollbar(view);
is(editor.input, view.styleDocument.activeElement,
"The editor input should still be focused.");
info("Check a new value can still be committed in the editable field");
let newValue = ".testclass.a.b.c.d.e.f";
let onRuleViewChanged = once(view, "ruleview-changed");
info("Enter new value and commit.");
editor.input.value = newValue;
EventUtils.synthesizeKey("VK_RETURN", {});
yield onRuleViewChanged;
ok(getRuleViewRule(view, newValue), "Rule with '" + newValue + " 'exists.");
});
function* clickOnRuleviewScrollbar(view) {
let container = view.element;
let onScroll = once(container, "scroll");
let rect = container.getBoundingClientRect();
// click 5 pixels before the bottom-right corner should hit the scrollbar
EventUtils.synthesizeMouse(container, rect.width - 5, rect.height - 5,
{}, view.styleWindow);
yield onScroll;
ok(true, "The rule view container scrolled after clicking on the scrollbar.");
}

Просмотреть файл

@ -8,7 +8,7 @@
const { setTheme } = require("devtools/client/shared/theme"); const { setTheme } = require("devtools/client/shared/theme");
const LIGHT_BG = "#fcfcfc"; const LIGHT_BG = "white";
const DARK_BG = "#14171a"; const DARK_BG = "#14171a";
setTheme("dark"); setTheme("dark");

Просмотреть файл

@ -19,7 +19,7 @@
%sourceEditorStrings; %sourceEditorStrings;
]> ]>
<page xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" class="theme-body"> <page xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" class="theme-body theme-light">
<script type="application/javascript" src="chrome://global/content/globalOverlay.js"/> <script type="application/javascript" src="chrome://global/content/globalOverlay.js"/>

Просмотреть файл

@ -13,7 +13,8 @@ support-files =
skip-if = true # Bug 1173950 skip-if = true # Bug 1173950
[browser_projecteditor_delete_file.js] [browser_projecteditor_delete_file.js]
skip-if = e10s # Frequent failures in e10s - Bug 1020027 skip-if = e10s # Frequent failures in e10s - Bug 1020027
[browser_projecteditor_rename_file.js] [browser_projecteditor_rename_file_01.js]
[browser_projecteditor_rename_file_02.js]
[browser_projecteditor_editing_01.js] [browser_projecteditor_editing_01.js]
[browser_projecteditor_editors_image.js] [browser_projecteditor_editors_image.js]
[browser_projecteditor_external_change.js] [browser_projecteditor_external_change.js]

Просмотреть файл

@ -1,82 +0,0 @@
/* 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";
// Test file rename functionality
add_task(function*() {
let projecteditor = yield addProjectEditorTabForTempDirectory();
ok(true, "ProjectEditor has loaded");
let root = [...projecteditor.project.allStores()][0].root;
is(root.path, TEMP_PATH, "The root store is set to the correct temp path.");
for (let child of root.children) {
yield renameWithContextMenu(projecteditor,
projecteditor.projectTree.getViewContainer(child),
".renamed");
}
});
add_task(function*() {
let projecteditor = yield addProjectEditorTabForTempDirectory();
ok(true, "ProjectEditor has loaded");
let root = [...projecteditor.project.allStores()][0].root;
is(root.path, TEMP_PATH, "The root store is set to the correct temp path.");
let childrenList = new Array();
for (let child of root.children) {
yield renameWithContextMenu(projecteditor,
projecteditor.projectTree.getViewContainer(child),
".ren\u0061\u0308med");
childrenList.push(child.basename + ".ren\u0061\u0308med");
}
for (let child of root.children) {
is (childrenList.indexOf(child.basename) == -1, false,
"Failed to update tree with non-ascii character");
}
});
function openContextMenuOn(node) {
EventUtils.synthesizeMouseAtCenter(
node,
{button: 2, type: "contextmenu"},
node.ownerDocument.defaultView
);
}
function renameWithContextMenu(projecteditor, container, newName) {
let defer = promise.defer();
let popup = projecteditor.contextMenuPopup;
let resource = container.resource;
info ("Going to attempt renaming for: " + resource.path);
onPopupShow(popup).then(function () {
let renameCommand = popup.querySelector("[command=cmd-rename]");
ok (renameCommand, "Rename command exists in popup");
is (renameCommand.getAttribute("hidden"), "", "Rename command is visible");
is (renameCommand.getAttribute("disabled"), "", "Rename command is enabled");
projecteditor.project.on("refresh-complete", function refreshComplete() {
projecteditor.project.off("refresh-complete", refreshComplete);
OS.File.stat(resource.path + newName).then(() => {
ok (true, "File is renamed");
defer.resolve();
}, (ex) => {
ok (false, "Failed to rename file");
defer.resolve();
});
});
renameCommand.click();
popup.hidePopup();
let input = container.elt.childNodes[0].childNodes[1];
input.value = resource.basename + newName;
EventUtils.synthesizeKey("VK_RETURN", {}, projecteditor.window);
});
openContextMenuOn(container.label);
return defer.promise;
}

Просмотреть файл

@ -0,0 +1,19 @@
/* 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";
// Test file rename functionality
add_task(function*() {
let projecteditor = yield addProjectEditorTabForTempDirectory();
ok(true, "ProjectEditor has loaded");
let root = [...projecteditor.project.allStores()][0].root;
is(root.path, TEMP_PATH, "The root store is set to the correct temp path.");
for (let child of root.children) {
yield renameWithContextMenu(projecteditor,
projecteditor.projectTree.getViewContainer(child), ".renamed");
}
});

Просмотреть файл

@ -0,0 +1,26 @@
/* 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";
// Test file rename functionality with non ascii characters
add_task(function*() {
let projecteditor = yield addProjectEditorTabForTempDirectory();
ok(true, "ProjectEditor has loaded");
let root = [...projecteditor.project.allStores()][0].root;
is(root.path, TEMP_PATH, "The root store is set to the correct temp path.");
let childrenList = [];
for (let child of root.children) {
yield renameWithContextMenu(projecteditor,
projecteditor.projectTree.getViewContainer(child), ".ren\u0061\u0308med");
childrenList.push(child.basename + ".ren\u0061\u0308med");
}
for (let child of root.children) {
is(childrenList.indexOf(child.basename) == -1, false,
"Failed to update tree with non-ascii character");
}
});

Просмотреть файл

@ -284,6 +284,46 @@ function* getFileData(file) {
return def.promise; return def.promise;
} }
/**
* Rename the resource of the provided container using the context menu.
*
* @param {ProjectEditor} projecteditor the current project editor instance
* @param {Shell} container for the resource to rename
* @param {String} newName the name to use for renaming the resource
* @return {Promise} a promise that resolves when the resource has been renamed
*/
var renameWithContextMenu = Task.async(function* (projecteditor,
container, newName) {
let popup = projecteditor.contextMenuPopup;
let resource = container.resource;
info("Going to attempt renaming for: " + resource.path);
let waitForPopupShow = onPopupShow(popup);
openContextMenu(container.label);
yield waitForPopupShow;
let renameCommand = popup.querySelector("[command=cmd-rename]");
ok(renameCommand, "Rename command exists in popup");
is(renameCommand.getAttribute("hidden"), "", "Rename command is visible");
is(renameCommand.getAttribute("disabled"), "", "Rename command is enabled");
renameCommand.click();
popup.hidePopup();
let input = container.elt.childNodes[0].childNodes[1];
input.value = resource.basename + newName;
let waitForProjectRefresh = onceProjectRefreshed(projecteditor);
EventUtils.synthesizeKey("VK_RETURN", {}, projecteditor.window);
yield waitForProjectRefresh;
try {
yield OS.File.stat(resource.path + newName);
ok(true, "File is renamed");
} catch (e) {
ok(false, "Failed to rename file");
}
});
function onceEditorCreated(projecteditor) { function onceEditorCreated(projecteditor) {
let def = promise.defer(); let def = promise.defer();
projecteditor.once("onEditorCreated", (editor) => { projecteditor.once("onEditorCreated", (editor) => {
@ -316,6 +356,15 @@ function onceEditorSave(projecteditor) {
return def.promise; return def.promise;
} }
function onceProjectRefreshed(projecteditor) {
return new Promise(resolve => {
projecteditor.project.on("refresh-complete", function refreshComplete() {
projecteditor.project.off("refresh-complete", refreshComplete);
resolve();
});
});
}
function onPopupShow(menu) { function onPopupShow(menu) {
let defer = promise.defer(); let defer = promise.defer();
menu.addEventListener("popupshown", function onpopupshown() { menu.addEventListener("popupshown", function onpopupshown() {
@ -333,3 +382,11 @@ function onPopupHidden(menu) {
}); });
return defer.promise; return defer.promise;
} }
function openContextMenu(node) {
EventUtils.synthesizeMouseAtCenter(
node,
{button: 2, type: "contextmenu"},
node.ownerDocument.defaultView
);
}

Просмотреть файл

@ -8,10 +8,10 @@
since they aren't loaded in this context (within commandlineoutput.xhtml since they aren't loaded in this context (within commandlineoutput.xhtml
and commandlinetooltip.xhtml). */ and commandlinetooltip.xhtml). */
:root[devtoolstheme="light"] { :root[devtoolstheme="light"] {
--gcli-background-color: #ebeced; /* --theme-tab-toolbar-background */ --gcli-background-color: #fcfcfc; /* --theme-tab-toolbar-background */
--gcli-input-focused-background: #f7f7f7; /* --theme-sidebar-background */ --gcli-input-focused-background: #ffffff; /* --theme-sidebar-background */
--gcli-input-color: #18191a; /* --theme-body-color */ --gcli-input-color: #393f4c; /* --theme-body-color */
--gcli-border-color: #aaaaaa; /* --theme-splitter-color */ --gcli-border-color: #dde1e4; /* --theme-splitter-color */
} }
:root[devtoolstheme="dark"] { :root[devtoolstheme="dark"] {

Просмотреть файл

@ -10,11 +10,11 @@
We are copy/pasting variables from light-theme and dark-theme, We are copy/pasting variables from light-theme and dark-theme,
since they aren't loaded in this context (within browser.css). */ since they aren't loaded in this context (within browser.css). */
:root[devtoolstheme="light"] #developer-toolbar { :root[devtoolstheme="light"] #developer-toolbar {
--gcli-background-color: #ebeced; /* --theme-tab-toolbar-background */ --gcli-background-color: #fcfcfc; /* --theme-tab-toolbar-background */
--gcli-input-background: #f0f1f2; /* --theme-toolbar-background */ --gcli-input-background: #fcfcfc; /* --theme-toolbar-background */
--gcli-input-focused-background: #f7f7f7; /* --theme-sidebar-background */ --gcli-input-focused-background: #ffffff; /* --theme-sidebar-background */
--gcli-input-color: #18191a; /* --theme-body-color */ --gcli-input-color: #393f4c; /* --theme-body-color */
--gcli-border-color: #aaaaaa; /* --theme-splitter-color */ --gcli-border-color: #dde1e4; /* --theme-splitter-color */
--selection-background: #4c9ed9; /* --theme-selection-background */ --selection-background: #4c9ed9; /* --theme-selection-background */
--selection-color: #f5f7fa; /* --theme-selection-color */ --selection-color: #f5f7fa; /* --theme-selection-color */
} }

Просмотреть файл

@ -68,13 +68,13 @@ body {
} }
.theme-gutter { .theme-gutter {
background-color: #0f171f; background-color: var(--theme-tab-toolbar-background);
color: var(--theme-content-color3); color: var(--theme-content-color3);
border-color: #303b47; border-color: var(--theme-splitter-color);
} }
.theme-separator { /* grey */ .theme-separator {
border-color: #303b47; border-color: var(--theme-splitter-color);
} }
.theme-fg-color1, .theme-fg-color1,

Просмотреть файл

@ -2,6 +2,6 @@
- License, v. 2.0. If a copy of the MPL was not distributed with this - 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/. --> - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<svg width="7" xmlns="http://www.w3.org/2000/svg" height="12" viewBox="0 0 7 12"> <svg width="7" xmlns="http://www.w3.org/2000/svg" height="12" viewBox="0 0 7 12">
<path fill="#f7f7f7" d="M7,11.6 7,.4 1.5,6z"/> <path fill="#ffffff" d="M7,11.6 7,.4 1.5,6z"/>
<path fill="#ababab" d="M7,0 6,0 0,6 6,12 7,12 7,11.6 1.5,6 7,.4z"/> <path fill="#dde1e4" d="M7,0 6,0 0,6 6,12 7,12 7,11.6 1.5,6 7,.4z"/>
</svg> </svg>

До

Ширина:  |  Высота:  |  Размер: 421 B

После

Ширина:  |  Высота:  |  Размер: 421 B

Просмотреть файл

@ -2,6 +2,6 @@
- License, v. 2.0. If a copy of the MPL was not distributed with this - 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/. --> - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<svg width="7" xmlns="http://www.w3.org/2000/svg" height="12" viewBox="0 0 7 12"> <svg width="7" xmlns="http://www.w3.org/2000/svg" height="12" viewBox="0 0 7 12">
<path fill="#f7f7f7" d="M0,11.6 0,.4 5.5,6z"/> <path fill="#ffffff" d="M0,11.6 0,.4 5.5,6z"/>
<path fill="#ababab" d="M1,0 0,0 0,.4 5.5,6 0,11.6 0,12 1,12 7,6z"/> <path fill="#dde1e4" d="M1,0 0,0 0,.4 5.5,6 0,11.6 0,12 1,12 7,6z"/>
</svg> </svg>

До

Ширина:  |  Высота:  |  Размер: 421 B

После

Ширина:  |  Высота:  |  Размер: 421 B

Просмотреть файл

@ -67,9 +67,9 @@ body {
} }
.theme-gutter { .theme-gutter {
background-color: hsl(0,0%,90%); background-color: var(--theme-tab-toolbar-background);
color: var(--theme-content-color3); color: var(--theme-content-color3);
border-color: hsl(0,0%,65%); border-color: var(--theme-splitter-color);
} }
.theme-separator { /* grey */ .theme-separator { /* grey */
@ -173,7 +173,7 @@ body {
.devtools-sidebar-tabs tabs, .devtools-sidebar-tabs tabs,
.devtools-sidebar-alltabs, .devtools-sidebar-alltabs,
.cm-s-mozilla .CodeMirror-dialog { /* General toolbar styling */ .cm-s-mozilla .CodeMirror-dialog { /* General toolbar styling */
color: var(--theme-body-color-alt); color: var(--theme-body-color);
background-color: var(--theme-toolbar-background); background-color: var(--theme-toolbar-background);
border-color: var(--theme-splitter-color); border-color: var(--theme-splitter-color);
} }

Просмотреть файл

@ -3,10 +3,6 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
:root {
color: #18191a;
}
.view-project-detail { .view-project-detail {
overflow: auto; overflow: auto;
} }

Просмотреть файл

@ -3,12 +3,21 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* Splitters */ /* Splitters */
:root[devtoolstheme="light"] .devtools-horizontal-splitter {
/* These variables are used in browser.xul but inside the toolbox they are overridden by --theme-splitter-color */
--devtools-splitter-color: #dde1e4;
}
:root[devtoolstheme="dark"] .devtools-horizontal-splitter {
--devtools-splitter-color: #42484f;
}
.devtools-horizontal-splitter { .devtools-horizontal-splitter {
-moz-appearance: none; -moz-appearance: none;
background-image: none; background-image: none;
background-color: transparent; background-color: transparent;
border: 0; border: 0;
border-bottom: 1px solid rgba(118, 121, 125, .5); border-bottom: 1px solid var(--devtools-splitter-color);
min-height: 3px; min-height: 3px;
height: 3px; height: 3px;
margin-top: -3px; margin-top: -3px;
@ -20,7 +29,7 @@
background-image: none; background-image: none;
background-color: transparent; background-color: transparent;
border: 0; border: 0;
-moz-border-end: 1px solid rgba(118, 121, 125, .5); -moz-border-end: 1px solid var(--devtools-splitter-color);
min-width: 3px; min-width: 3px;
width: 3px; width: 3px;
-moz-margin-start: -3px; -moz-margin-start: -3px;

Просмотреть файл

@ -818,10 +818,6 @@
border-bottom-color: var(--theme-splitter-color); border-bottom-color: var(--theme-splitter-color);
} }
.theme-light .devtools-tabbar {
box-shadow: 0 -2px 0 rgba(170,170,170,.1) inset;
}
.theme-dark .devtools-tabbar { .theme-dark .devtools-tabbar {
box-shadow: 0 -2px 0 rgba(0,0,0,.1) inset; box-shadow: 0 -2px 0 rgba(0,0,0,.1) inset;
} }
@ -920,12 +916,6 @@
0 -2px 0 rgba(0,0,0,.2) inset; 0 -2px 0 rgba(0,0,0,.2) inset;
} }
.theme-light .devtools-tabbar .devtools-tab[selected] {
box-shadow: 0 2px 0 #d7f1ff inset,
0 8px 3px -5px #2b82bf inset,
0 -2px 0 rgba(0,0,0,.06) inset;
}
#toolbox-tabs .devtools-tab[selected], #toolbox-tabs .devtools-tab[selected],
#toolbox-tabs .devtools-tab[highlighted] { #toolbox-tabs .devtools-tab[highlighted] {
border-width: 0; border-width: 0;

Просмотреть файл

@ -15,19 +15,19 @@
*/ */
:root.theme-light { :root.theme-light {
--theme-body-background: #fcfcfc; --theme-body-background: white;
--theme-sidebar-background: #f7f7f7; --theme-sidebar-background: white;
--theme-contrast-background: #e6b064; --theme-contrast-background: #e6b064;
--theme-tab-toolbar-background: #ebeced; --theme-tab-toolbar-background: #fcfcfc;
--theme-toolbar-background: #f0f1f2; --theme-toolbar-background: #fcfcfc;
--theme-selection-background: #4c9ed9; --theme-selection-background: #4c9ed9;
--theme-selection-background-semitransparent: rgba(76, 158, 217, .23); --theme-selection-background-semitransparent: rgba(76, 158, 217, 0.15);
--theme-selection-color: #f5f7fa; --theme-selection-color: #f5f7fa;
--theme-splitter-color: #aaaaaa; --theme-splitter-color: #dde1e4;
--theme-comment: #757873; --theme-comment: #696969;
--theme-body-color: #18191a; --theme-body-color: #393f4c;
--theme-body-color-alt: #585959; --theme-body-color-alt: #585959;
--theme-content-color1: #292e33; --theme-content-color1: #292e33;
--theme-content-color2: #8fa1b2; --theme-content-color2: #8fa1b2;

Просмотреть файл

@ -6,14 +6,12 @@
.theme-dark { .theme-dark {
--table-splitter-color: rgba(255,255,255,0.15); --table-splitter-color: rgba(255,255,255,0.15);
--table-zebra-background: rgba(255,255,255,0.05); --table-zebra-background: rgba(255,255,255,0.05);
--smw-margin: #000;
--smw-item-top-border: rgba(0,0,0,0.2); --smw-item-top-border: rgba(0,0,0,0.2);
--smw-item-bottom-border: rgba(128,128,128,0.15); --smw-item-bottom-border: rgba(128,128,128,0.15);
} }
.theme-light { .theme-light {
--table-splitter-color: rgba(0,0,0,0.15); --table-splitter-color: rgba(0,0,0,0.15);
--table-zebra-background: rgba(0,0,0,0.05); --table-zebra-background: rgba(0,0,0,0.05);
--smw-margin: #aaa;
--smw-item-top-border: rgba(128,128,128,0.15); --smw-item-top-border: rgba(128,128,128,0.15);
--smw-item-bottom-border: transparent; --smw-item-bottom-border: transparent;
} }
@ -357,12 +355,12 @@
.side-menu-widget-container:-moz-locale-dir(ltr), .side-menu-widget-container:-moz-locale-dir(ltr),
.side-menu-widget-empty-text:-moz-locale-dir(ltr) { .side-menu-widget-empty-text:-moz-locale-dir(ltr) {
box-shadow: inset -1px 0 0 var(--smw-margin); box-shadow: inset -1px 0 0 var(--theme-splitter-color);
} }
.side-menu-widget-container:-moz-locale-dir(rtl), .side-menu-widget-container:-moz-locale-dir(rtl),
.side-menu-widget-empty-text:-moz-locale-dir(rtl) { .side-menu-widget-empty-text:-moz-locale-dir(rtl) {
box-shadow: inset 1px 0 0 var(--smw-margin); box-shadow: inset 1px 0 0 var(--theme-splitter-color);
} }
.side-menu-widget-group { .side-menu-widget-group {

Просмотреть файл

@ -106,8 +106,7 @@ function* populateInputHistory(hud) {
*/ */
function* testNaviatingHistoryInUI(hud) { function* testNaviatingHistoryInUI(hud) {
let jsterm = hud.jsterm; let jsterm = hud.jsterm;
let {inputNode} = jsterm; jsterm.focus();
inputNode.focus();
// Count backwards from original input and make sure that pressing up // Count backwards from original input and make sure that pressing up
// restores this. // restores this.

Просмотреть файл

@ -21,8 +21,6 @@ add_task(function* () {
function testClosingAfterCompletion(hud, browser) { function testClosingAfterCompletion(hud, browser) {
let deferred = promise.defer(); let deferred = promise.defer();
let inputNode = hud.jsterm.inputNode;
let errorWhileClosing = false; let errorWhileClosing = false;
function errorListener() { function errorListener() {
errorWhileClosing = true; errorWhileClosing = true;
@ -30,8 +28,8 @@ function testClosingAfterCompletion(hud, browser) {
browser.addEventListener("error", errorListener, false); browser.addEventListener("error", errorListener, false);
// Focus the inputNode and perform the keycombo to close the WebConsole. // Focus the jsterm and perform the keycombo to close the WebConsole.
inputNode.focus(); hud.jsterm.focus();
gDevTools.once("toolbox-destroyed", function() { gDevTools.once("toolbox-destroyed", function() {
browser.removeEventListener("error", errorListener, false); browser.removeEventListener("error", errorListener, false);

Просмотреть файл

@ -25,7 +25,7 @@ function setup(HUD) {
jsterm = HUD.jsterm; jsterm = HUD.jsterm;
inputNode = jsterm.inputNode; inputNode = jsterm.inputNode;
inputNode.focus(); jsterm.focus();
ok(!jsterm.getInputValue(), "jsterm.getInputValue() is empty"); ok(!jsterm.getInputValue(), "jsterm.getInputValue() is empty");

Просмотреть файл

@ -30,7 +30,7 @@ function test() {
yield executeJS(); yield executeJS();
yield clickMessageAndShowVariablesView(); yield clickMessageAndShowVariablesView();
jsterm.inputNode.focus(); jsterm.focus();
yield testHideVariablesViewAfterEscape(); yield testHideVariablesViewAfterEscape();
@ -144,7 +144,7 @@ function test() {
deferred.resolve(); deferred.resolve();
}, false); }, false);
jsterm.inputNode.focus(); jsterm.focus();
jsterm.setInputValue("document.location."); jsterm.setInputValue("document.location.");
EventUtils.sendKey("TAB", hud.iframeWindow); EventUtils.sendKey("TAB", hud.iframeWindow);

Просмотреть файл

@ -577,7 +577,7 @@ WebConsoleFrame.prototype = {
this._addFocusCallback(this.outputNode, (evt) => { this._addFocusCallback(this.outputNode, (evt) => {
if ((evt.target.nodeName.toLowerCase() != "a") && if ((evt.target.nodeName.toLowerCase() != "a") &&
(evt.target.parentNode.nodeName.toLowerCase() != "a")) { (evt.target.parentNode.nodeName.toLowerCase() != "a")) {
this.jsterm.inputNode.focus(); this.jsterm.focus();
} }
}); });
@ -589,7 +589,7 @@ WebConsoleFrame.prototype = {
}); });
// focus input node // focus input node
this.jsterm.inputNode.focus(); this.jsterm.focus();
}, },
/** /**
@ -607,7 +607,7 @@ WebConsoleFrame.prototype = {
* @private * @private
*/ */
_onPanelSelected: function() { _onPanelSelected: function() {
this.jsterm.inputNode.focus(); this.jsterm.focus();
}, },
/** /**
@ -3090,9 +3090,8 @@ JSTerm.prototype = {
}, },
focus: function() { focus: function() {
let inputNode = this.inputNode; if (!this.inputNode.getAttribute("focused")) {
if (!inputNode.getAttribute("focused")) { this.inputNode.focus();
inputNode.focus();
} }
}, },
@ -3461,7 +3460,7 @@ JSTerm.prototype = {
} }
this._sidebarDestroy(); this._sidebarDestroy();
this.inputNode.focus(); this.focus();
event.stopPropagation(); event.stopPropagation();
}, },
@ -3854,7 +3853,7 @@ JSTerm.prototype = {
// Ctrl-N is also used to focus the Network category button on // Ctrl-N is also used to focus the Network category button on
// MacOSX. The preventDefault() call doesn't prevent the focus // MacOSX. The preventDefault() call doesn't prevent the focus
// from moving away from the input. // from moving away from the input.
inputNode.focus(); this.focus();
} }
this.clearCompletion(); this.clearCompletion();
break; break;
@ -3870,7 +3869,7 @@ JSTerm.prototype = {
// Ctrl-P may also be used to focus some category button on MacOSX. // Ctrl-P may also be used to focus some category button on MacOSX.
// The preventDefault() call doesn't prevent the focus from moving // The preventDefault() call doesn't prevent the focus from moving
// away from the input. // away from the input.
inputNode.focus(); this.focus();
} }
this.clearCompletion(); this.clearCompletion();
break; break;

Просмотреть файл

@ -10853,6 +10853,24 @@ nsIDocument::ObsoleteSheet(const nsAString& aSheetURI, ErrorResult& rv)
} }
} }
already_AddRefed<nsIURI>
nsIDocument::GetMozDocumentURIIfNotForErrorPages()
{
if (mFailedChannel) {
nsCOMPtr<nsIURI> failedURI;
if (NS_SUCCEEDED(mFailedChannel->GetURI(getter_AddRefs(failedURI)))) {
return failedURI.forget();
}
}
nsCOMPtr<nsIURI> uri = GetDocumentURIObject();
if (!uri) {
return nullptr;
}
return uri.forget();
}
nsIHTMLCollection* nsIHTMLCollection*
nsIDocument::Children() nsIDocument::Children()
{ {

Просмотреть файл

@ -2601,6 +2601,8 @@ public:
void ObsoleteSheet(const nsAString& aSheetURI, mozilla::ErrorResult& rv); void ObsoleteSheet(const nsAString& aSheetURI, mozilla::ErrorResult& rv);
already_AddRefed<nsIURI> GetMozDocumentURIIfNotForErrorPages();
// ParentNode // ParentNode
nsIHTMLCollection* Children(); nsIHTMLCollection* Children();
uint32_t ChildElementCount(); uint32_t ChildElementCount();

Просмотреть файл

@ -6,7 +6,7 @@ support-files =
plugin_no_scroll_div.html plugin_no_scroll_div.html
[browser_bug1163570.js] [browser_bug1163570.js]
skip-if = (!e10s || os != "win") skip-if = true # Bug 1249878
[browser_bug1196539.js] [browser_bug1196539.js]
skip-if = (!e10s || os != "win") skip-if = (!e10s || os != "win")
[browser_tabswitchbetweenplugins.js] [browser_tabswitchbetweenplugins.js]

Просмотреть файл

@ -39,20 +39,18 @@ function promiseWaitForEvent(object, eventName, capturing = false, chrome = fals
add_task(function* () { add_task(function* () {
registerCleanupFunction(function () { registerCleanupFunction(function () {
Services.prefs.clearUserPref("browser.uiCustomization.disableAnimation");
window.focus(); window.focus();
}); });
}); });
add_task(function* () { add_task(function* () {
Services.prefs.setBoolPref("browser.uiCustomization.disableAnimation", true);
setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Test Plug-in"); setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Test Plug-in");
let pluginTab = gBrowser.selectedTab = gBrowser.addTab(); let pluginTab = gBrowser.selectedTab = gBrowser.addTab();
let customizeTab = gBrowser.addTab(); let prefTab = gBrowser.addTab();
yield promiseTabLoad(pluginTab, gTestRoot + "plugin_test.html"); yield promiseTabLoad(pluginTab, gTestRoot + "plugin_test.html");
yield promiseTabLoad(customizeTab, "about:customizing"); yield promiseTabLoad(prefTab, "about:preferences");
let result = yield ContentTask.spawn(gBrowser.selectedBrowser, null, function*() { let result = yield ContentTask.spawn(gBrowser.selectedBrowser, null, function*() {
let doc = content.document; let doc = content.document;
@ -62,10 +60,8 @@ add_task(function* () {
is(result, true, "plugin is loaded"); is(result, true, "plugin is loaded");
let cpromise = promiseWaitForEvent(window.gNavToolbox, "customizationready");
let ppromise = promiseWaitForEvent(window, "MozAfterPaint"); let ppromise = promiseWaitForEvent(window, "MozAfterPaint");
gBrowser.selectedTab = customizeTab; gBrowser.selectedTab = prefTab;
yield cpromise;
yield ppromise; yield ppromise;
// We're going to switch tabs using actual mouse clicks, which helps // We're going to switch tabs using actual mouse clicks, which helps
@ -77,13 +73,11 @@ add_task(function* () {
info("-> " + tabStripContainer.firstChild.tagName); // tab info("-> " + tabStripContainer.firstChild.tagName); // tab
info("-> " + tabStripContainer.childNodes[0].label); // test harness tab info("-> " + tabStripContainer.childNodes[0].label); // test harness tab
info("-> " + tabStripContainer.childNodes[1].label); // plugin tab info("-> " + tabStripContainer.childNodes[1].label); // plugin tab
info("-> " + tabStripContainer.childNodes[2].label); // customize tab info("-> " + tabStripContainer.childNodes[2].label); // preferences tab
for (let iteration = 0; iteration < 5; iteration++) { for (let iteration = 0; iteration < 5; iteration++) {
cpromise = promiseWaitForEvent(window.gNavToolbox, "aftercustomization");
ppromise = promiseWaitForEvent(window, "MozAfterPaint"); ppromise = promiseWaitForEvent(window, "MozAfterPaint");
EventUtils.synthesizeMouseAtCenter(tabStripContainer.childNodes[1], {}, window); EventUtils.synthesizeMouseAtCenter(tabStripContainer.childNodes[1], {}, window);
yield cpromise;
yield ppromise; yield ppromise;
result = yield ContentTask.spawn(pluginTab.linkedBrowser, null, function*() { result = yield ContentTask.spawn(pluginTab.linkedBrowser, null, function*() {
@ -94,10 +88,8 @@ add_task(function* () {
is(result, true, "plugin is visible"); is(result, true, "plugin is visible");
cpromise = promiseWaitForEvent(window.gNavToolbox, "customizationready");
ppromise = promiseWaitForEvent(window, "MozAfterPaint"); ppromise = promiseWaitForEvent(window, "MozAfterPaint");
EventUtils.synthesizeMouseAtCenter(tabStripContainer.childNodes[2], {}, window); EventUtils.synthesizeMouseAtCenter(tabStripContainer.childNodes[2], {}, window);
yield cpromise;
yield ppromise; yield ppromise;
result = yield ContentTask.spawn(pluginTab.linkedBrowser, null, function*() { result = yield ContentTask.spawn(pluginTab.linkedBrowser, null, function*() {
@ -108,11 +100,6 @@ add_task(function* () {
is(result, false, "plugin is hidden"); is(result, false, "plugin is hidden");
} }
// wait for customize view to shutdown cleanly otherwise we get gBrowser.removeTab(prefTab);
// a ton of error spew on shutdown.
cpromise = promiseWaitForEvent(window.gNavToolbox, "aftercustomization");
gBrowser.removeTab(customizeTab);
yield cpromise;
gBrowser.removeTab(pluginTab); gBrowser.removeTab(pluginTab);
}); });

Просмотреть файл

@ -373,6 +373,10 @@ partial interface Document {
[ChromeOnly] readonly attribute DOMString contentLanguage; [ChromeOnly] readonly attribute DOMString contentLanguage;
[ChromeOnly] readonly attribute nsILoadGroup? documentLoadGroup; [ChromeOnly] readonly attribute nsILoadGroup? documentLoadGroup;
// like documentURI, except that for error pages, it returns the URI we were
// trying to load when we hit an error, rather than the error page's own URI.
[ChromeOnly] readonly attribute URI? mozDocumentURIIfNotForErrorPages;
}; };
// Extension to give chrome JS the ability to determine when a document was // Extension to give chrome JS the ability to determine when a document was

Просмотреть файл

@ -228,7 +228,7 @@ nsTextBoxFrame::UpdateAttributes(nsIAtom* aAttribute,
if (aAttribute == nullptr || aAttribute == nsGkAtoms::crop) { if (aAttribute == nullptr || aAttribute == nsGkAtoms::crop) {
static nsIContent::AttrValuesArray strings[] = static nsIContent::AttrValuesArray strings[] =
{&nsGkAtoms::left, &nsGkAtoms::start, &nsGkAtoms::center, {&nsGkAtoms::left, &nsGkAtoms::start, &nsGkAtoms::center,
&nsGkAtoms::right, &nsGkAtoms::end, nullptr}; &nsGkAtoms::right, &nsGkAtoms::end, &nsGkAtoms::none, nullptr};
CroppingStyle cropType; CroppingStyle cropType;
switch (mContent->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::crop, switch (mContent->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::crop,
strings, eCaseMatters)) { strings, eCaseMatters)) {
@ -243,9 +243,12 @@ nsTextBoxFrame::UpdateAttributes(nsIAtom* aAttribute,
case 4: case 4:
cropType = CropRight; cropType = CropRight;
break; break;
default: case 5:
cropType = CropNone; cropType = CropNone;
break; break;
default:
cropType = CropAuto;
break;
} }
if (cropType != mCropType) { if (cropType != mCropType) {
@ -647,6 +650,7 @@ nsTextBoxFrame::CalculateTitleForWidth(nsRenderingContext& aRenderingContext,
} }
const nsDependentString& kEllipsis = nsContentUtils::GetLocalizedEllipsis(); const nsDependentString& kEllipsis = nsContentUtils::GetLocalizedEllipsis();
if (mCropType != CropNone) {
// start with an ellipsis // start with an ellipsis
mCroppedTitle.Assign(kEllipsis); mCroppedTitle.Assign(kEllipsis);
@ -666,12 +670,17 @@ nsTextBoxFrame::CalculateTitleForWidth(nsRenderingContext& aRenderingContext,
return titleWidth; return titleWidth;
aWidth -= titleWidth; aWidth -= titleWidth;
} else {
mCroppedTitle.Truncate(0);
titleWidth = 0;
}
// XXX: This whole block should probably take surrogates into account // XXX: This whole block should probably take surrogates into account
// XXX and clusters! // XXX and clusters!
// ok crop things // ok crop things
switch (mCropType) switch (mCropType)
{ {
case CropAuto:
case CropNone: case CropNone:
case CropRight: case CropRight:
{ {
@ -1126,7 +1135,7 @@ nsTextBoxFrame::GetMinSize(nsBoxLayoutState& aBoxLayoutState)
DISPLAY_MIN_SIZE(this, size); DISPLAY_MIN_SIZE(this, size);
// if there is cropping our min width becomes our border and padding // if there is cropping our min width becomes our border and padding
if (mCropType != CropNone) { if (mCropType != CropNone && mCropType != CropAuto) {
if (GetWritingMode().IsVertical()) { if (GetWritingMode().IsVertical()) {
size.height = 0; size.height = 0;
} else { } else {

Просмотреть файл

@ -26,7 +26,7 @@ public:
NS_IMETHOD DoLayout(nsBoxLayoutState& aBoxLayoutState) override; NS_IMETHOD DoLayout(nsBoxLayoutState& aBoxLayoutState) override;
virtual void MarkIntrinsicISizesDirty() override; virtual void MarkIntrinsicISizesDirty() override;
enum CroppingStyle { CropNone, CropLeft, CropRight, CropCenter }; enum CroppingStyle { CropNone, CropLeft, CropRight, CropCenter, CropAuto };
friend nsIFrame* NS_NewTextBoxFrame(nsIPresShell* aPresShell, nsStyleContext* aContext); friend nsIFrame* NS_NewTextBoxFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);

Просмотреть файл

@ -424,7 +424,7 @@ public class BrowserApp extends GeckoApp
} }
private void showBookmarkRemovedSnackbar() { private void showBookmarkRemovedSnackbar() {
SnackbarHelper.showSnackbar(this, getResources().getString(R.string.bookmark_removed), Snackbar.LENGTH_SHORT); SnackbarHelper.showSnackbar(this, getResources().getString(R.string.bookmark_removed), Snackbar.LENGTH_LONG);
} }
private void showSwitchToReadingListSnackbar(String message) { private void showSwitchToReadingListSnackbar(String message) {
@ -456,7 +456,7 @@ public class BrowserApp extends GeckoApp
public void onRemovedFromReadingList(String url) { public void onRemovedFromReadingList(String url) {
SnackbarHelper.showSnackbar(this, SnackbarHelper.showSnackbar(this,
getResources().getString(R.string.reading_list_removed), getResources().getString(R.string.reading_list_removed),
Snackbar.LENGTH_SHORT); Snackbar.LENGTH_LONG);
} }
@Override @Override
@ -2016,7 +2016,7 @@ public class BrowserApp extends GeckoApp
if (Tabs.getInstance().getDisplayCount() == 0) if (Tabs.getInstance().getDisplayCount() == 0)
return; return;
hideFirstrunPager(TelemetryContract.Method.TABSTRAY); hideFirstrunPager(TelemetryContract.Method.BUTTON);
if (ensureTabsPanelExists()) { if (ensureTabsPanelExists()) {
// If we've just inflated the tabs panel, only show it once the current // If we've just inflated the tabs panel, only show it once the current

Просмотреть файл

@ -219,7 +219,7 @@ public class EditBookmarkDialog {
public void onPostExecute(Void result) { public void onPostExecute(Void result) {
SnackbarHelper.showSnackbar((Activity) context, SnackbarHelper.showSnackbar((Activity) context,
context.getString(R.string.bookmark_updated), context.getString(R.string.bookmark_updated),
Snackbar.LENGTH_SHORT); Snackbar.LENGTH_LONG);
} }
}).execute(); }).execute();
} }

Просмотреть файл

@ -576,7 +576,7 @@ public abstract class GeckoApp
ThreadUtils.postToUiThread(new Runnable() { ThreadUtils.postToUiThread(new Runnable() {
@Override @Override
public void run() { public void run() {
SnackbarHelper.showSnackbar(GeckoApp.this, getString(resId), Snackbar.LENGTH_SHORT); SnackbarHelper.showSnackbar(GeckoApp.this, getString(resId), Snackbar.LENGTH_LONG);
} }
}); });
} }
@ -1014,12 +1014,12 @@ public abstract class GeckoApp
File dcimDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES); File dcimDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
if (!dcimDir.mkdirs() && !dcimDir.isDirectory()) { if (!dcimDir.mkdirs() && !dcimDir.isDirectory()) {
SnackbarHelper.showSnackbar(this, getString(R.string.set_image_path_fail), Snackbar.LENGTH_SHORT); SnackbarHelper.showSnackbar(this, getString(R.string.set_image_path_fail), Snackbar.LENGTH_LONG);
return; return;
} }
String path = Media.insertImage(getContentResolver(),image, null, null); String path = Media.insertImage(getContentResolver(),image, null, null);
if (path == null) { if (path == null) {
SnackbarHelper.showSnackbar(this, getString(R.string.set_image_path_fail), Snackbar.LENGTH_SHORT); SnackbarHelper.showSnackbar(this, getString(R.string.set_image_path_fail), Snackbar.LENGTH_LONG);
return; return;
} }
final Intent intent = new Intent(Intent.ACTION_ATTACH_DATA); final Intent intent = new Intent(Intent.ACTION_ATTACH_DATA);
@ -1036,7 +1036,7 @@ public abstract class GeckoApp
}; };
ActivityHandlerHelper.startIntentForActivity(this, chooser, handler); ActivityHandlerHelper.startIntentForActivity(this, chooser, handler);
} else { } else {
SnackbarHelper.showSnackbar(this, getString(R.string.set_image_fail), Snackbar.LENGTH_SHORT); SnackbarHelper.showSnackbar(this, getString(R.string.set_image_fail), Snackbar.LENGTH_LONG);
} }
} catch(OutOfMemoryError ome) { } catch(OutOfMemoryError ome) {
Log.e(LOGTAG, "Out of Memory when converting to byte array", ome); Log.e(LOGTAG, "Out of Memory when converting to byte array", ome);

Просмотреть файл

@ -2670,7 +2670,7 @@ public class GeckoAppShell
private static final void showImageShareFailureSnackbar() { private static final void showImageShareFailureSnackbar() {
SnackbarHelper.showSnackbar((Activity) getContext(), SnackbarHelper.showSnackbar((Activity) getContext(),
getApplicationContext().getString(R.string.share_image_failed), getApplicationContext().getString(R.string.share_image_failed),
Snackbar.LENGTH_SHORT Snackbar.LENGTH_LONG
); );
} }

Просмотреть файл

@ -16,6 +16,7 @@ import java.nio.charset.Charset;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.HashMap; import java.util.HashMap;
import java.util.Hashtable; import java.util.Hashtable;
import java.util.UUID;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -48,6 +49,7 @@ public final class GeckoProfile {
// The path in the profile to the file containing the client ID. // The path in the profile to the file containing the client ID.
private static final String CLIENT_ID_FILE_PATH = "datareporting/state.json"; private static final String CLIENT_ID_FILE_PATH = "datareporting/state.json";
private static final String FHR_CLIENT_ID_FILE_PATH = "healthreport/state.json";
// In the client ID file, the attribute title in the JSON object containing the client ID value. // In the client ID file, the attribute title in the JSON object containing the client ID value.
private static final String CLIENT_ID_JSON_ATTR = "clientID"; private static final String CLIENT_ID_JSON_ATTR = "clientID";
@ -599,7 +601,8 @@ public final class GeckoProfile {
} }
/** /**
* Retrieves the Gecko client ID from the filesystem. * Retrieves the Gecko client ID from the filesystem. If the client ID does not exist, we attempt to migrate and
* persist it from FHR and, if that fails, we attempt to create a new one ourselves.
* *
* This method assumes the client ID is located in a file at a hard-coded path within the profile. The format of * This method assumes the client ID is located in a file at a hard-coded path within the profile. The format of
* this file is a JSONObject which at the bottom level contains a String -> String mapping containing the client ID. * this file is a JSONObject which at the bottom level contains a String -> String mapping containing the client ID.
@ -608,21 +611,84 @@ public final class GeckoProfile {
* robust way to access it. However, we don't want to rely on Gecko running in order to get * robust way to access it. However, we don't want to rely on Gecko running in order to get
* the client ID so instead we access the file this module accesses directly. However, it's * the client ID so instead we access the file this module accesses directly. However, it's
* possible the format of this file (and the access calls in the jsm) will change, leaving * possible the format of this file (and the access calls in the jsm) will change, leaving
* this code to fail. * this code to fail. There are tests in TestGeckoProfile to verify the file format but be
* * warned: THIS IS NOT FOOLPROOF.
* TODO: Write tests to prevent regressions. Mention them here. Test both file location and file format.
* *
* [1]: https://mxr.mozilla.org/mozilla-central/source/toolkit/modules/ClientID.jsm * [1]: https://mxr.mozilla.org/mozilla-central/source/toolkit/modules/ClientID.jsm
*
* @throws IOException if the client ID could not be retrieved.
*/ */
// Mimics ClientID.jsm _doLoadClientID.
@WorkerThread @WorkerThread
public String getClientId() throws IOException { public String getClientId() throws IOException {
final JSONObject obj = readJSONObjectFromFile(CLIENT_ID_FILE_PATH);
try { try {
return obj.getString(CLIENT_ID_JSON_ATTR); return getValidClientIdFromDisk(CLIENT_ID_FILE_PATH);
} catch (final JSONException e) { } catch (final IOException e) {
// Don't log to avoid leaking data in JSONObject. // Avoid log spam: don't log the full Exception w/ the stack trace.
throw new IOException("Client ID does not exist in JSONObject"); Log.d(LOGTAG, "Could not get client ID - attempting to migrate ID from FHR: " + e.getLocalizedMessage());
} }
String clientIdToWrite;
try {
clientIdToWrite = getValidClientIdFromDisk(FHR_CLIENT_ID_FILE_PATH);
} catch (final IOException e) {
// Avoid log spam: don't log the full Exception w/ the stack trace.
Log.d(LOGTAG, "Could not migrate client ID from FHR – creating a new one: " + e.getLocalizedMessage());
clientIdToWrite = UUID.randomUUID().toString();
}
// There is a possibility Gecko is running and the Gecko telemetry implementation decided it's time to generate
// the client ID, writing client ID underneath us. Since it's highly unlikely (e.g. we run in onStart before
// Gecko is started), we don't handle that possibility besides writing the ID and then reading from the file
// again (rather than just returning the value we generated before writing).
//
// In the event it does happen, any discrepancy will be resolved after a restart. In the mean time, both this
// implementation and the Gecko implementation could upload documents with inconsistent IDs.
//
// In any case, if we get an exception, intentionally throw - there's nothing more to do here.
persistClientId(clientIdToWrite);
return getValidClientIdFromDisk(CLIENT_ID_FILE_PATH);
}
/**
* @return a valid client ID
* @throws IOException if a valid client ID could not be retrieved
*/
@WorkerThread
private String getValidClientIdFromDisk(final String filePath) throws IOException {
final JSONObject obj = readJSONObjectFromFile(filePath);
final String clientId = obj.optString(CLIENT_ID_JSON_ATTR);
if (isClientIdValid(clientId)) {
return clientId;
}
throw new IOException("Received client ID is invalid: " + clientId);
}
@WorkerThread
private void persistClientId(final String clientId) throws IOException {
if (!ensureParentDirs(CLIENT_ID_FILE_PATH)) {
throw new IOException("Could not create client ID parent directories");
}
final JSONObject obj = new JSONObject();
try {
obj.put(CLIENT_ID_JSON_ATTR, clientId);
} catch (final JSONException e) {
throw new IOException("Could not create client ID JSON object", e);
}
// ClientID.jsm overwrites the file to store the client ID so it's okay if we do it too.
Log.d(LOGTAG, "Attempting to write new client ID");
writeFile(CLIENT_ID_FILE_PATH, obj.toString()); // Logs errors within function: ideally we'd throw.
}
// From ClientID.jsm - isValidClientID.
public static boolean isClientIdValid(final String clientId) {
// We could use UUID.fromString but, for consistency, we take the implementation from ClientID.jsm.
if (TextUtils.isEmpty(clientId)) {
return false;
}
return clientId.matches("(?i:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})");
} }
/** /**
@ -702,6 +768,20 @@ public final class GeckoProfile {
return null; return null;
} }
/**
* Ensures the parent director(y|ies) of the given filename exist by making them
* if they don't already exist..
*
* @param filename The path to the file whose parents should be made directories
* @return true if the parent directory exists, false otherwise
*/
@WorkerThread
protected boolean ensureParentDirs(final String filename) {
final File file = new File(getDir(), filename);
final File parentFile = file.getParentFile();
return parentFile.mkdirs() || parentFile.isDirectory();
}
public void writeFile(final String filename, final String data) { public void writeFile(final String filename, final String data) {
File file = new File(getDir(), filename); File file = new File(getDir(), filename);
BufferedWriter bufferedWriter = null; BufferedWriter bufferedWriter = null;

Просмотреть файл

@ -188,8 +188,8 @@ public interface TelemetryContract {
// Action triggered from a suggestion provided to the user. // Action triggered from a suggestion provided to the user.
SUGGESTION("suggestion"), SUGGESTION("suggestion"),
// Action triggered from the Tabs tray. // Action triggered from an OS system action.
TABSTRAY("tabstray"), SYSTEM("system"),
// Action triggered from a SuperToast. // Action triggered from a SuperToast.
// Note: Only used in JavaScript for now, but here for completeness. // Note: Only used in JavaScript for now, but here for completeness.

Просмотреть файл

@ -419,7 +419,7 @@ public abstract class HomeFragment extends Fragment {
public void onPostExecute(Void result) { public void onPostExecute(Void result) {
SnackbarHelper.showSnackbar((Activity) mContext, SnackbarHelper.showSnackbar((Activity) mContext,
mContext.getString(R.string.page_removed), mContext.getString(R.string.page_removed),
Snackbar.LENGTH_SHORT); Snackbar.LENGTH_LONG);
} }
} }
} }

Просмотреть файл

@ -655,7 +655,7 @@ OnSharedPreferenceChangeListener
SnackbarHelper.showSnackbar(GeckoPreferences.this, SnackbarHelper.showSnackbar(GeckoPreferences.this,
getString(stringRes), getString(stringRes),
Snackbar.LENGTH_SHORT); Snackbar.LENGTH_LONG);
} }
} catch (Exception e) { } catch (Exception e) {
Log.e(LOGTAG, "Exception handling message \"" + event + "\":", e); Log.e(LOGTAG, "Exception handling message \"" + event + "\":", e);

Просмотреть файл

@ -94,7 +94,7 @@ public class SearchEnginePreference extends CustomListPreference {
SnackbarHelper.showSnackbar(activity, SnackbarHelper.showSnackbar(activity,
activity.getString(R.string.pref_search_last_toast), activity.getString(R.string.pref_search_last_toast),
Snackbar.LENGTH_SHORT); Snackbar.LENGTH_LONG);
return; return;
} }

Просмотреть файл

@ -172,8 +172,7 @@ public class TelemetryUploadService extends BackgroundService {
try { try {
clientId = profile.getClientId(); clientId = profile.getClientId();
} catch (final IOException e) { } catch (final IOException e) {
// Don't log the exception to avoid leaking the profile path. Log.w(LOGTAG, "Unable to get client ID to generate core ping: returning.", e);
Log.w(LOGTAG, "Unable to get client ID to generate core ping: returning.");
return; return;
} }

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 46 KiB

После

Ширина:  |  Высота:  |  Размер: 18 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 38 KiB

После

Ширина:  |  Высота:  |  Размер: 16 KiB

Просмотреть файл

@ -348,7 +348,7 @@ var ActionBarHandler = {
clipboard.copyString(selectedText); clipboard.copyString(selectedText);
let msg = Strings.browser.GetStringFromName("selectionHelper.textCopied"); let msg = Strings.browser.GetStringFromName("selectionHelper.textCopied");
Snackbars.show(msg, Snackbars.LENGTH_SHORT); Snackbars.show(msg, Snackbars.LENGTH_LONG);
// Then cut the selection text. // Then cut the selection text.
ActionBarHandler._getSelection(element, win).deleteFromDocument(); ActionBarHandler._getSelection(element, win).deleteFromDocument();
@ -383,7 +383,7 @@ var ActionBarHandler = {
clipboard.copyString(selectedText); clipboard.copyString(selectedText);
let msg = Strings.browser.GetStringFromName("selectionHelper.textCopied"); let msg = Strings.browser.GetStringFromName("selectionHelper.textCopied");
Snackbars.show(msg, Snackbars.LENGTH_SHORT); Snackbars.show(msg, Snackbars.LENGTH_LONG);
ActionBarHandler._uninit(); ActionBarHandler._uninit();
UITelemetry.addEvent("action.1", "actionbar", null, "copy"); UITelemetry.addEvent("action.1", "actionbar", null, "copy");

Просмотреть файл

@ -63,7 +63,7 @@ var MasterPassword = {
} catch(e) { } catch(e) {
dump("MasterPassword.removePassword: " + e + "\n"); dump("MasterPassword.removePassword: " + e + "\n");
} }
Snackbars.show(Strings.browser.GetStringFromName("masterPassword.incorrect"), Snackbars.LENGTH_SHORT); Snackbars.show(Strings.browser.GetStringFromName("masterPassword.incorrect"), Snackbars.LENGTH_LONG);
return false; return false;
} }
}; };

Просмотреть файл

@ -180,7 +180,7 @@ var Reader = {
case "Reader:ToolbarHidden": case "Reader:ToolbarHidden":
if (!this._hasUsedToolbar) { if (!this._hasUsedToolbar) {
Snackbars.show(Strings.browser.GetStringFromName("readerMode.toolbarTip"), Snackbars.LENGTH_SHORT); Snackbars.show(Strings.browser.GetStringFromName("readerMode.toolbarTip"), Snackbars.LENGTH_LONG);
Services.prefs.setBoolPref("reader.has_used_toolbar", true); Services.prefs.setBoolPref("reader.has_used_toolbar", true);
this._hasUsedToolbar = true; this._hasUsedToolbar = true;
} }

Просмотреть файл

@ -1090,7 +1090,7 @@ var SelectionHandler = {
if (selectedText.length) { if (selectedText.length) {
let clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.nsIClipboardHelper); let clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.nsIClipboardHelper);
clipboard.copyString(selectedText); clipboard.copyString(selectedText);
Snackbars.show(Strings.browser.GetStringFromName("selectionHelper.textCopied"), Snackbars.LENGTH_SHORT); Snackbars.show(Strings.browser.GetStringFromName("selectionHelper.textCopied"), Snackbars.LENGTH_LONG);
} }
this._closeSelection(); this._closeSelection();
}, },

Просмотреть файл

@ -31,10 +31,10 @@ function copyStringShowSnackbar(string, notifyString) {
try { try {
let clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.nsIClipboardHelper); let clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.nsIClipboardHelper);
clipboard.copyString(string); clipboard.copyString(string);
Snackbars.show(notifyString, Snackbars.LENGTH_SHORT); Snackbars.show(notifyString, Snackbars.LENGTH_LONG);
} catch (e) { } catch (e) {
debug("Error copying from about:logins"); debug("Error copying from about:logins");
Snackbars.show(gStringBundle.GetStringFromName("loginsDetails.copyFailed"), Snackbars.LENGTH_SHORT); Snackbars.show(gStringBundle.GetStringFromName("loginsDetails.copyFailed"), Snackbars.LENGTH_LONG);
} }
} }
@ -291,7 +291,7 @@ var Logins = {
if ((newUsername === origUsername) && if ((newUsername === origUsername) &&
(newPassword === origPassword) && (newPassword === origPassword) &&
(newDomain === origDomain) ) { (newDomain === origDomain) ) {
Snackbars.show(gStringBundle.GetStringFromName("editLogin.saved1"), Snackbars.LENGTH_SHORT); Snackbars.show(gStringBundle.GetStringFromName("editLogin.saved1"), Snackbars.LENGTH_LONG);
this._showList(); this._showList();
return; return;
} }
@ -310,10 +310,10 @@ var Logins = {
} }
} }
} catch (e) { } catch (e) {
Snackbars.show(gStringBundle.GetStringFromName("editLogin.couldNotSave"), Snackbars.LENGTH_SHORT); Snackbars.show(gStringBundle.GetStringFromName("editLogin.couldNotSave"), Snackbars.LENGTH_LONG);
return; return;
} }
Snackbars.show(gStringBundle.GetStringFromName("editLogin.saved1"), Snackbars.LENGTH_SHORT); Snackbars.show(gStringBundle.GetStringFromName("editLogin.saved1"), Snackbars.LENGTH_LONG);
this._showList(); this._showList();
}, },

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше