+
+
&searchreset.pageTitle;
+
+
+
+
&searchreset.pageInfo1;
+
&searchreset.selector.label;
+
+
+
+
&searchreset.beforelink.pageInfo2;&searchreset.link.pageInfo2;&searchreset.afterlink.pageInfo2;
+
+
+
+
+
+
+
+
+
+
diff --git a/browser/components/search/jar.mn b/browser/components/search/jar.mn
index c68b6b326267..089ec4bb97b6 100644
--- a/browser/components/search/jar.mn
+++ b/browser/components/search/jar.mn
@@ -5,3 +5,5 @@
browser.jar:
content/browser/search/search.xml (content/search.xml)
content/browser/search/searchbarBindings.css (content/searchbarBindings.css)
+ content/browser/search/searchReset.xhtml (content/searchReset.xhtml)
+ content/browser/search/searchReset.js (content/searchReset.js)
diff --git a/browser/components/search/test/browser.ini b/browser/components/search/test/browser.ini
index 90fa60ff2327..71d79fd39dd1 100644
--- a/browser/components/search/test/browser.ini
+++ b/browser/components/search/test/browser.ini
@@ -37,6 +37,7 @@ skip-if = os == "mac" # bug 967013
[browser_yahoo_behavior.js]
[browser_abouthome_behavior.js]
skip-if = true # Bug ??????, Bug 1100301 - leaks windows until shutdown when --run-by-dir
+[browser_aboutSearchReset.js]
[browser_searchbar_openpopup.js]
skip-if = os == "linux" # Linux has different focus behaviours.
[browser_searchbar_keyboard_navigation.js]
diff --git a/browser/components/search/test/browser_aboutSearchReset.js b/browser/components/search/test/browser_aboutSearchReset.js
new file mode 100644
index 000000000000..4bbd15322030
--- /dev/null
+++ b/browser/components/search/test/browser_aboutSearchReset.js
@@ -0,0 +1,181 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+const TELEMETRY_RESULT_ENUM = {
+ RESTORED_DEFAULT: 0,
+ KEPT_CURRENT: 1,
+ CHANGED_ENGINE: 2,
+ CLOSED_PAGE: 3
+};
+
+const kSearchStr = "a search";
+const kSearchPurpose = "searchbar";
+
+const kTestEngine = "testEngine.xml";
+
+function checkTelemetryRecords(expectedValue) {
+ let histogram = Services.telemetry.getHistogramById("SEARCH_RESET_RESULT");
+ let snapshot = histogram.snapshot();
+ // The probe is declared with 5 values, but we get 6 back from .counts
+ let expectedCounts = [0, 0, 0, 0, 0, 0];
+ if (expectedValue != null) {
+ expectedCounts[expectedValue] = 1;
+ }
+ Assert.deepEqual(snapshot.counts, expectedCounts,
+ "histogram has expected content");
+ histogram.clear();
+}
+
+function promiseStoppedLoad(expectedURL) {
+ return new Promise(resolve => {
+ let browser = gBrowser.selectedBrowser;
+ let original = browser.loadURIWithFlags;
+ browser.loadURIWithFlags = function(URI) {
+ if (URI == expectedURL) {
+ browser.loadURIWithFlags = original;
+ ok(true, "loaded expected url: " + URI);
+ resolve();
+ return;
+ }
+
+ original.apply(browser, arguments);
+ };
+ });
+}
+
+var gTests = [
+
+{
+ desc: "Test the 'Keep Current Settings' button.",
+ run: function* () {
+ let engine = yield promiseNewEngine(kTestEngine, {setAsCurrent: true});
+
+ let expectedURL = engine.
+ getSubmission(kSearchStr, null, kSearchPurpose).
+ uri.spec;
+
+ let rawEngine = engine.wrappedJSObject;
+ let initialHash = rawEngine.getAttr("loadPathHash");
+ rawEngine.setAttr("loadPathHash", "broken");
+
+ let loadPromise = promiseStoppedLoad(expectedURL);
+ gBrowser.contentDocument.getElementById("searchResetKeepCurrent").click();
+ yield loadPromise;
+
+ is(engine, Services.search.currentEngine,
+ "the custom engine is still default");
+ is(rawEngine.getAttr("loadPathHash"), initialHash,
+ "the loadPathHash has been fixed");
+
+ checkTelemetryRecords(TELEMETRY_RESULT_ENUM.KEPT_CURRENT);
+ }
+},
+
+{
+ desc: "Test the 'Restore Search Defaults' button.",
+ run: function* () {
+ let currentEngine = Services.search.currentEngine;
+ let originalEngine = Services.search.originalDefaultEngine;
+ let expectedURL = originalEngine.
+ getSubmission(kSearchStr, null, kSearchPurpose).
+ uri.spec;
+
+ let loadPromise = promiseStoppedLoad(expectedURL);
+ let doc = gBrowser.contentDocument;
+ let button = doc.getElementById("searchResetChangeEngine");
+ is(doc.activeElement, button,
+ "the 'Change Search Engine' button is focused");
+ button.click();
+ yield loadPromise;
+
+ is(originalEngine, Services.search.currentEngine,
+ "the default engine is back to the original one");
+
+ checkTelemetryRecords(TELEMETRY_RESULT_ENUM.RESTORED_DEFAULT);
+ Services.search.currentEngine = currentEngine;
+ }
+},
+
+{
+ desc: "Test the engine selector drop down.",
+ run: function* () {
+ let originalEngineName = Services.search.originalDefaultEngine.name;
+
+ let doc = gBrowser.contentDocument;
+ let list = doc.getElementById("defaultEngine");
+ is(list.value, originalEngineName,
+ "the default selection of the dropdown is the original default engine");
+
+ let defaultEngines = Services.search.getDefaultEngines();
+ is(list.childNodes.length, defaultEngines.length,
+ "the dropdown has the correct count of engines");
+
+ // Select an engine that isn't the original default one.
+ let engine;
+ for (let i = 0; i < defaultEngines.length; ++i) {
+ if (defaultEngines[i].name != originalEngineName) {
+ engine = defaultEngines[i];
+ engine.hidden = true;
+ break;
+ }
+ }
+ list.value = engine.name;
+
+ let expectedURL = engine.getSubmission(kSearchStr, null, kSearchPurpose)
+ .uri.spec;
+ let loadPromise = promiseStoppedLoad(expectedURL);
+ doc.getElementById("searchResetChangeEngine").click();
+ yield loadPromise;
+
+ ok(!engine.hidden, "the selected engine has been unhidden");
+ is(engine, Services.search.currentEngine,
+ "the current engine is what was selected in the drop down");
+
+ checkTelemetryRecords(TELEMETRY_RESULT_ENUM.CHANGED_ENGINE);
+ }
+},
+
+{
+ desc: "Load another page without clicking any of the buttons.",
+ run: function* () {
+ yield promiseTabLoadEvent(gBrowser.selectedTab, "about:mozilla");
+
+ checkTelemetryRecords(TELEMETRY_RESULT_ENUM.CLOSED_PAGE);
+ }
+},
+
+];
+
+function test()
+{
+ waitForExplicitFinish();
+ Task.spawn(function* () {
+ let oldCanRecord = Services.telemetry.canRecordExtended;
+ Services.telemetry.canRecordExtended = true;
+ checkTelemetryRecords();
+
+ for (let test of gTests) {
+ info(test.desc);
+
+ // Create a tab to run the test.
+ let tab = gBrowser.selectedTab = gBrowser.addTab("about:blank");
+
+ // Start loading about:searchreset and wait for it to complete.
+ let url = "about:searchreset?data=" + encodeURIComponent(kSearchStr) +
+ "&purpose=" + kSearchPurpose;
+ yield promiseTabLoadEvent(tab, url);
+
+ info("Running test");
+ yield test.run();
+
+ info("Cleanup");
+ gBrowser.removeCurrentTab();
+ }
+
+ Services.telemetry.canRecordExtended = oldCanRecord;
+ }).then(finish, ex => {
+ ok(false, "Unexpected Exception: " + ex);
+ finish();
+ });
+}
diff --git a/browser/components/search/test/head.js b/browser/components/search/test/head.js
index 6c38b659c4c1..22e25bac1316 100644
--- a/browser/components/search/test/head.js
+++ b/browser/components/search/test/head.js
@@ -1,6 +1,8 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
+Cu.import("resource://gre/modules/Promise.jsm");
+
/**
* Recursively compare two objects and check that every property of expectedObj has the same value
* on actualObj.
@@ -85,3 +87,52 @@ function promiseNewEngine(basename, options = {}) {
});
});
}
+
+/**
+ * Waits for a load (or custom) event to finish in a given tab. If provided
+ * load an uri into the tab.
+ *
+ * @param tab
+ * The tab to load into.
+ * @param [optional] url
+ * The url to load, or the current url.
+ * @return {Promise} resolved when the event is handled.
+ * @resolves to the received event
+ * @rejects if a valid load event is not received within a meaningful interval
+ */
+function promiseTabLoadEvent(tab, url)
+{
+ let deferred = Promise.defer();
+ info("Wait tab event: load");
+
+ function handle(loadedUrl) {
+ if (loadedUrl === "about:blank" || (url && loadedUrl !== url)) {
+ info(`Skipping spurious load event for ${loadedUrl}`);
+ return false;
+ }
+
+ info("Tab event received: load");
+ return true;
+ }
+
+ // Create two promises: one resolved from the content process when the page
+ // loads and one that is rejected if we take too long to load the url.
+ let loaded = BrowserTestUtils.browserLoaded(tab.linkedBrowser, false, handle);
+
+ let timeout = setTimeout(() => {
+ deferred.reject(new Error("Timed out while waiting for a 'load' event"));
+ }, 30000);
+
+ loaded.then(() => {
+ clearTimeout(timeout);
+ deferred.resolve()
+ });
+
+ if (url)
+ BrowserTestUtils.loadURI(tab.linkedBrowser, url);
+
+ // Promise.all rejects if either promise rejects (i.e. if we time out) and
+ // if our loaded promise resolves before the timeout, then we resolve the
+ // timeout promise as well, causing the all promise to resolve.
+ return Promise.all([deferred.promise, loaded]);
+}
diff --git a/browser/extensions/pdfjs/README.mozilla b/browser/extensions/pdfjs/README.mozilla
index 0d25310fe084..2ea19cd0d88a 100644
--- a/browser/extensions/pdfjs/README.mozilla
+++ b/browser/extensions/pdfjs/README.mozilla
@@ -1,3 +1,3 @@
This is the pdf.js project output, https://github.com/mozilla/pdf.js
-Current extension version is: 1.5.256
+Current extension version is: 1.5.276
diff --git a/browser/extensions/pdfjs/content/build/pdf.js b/browser/extensions/pdfjs/content/build/pdf.js
index c35b13d8f911..715c864680a0 100644
--- a/browser/extensions/pdfjs/content/build/pdf.js
+++ b/browser/extensions/pdfjs/content/build/pdf.js
@@ -28,8 +28,8 @@ factory((root.pdfjsDistBuildPdf = {}));
// Use strict in our context only - users might not want it
'use strict';
-var pdfjsVersion = '1.5.256';
-var pdfjsBuild = '1c04335';
+var pdfjsVersion = '1.5.276';
+var pdfjsBuild = '41f978c';
var pdfjsFilePath =
typeof document !== 'undefined' && document.currentScript ?
@@ -2812,7 +2812,6 @@ var Util = sharedUtil.Util;
var createPromiseCapability = sharedUtil.createPromiseCapability;
var CustomStyle = displayDOMUtils.CustomStyle;
var getDefaultSetting = displayDOMUtils.getDefaultSetting;
-var PageViewport = sharedUtil.PageViewport;
/**
* Text layer render parameters.
diff --git a/browser/extensions/pdfjs/content/build/pdf.worker.js b/browser/extensions/pdfjs/content/build/pdf.worker.js
index 847c3c0d4364..6d6750435e1e 100644
--- a/browser/extensions/pdfjs/content/build/pdf.worker.js
+++ b/browser/extensions/pdfjs/content/build/pdf.worker.js
@@ -28,8 +28,8 @@ factory((root.pdfjsDistBuildPdfWorker = {}));
// Use strict in our context only - users might not want it
'use strict';
-var pdfjsVersion = '1.5.256';
-var pdfjsBuild = '1c04335';
+var pdfjsVersion = '1.5.276';
+var pdfjsBuild = '41f978c';
var pdfjsFilePath =
typeof document !== 'undefined' && document.currentScript ?
@@ -4457,6 +4457,11 @@ var CFFDict = (function CFFDictClosure() {
// remove the array wrapping these types of values
if (type === 'num' || type === 'sid' || type === 'offset') {
value = value[0];
+ // Ignore invalid values (fixes bug 1068432).
+ if (isNaN(value)) {
+ warn('Invalid CFFDict value: ' + value + ', for key: ' + key + '.');
+ return true;
+ }
}
this.values[key] = value;
return true;
@@ -37199,7 +37204,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
textState = stateManager.state;
var fn = operation.fn;
args = operation.args;
- var advance;
+ var advance, diff;
switch (fn | 0) {
case OPS.setFont:
@@ -37232,8 +37237,8 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
(args[0] - textContentItem.lastAdvanceWidth);
textContentItem.height +=
(args[1] - textContentItem.lastAdvanceHeight);
- var diff = (args[0] - textContentItem.lastAdvanceWidth) -
- (args[1] - textContentItem.lastAdvanceHeight);
+ diff = (args[0] - textContentItem.lastAdvanceWidth) -
+ (args[1] - textContentItem.lastAdvanceHeight);
addFakeSpaces(diff, textContentItem.str);
break;
}
@@ -37253,6 +37258,24 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
textState.carriageReturn();
break;
case OPS.setTextMatrix:
+ // Optimization to treat same line movement as advance.
+ advance = textState.calcTextLineMatrixAdvance(
+ args[0], args[1], args[2], args[3], args[4], args[5]);
+ if (advance !== null && textContentItem.initialized &&
+ advance.value > 0 &&
+ advance.value <= textContentItem.fakeMultiSpaceMax) {
+ textState.translateTextLineMatrix(advance.width,
+ advance.height);
+ textContentItem.width +=
+ (advance.width - textContentItem.lastAdvanceWidth);
+ textContentItem.height +=
+ (advance.height - textContentItem.lastAdvanceHeight);
+ diff = (advance.width - textContentItem.lastAdvanceWidth) -
+ (advance.height - textContentItem.lastAdvanceHeight);
+ addFakeSpaces(diff, textContentItem.str);
+ break;
+ }
+
flushTextContentItem();
textState.setTextMatrix(args[0], args[1], args[2], args[3],
args[4], args[5]);
@@ -38350,6 +38373,30 @@ var TextState = (function TextStateClosure() {
m[4] = m[0] * x + m[2] * y + m[4];
m[5] = m[1] * x + m[3] * y + m[5];
},
+ calcTextLineMatrixAdvance:
+ function TextState_calcTextLineMatrixAdvance(a, b, c, d, e, f) {
+ var font = this.font;
+ if (!font) {
+ return null;
+ }
+ var m = this.textLineMatrix;
+ if (!(a === m[0] && b === m[1] && c === m[2] && d === m[3])) {
+ return null;
+ }
+ var txDiff = e - m[4], tyDiff = f - m[5];
+ if ((font.vertical && txDiff !== 0) || (!font.vertical && tyDiff !== 0)) {
+ return null;
+ }
+ var tx, ty, denominator = a * d - b * c;
+ if (font.vertical) {
+ tx = -tyDiff * c / denominator;
+ ty = tyDiff * a / denominator;
+ } else {
+ tx = txDiff * d / denominator;
+ ty = -txDiff * b / denominator;
+ }
+ return { width: tx, height: ty, value: (font.vertical ? ty : tx), };
+ },
calcRenderMatrix: function TextState_calcRendeMatrix(ctm) {
// 9.4.4 Text Space Details
var tsm = [this.fontSize * this.textHScale, 0,
@@ -39202,28 +39249,49 @@ var Annotation = (function AnnotationClosure() {
}
Annotation.prototype = {
+ /**
+ * @private
+ */
+ _hasFlag: function Annotation_hasFlag(flags, flag) {
+ return !!(flags & flag);
+ },
+
+ /**
+ * @private
+ */
+ _isViewable: function Annotation_isViewable(flags) {
+ return !this._hasFlag(flags, AnnotationFlag.INVISIBLE) &&
+ !this._hasFlag(flags, AnnotationFlag.HIDDEN) &&
+ !this._hasFlag(flags, AnnotationFlag.NOVIEW);
+ },
+
+ /**
+ * @private
+ */
+ _isPrintable: function AnnotationFlag_isPrintable(flags) {
+ return this._hasFlag(flags, AnnotationFlag.PRINT) &&
+ !this._hasFlag(flags, AnnotationFlag.INVISIBLE) &&
+ !this._hasFlag(flags, AnnotationFlag.HIDDEN);
+ },
+
/**
* @return {boolean}
*/
get viewable() {
- if (this.flags) {
- return !this.hasFlag(AnnotationFlag.INVISIBLE) &&
- !this.hasFlag(AnnotationFlag.HIDDEN) &&
- !this.hasFlag(AnnotationFlag.NOVIEW);
+ if (this.flags === 0) {
+ return true;
}
- return true;
+ return this._isViewable(this.flags);
},
/**
* @return {boolean}
*/
get printable() {
- if (this.flags) {
- return this.hasFlag(AnnotationFlag.PRINT) &&
- !this.hasFlag(AnnotationFlag.INVISIBLE) &&
- !this.hasFlag(AnnotationFlag.HIDDEN);
+ if (this.flags === 0) {
+ return false;
}
- return false;
+ return this._isPrintable(this.flags);
},
/**
@@ -39236,11 +39304,7 @@ var Annotation = (function AnnotationClosure() {
* @see {@link shared/util.js}
*/
setFlags: function Annotation_setFlags(flags) {
- if (isInt(flags)) {
- this.flags = flags;
- } else {
- this.flags = 0;
- }
+ this.flags = (isInt(flags) && flags > 0) ? flags : 0;
},
/**
@@ -39254,10 +39318,7 @@ var Annotation = (function AnnotationClosure() {
* @see {@link shared/util.js}
*/
hasFlag: function Annotation_hasFlag(flag) {
- if (this.flags) {
- return (this.flags & flag) > 0;
- }
- return false;
+ return this._hasFlag(this.flags, flag);
},
/**
@@ -39835,6 +39896,16 @@ var PopupAnnotation = (function PopupAnnotationClosure() {
this.setColor(parentItem.getArray('C'));
this.data.color = this.color;
}
+
+ // If the Popup annotation is not viewable, but the parent annotation is,
+ // that is most likely a bug. Fallback to inherit the flags from the parent
+ // annotation (this is consistent with the behaviour in Adobe Reader).
+ if (!this.viewable) {
+ var parentFlags = parentItem.get('F');
+ if (this._isViewable(parentFlags)) {
+ this.setFlags(parentFlags);
+ }
+ }
}
Util.inherit(PopupAnnotation, Annotation, {});
diff --git a/browser/extensions/pdfjs/content/web/viewer.js b/browser/extensions/pdfjs/content/web/viewer.js
index e0736c240aa6..d89c947f0611 100644
--- a/browser/extensions/pdfjs/content/web/viewer.js
+++ b/browser/extensions/pdfjs/content/web/viewer.js
@@ -2956,7 +2956,7 @@ exports.PDFDocumentProperties = PDFDocumentProperties;
{
factory((root.pdfjsWebPDFFindController = {}), root.pdfjsWebUIUtils);
}
-}(this, function (exports, uiUtils, firefoxCom) {
+}(this, function (exports, uiUtils) {
var scrollIntoView = uiUtils.scrollIntoView;
@@ -3254,10 +3254,9 @@ var PDFFindController = (function PDFFindControllerClosure() {
* @param {number} index - match index.
* @param {Array} elements - text layer div elements array.
* @param {number} beginIdx - start index of the div array for the match.
- * @param {number} endIdx - end index of the div array for the match.
*/
updateMatchPosition: function PDFFindController_updateMatchPosition(
- pageIndex, index, elements, beginIdx, endIdx) {
+ pageIndex, index, elements, beginIdx) {
if (this.selected.matchIdx === index &&
this.selected.pageIdx === pageIndex) {
var spot = {
@@ -4995,7 +4994,6 @@ var PDFPageView = (function PDFPageViewClosure() {
var isScalingRestricted = false;
if (this.canvas && pdfjsLib.PDFJS.maxCanvasPixels > 0) {
var outputScale = this.outputScale;
- var pixelsInViewport = this.viewport.width * this.viewport.height;
if (((Math.floor(this.viewport.width) * outputScale.sx) | 0) *
((Math.floor(this.viewport.height) * outputScale.sy) | 0) >
pdfjsLib.PDFJS.maxCanvasPixels) {
@@ -5801,7 +5799,7 @@ var TextLayerBuilder = (function TextLayerBuilderClosure() {
if (this.findController) {
this.findController.updateMatchPosition(pageIdx, i, textDivs,
- begin.divIdx, end.divIdx);
+ begin.divIdx);
}
// Match inside new div.
@@ -7570,7 +7568,6 @@ var PDFViewerApplication = {
pdfViewer.setDocument(pdfDocument);
var firstPagePromise = pdfViewer.firstPagePromise;
var pagesPromise = pdfViewer.pagesPromise;
- var onePageRendered = pdfViewer.onePageRendered;
this.pageRotation = 0;
diff --git a/browser/locales/en-US/chrome/browser/aboutSearchReset.dtd b/browser/locales/en-US/chrome/browser/aboutSearchReset.dtd
new file mode 100644
index 000000000000..6e44d295ca4d
--- /dev/null
+++ b/browser/locales/en-US/chrome/browser/aboutSearchReset.dtd
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/browser/locales/en-US/chrome/browser/browser.dtd b/browser/locales/en-US/chrome/browser/browser.dtd
index 5794ed7e68e3..2e8f4eddf800 100644
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -682,7 +682,7 @@ you can use these alternative items. Otherwise, their values should be empty. -
-
+
diff --git a/browser/locales/jar.mn b/browser/locales/jar.mn
index f9aeb4a2ec72..f1ef7506ff95 100644
--- a/browser/locales/jar.mn
+++ b/browser/locales/jar.mn
@@ -17,6 +17,7 @@
#ifdef MOZ_SERVICES_HEALTHREPORT
locale/browser/aboutHealthReport.dtd (%chrome/browser/aboutHealthReport.dtd)
#endif
+ locale/browser/aboutSearchReset.dtd (%chrome/browser/aboutSearchReset.dtd)
locale/browser/aboutSessionRestore.dtd (%chrome/browser/aboutSessionRestore.dtd)
locale/browser/aboutTabCrashed.dtd (%chrome/browser/aboutTabCrashed.dtd)
locale/browser/syncCustomize.dtd (%chrome/browser/syncCustomize.dtd)
diff --git a/browser/themes/linux/browser.css b/browser/themes/linux/browser.css
index 29bfe57fe433..bdb1566bbd92 100644
--- a/browser/themes/linux/browser.css
+++ b/browser/themes/linux/browser.css
@@ -1018,8 +1018,7 @@ menuitem:not([type]):not(.menuitem-tooltip):not(.menuitem-iconic-tooltip) {
outline: 1px dotted -moz-DialogText;
}
-.indexedDB-notification-icon,
-#indexedDB-notification-icon {
+.indexedDB-icon {
list-style-image: url(moz-icon://stock/gtk-dialog-question?size=16);
}
diff --git a/browser/themes/shared/favicon-search-16.svg b/browser/themes/shared/favicon-search-16.svg
new file mode 100644
index 000000000000..e839cc8042af
--- /dev/null
+++ b/browser/themes/shared/favicon-search-16.svg
@@ -0,0 +1,10 @@
+
+
+