Merge mozilla-central to b2g-inbound

This commit is contained in:
Carsten "Tomcat" Book 2015-12-01 15:28:29 +01:00
Родитель 207c64c6c1 f3e1aec951
Коммит 31b570ce3c
623 изменённых файлов: 18485 добавлений и 13566 удалений

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

@ -34,6 +34,7 @@ else
configure_dir = $(topsrcdir)
endif
ifndef TEST_MOZBUILD
ifndef MOZ_PROFILE_USE
# We need to explicitly put backend.RecursiveMakeBackend here
# otherwise the rule in rules.mk doesn't run early enough.
@ -44,6 +45,7 @@ $(TIERS) binaries:: $(topsrcdir)/js/src/configure js/src/config.status
endif
endif
endif
endif
ifdef JS_STANDALONE
.PHONY: CLOBBER
@ -81,6 +83,7 @@ config.status js/src/config.status:
# The mach build driver will ensure the backend is up to date for partial tree
# builds. This cleanly avoids most of the pain.
ifndef TEST_MOZBUILD
backend.RecursiveMakeBackend:
@echo 'Build configuration changed. Regenerating backend.'
$(PYTHON) config.status
@ -91,6 +94,7 @@ Makefile: backend.RecursiveMakeBackend
include backend.RecursiveMakeBackend.pp
default:: backend.RecursiveMakeBackend
endif
install_manifests := \
$(addprefix dist/,bin branding idl include public private sdk xpi-stage) \

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

@ -12,40 +12,34 @@
// Accessible cache utils
////////////////////////////////////////////////////////////////////////////////
/**
* Shutdown and removes the accessible from cache.
*/
template <class T>
static PLDHashOperator
ClearCacheEntry(const void* aKey, RefPtr<T>& aAccessible, void* aUserArg)
void
UnbindCacheEntriesFromDocument(
nsRefPtrHashtable<nsPtrHashKey<const void>, T>& aCache)
{
NS_ASSERTION(aAccessible, "Calling ClearCacheEntry with a nullptr pointer!");
if (aAccessible && !aAccessible->IsDefunct())
aAccessible->Shutdown();
return PL_DHASH_REMOVE;
}
template <class T>
static PLDHashOperator
UnbindCacheEntryFromDocument(const void* aKey, RefPtr<T>& aAccessible,
void* aUserArg)
{
MOZ_ASSERT(aAccessible && !aAccessible->IsDefunct());
aAccessible->Document()->UnbindFromDocument(aAccessible);
return PL_DHASH_REMOVE;
for (auto iter = aCache.Iter(); !iter.Done(); iter.Next()) {
T* accessible = iter.Data();
MOZ_ASSERT(accessible && !accessible->IsDefunct());
accessible->Document()->UnbindFromDocument(accessible);
iter.Remove();
}
}
/**
* Clear the cache and shutdown the accessibles.
*/
template <class T>
static void
ClearCache(nsRefPtrHashtable<nsPtrHashKey<const void>, T>& aCache)
{
aCache.Enumerate(ClearCacheEntry<T>, nullptr);
for (auto iter = aCache.Iter(); !iter.Done(); iter.Next()) {
T* accessible = iter.Data();
MOZ_ASSERT(accessible);
if (accessible && !accessible->IsDefunct()) {
accessible->Shutdown();
}
iter.Remove();
}
}
#endif

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

@ -195,17 +195,12 @@ xpcAccessibleDocument::GetAccessible(Accessible* aAccessible)
return xpcAcc;
}
static PLDHashOperator
ShutdownAndRemove(const Accessible* aKey, RefPtr<xpcAccessibleGeneric>& aValue,
void* aUnused)
{
aValue->Shutdown();
return PL_DHASH_REMOVE;
}
void
xpcAccessibleDocument::Shutdown()
{
mCache.Enumerate(ShutdownAndRemove, nullptr);
for (auto iter = mCache.Iter(); !iter.Done(); iter.Next()) {
iter.Data()->Shutdown();
iter.Remove();
}
xpcAccessibleGeneric::Shutdown();
}

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

@ -145,8 +145,9 @@ XULTreeAccessible::Value(nsString& aValue)
void
XULTreeAccessible::Shutdown()
{
if (!mDoc->IsDefunct())
mAccessibleCache.Enumerate(UnbindCacheEntryFromDocument<Accessible>, nullptr);
if (!mDoc->IsDefunct()) {
UnbindCacheEntriesFromDocument(mAccessibleCache);
}
mTree = nullptr;
mTreeView = nullptr;
@ -550,8 +551,7 @@ XULTreeAccessible::InvalidateCache(int32_t aRow, int32_t aCount)
return;
if (!mTreeView) {
mAccessibleCache.Enumerate(UnbindCacheEntryFromDocument<Accessible>,
nullptr);
UnbindCacheEntriesFromDocument(mAccessibleCache);
return;
}
@ -609,8 +609,7 @@ XULTreeAccessible::TreeViewInvalidated(int32_t aStartRow, int32_t aEndRow,
return;
if (!mTreeView) {
mAccessibleCache.Enumerate(UnbindCacheEntryFromDocument<Accessible>,
nullptr);
UnbindCacheEntriesFromDocument(mAccessibleCache);
return;
}
@ -669,8 +668,7 @@ XULTreeAccessible::TreeViewChanged(nsITreeView* aView)
Document()->FireDelayedEvent(reorderEvent);
// Clear cache.
mAccessibleCache.Enumerate(UnbindCacheEntryFromDocument<Accessible>,
nullptr);
UnbindCacheEntriesFromDocument(mAccessibleCache);
mTreeView = aView;
}
@ -687,7 +685,7 @@ XULTreeAccessible::CreateTreeItemAccessible(int32_t aRow) const
return accessible.forget();
}
////////////////////////////////////////////////////////////////////////////////
// XULTreeItemAccessibleBase
////////////////////////////////////////////////////////////////////////////////

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

@ -277,8 +277,7 @@ void
XULTreeGridRowAccessible::Shutdown()
{
if (!mDoc->IsDefunct()) {
mAccessibleCache.Enumerate(UnbindCacheEntryFromDocument<XULTreeGridCellAccessible>,
nullptr);
UnbindCacheEntriesFromDocument(mAccessibleCache);
}
XULTreeItemAccessibleBase::Shutdown();

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

@ -9,6 +9,9 @@
# 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/.
# Makefile.in uses a misc target through test_addons_TARGET.
HAS_MISC_RULE = True
BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
JETPACK_PACKAGE_MANIFESTS += ['source/test/jetpack-package.ini']
JETPACK_ADDON_MANIFESTS += ['source/test/addons/jetpack-addon.ini']

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

@ -4,6 +4,9 @@
# 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/.
# Makefile.in uses a misc target through test_addons_TARGET.
HAS_MISC_RULE = True
BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
JETPACK_PACKAGE_MANIFESTS += ['source/test/jetpack-package.ini']
JETPACK_ADDON_MANIFESTS += ['source/test/addons/jetpack-addon.ini']

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

@ -74,10 +74,10 @@ if CONFIG['OS_ARCH'] == 'WINNT':
if CONFIG['GNU_CXX']:
CXXFLAGS += ['-Wshadow']
JS_PREFERENCE_FILES += [
JS_PREFERENCE_PP_FILES += [
'b2g.js',
]
DIST_FILES += [
FINAL_TARGET_PP_FILES += [
'ua-update.json.in',
]

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

@ -8,4 +8,4 @@
% locale branding @AB_CD@ %locale/branding/
# Branding only exists in en-US
locale/branding/brand.dtd (en-US/brand.dtd)
* locale/branding/brand.properties (en-US/brand.properties)
locale/branding/brand.properties (en-US/brand.properties)

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

@ -8,4 +8,4 @@
% locale branding @AB_CD@ %locale/branding/
# Branding only exists in en-US
locale/branding/brand.dtd (en-US/brand.dtd)
* locale/branding/brand.properties (en-US/brand.properties)
locale/branding/brand.properties (en-US/brand.properties)

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

@ -8,4 +8,4 @@
% locale branding @AB_CD@ %locale/branding/
# Nightly branding only exists in en-US
locale/branding/brand.dtd (en-US/brand.dtd)
* locale/branding/brand.properties (en-US/brand.properties)
locale/branding/brand.properties (en-US/brand.properties)

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

@ -5,8 +5,11 @@
DIST_SUBDIR = 'browser'
export('DIST_SUBDIR')
JS_PREFERENCE_FILES += [
'/b2g/app/b2g.js',
'/b2g/dev/app/mulet.js',
JS_PREFERENCE_PP_FILES += [
'../../app/b2g.js',
]
JS_PREFERENCE_FILES += [
'mulet.js',
]

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

@ -15,6 +15,13 @@
"unpack": true
},
{
"size": 73029932,
"digest": "ef1818acf065838dcb72554e521f9fd7098f0a3690cb6a3106d7bf18f46c342bfdd5a2b7d86e92ee3ddb9e478380343e58ecf8fd242807b8881a2d53fbec5ab3",
"algorithm": "sha512",
"filename": "rustc.tar.xz",
"unpack": true
},
{
"size": 167175,
"digest": "0b71a936edf5bd70cf274aaa5d7abc8f77fe8e7b5593a208f805cc9436fac646b9c4f0b43c2b10de63ff3da671497d35536077ecbc72dba7f8159a38b580f831",
"algorithm": "sha512",

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

@ -9,8 +9,8 @@
% override chrome://global/locale/aboutCertError.dtd chrome://b2g-l10n/locale/aboutCertError.dtd
% override chrome://global/locale/appstrings.properties chrome://b2g-l10n/locale/appstrings.properties
* locale/@AB_CD@/b2g-l10n/aboutCertError.dtd (%chrome/overrides/aboutCertError.dtd)
* locale/@AB_CD@/b2g-l10n/appstrings.properties (%chrome/overrides/appstrings.properties)
locale/@AB_CD@/b2g-l10n/aboutCertError.dtd (%chrome/overrides/aboutCertError.dtd)
locale/@AB_CD@/b2g-l10n/appstrings.properties (%chrome/overrides/appstrings.properties)
#ifdef MOZ_GRAPHENE
locale/@AB_CD@/b2g-l10n/graphene.properties (%chrome/graphene.properties)
#endif

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

@ -11,7 +11,7 @@ if CONFIG['OS_ARCH'] == 'WINNT' and CONFIG['MOZ_ASAN']:
else:
GeckoProgram(CONFIG['MOZ_APP_NAME'], msvcrt='static')
JS_PREFERENCE_FILES += [
JS_PREFERENCE_PP_FILES += [
'profile/firefox.js',
]

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

@ -6,6 +6,6 @@
FINAL_TARGET = 'dist/bin/browser/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}'
DIST_FILES += [
FINAL_TARGET_PP_FILES += [
'install.rdf.in',
]

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

@ -1608,17 +1608,13 @@ pref("browser.pocket.enabledLocales", "cs de en-GB en-US en-ZA es-ES es-MX fr hu
pref("view_source.tab", true);
#ifndef RELEASE_BUILD
// Enable ServiceWorkers for Push API consumers.
// Interception is still disabled on beta and release.
pref("dom.serviceWorkers.enabled", true);
pref("dom.serviceWorkers.interception.enabled", true);
pref("dom.serviceWorkers.openWindow.enabled", true);
#ifndef RELEASE_BUILD
// Enable Push API.
pref("dom.push.enabled", true);
pref("dom.serviceWorkers.openWindow.enabled", true);
#endif
// These are the thumbnail width/height set in about:newtab.

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

@ -1346,8 +1346,7 @@ nsContextMenu.prototype = {
// checks after redirects, see bug: 1136055
var channel = NetUtil.newChannel({
uri: makeURI(linkURL),
loadUsingSystemPrincipal: true,
securityFlags: Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL
loadUsingSystemPrincipal: true
});
if (linkDownload)

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

@ -273,7 +273,7 @@ var RemoteTabViewer = {
}.bind(this);
return CloudSync().tabs.getRemoteTabs()
.then(updateTabList, Promise.reject);
.then(updateTabList, Promise.reject.bind(Promise));
},
adjustContextMenu: function (event) {

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

@ -513,16 +513,26 @@ var PageStyleHandler = {
}
}
// We won't send data URIs all of the way up to the parent, as these
// can be arbitrarily large.
let URI = Services.io.newURI(currentStyleSheet.href, null, null);
let sentURI = URI.scheme == "data" ? null : URI.spec;
let URI;
try {
URI = Services.io.newURI(currentStyleSheet.href, null, null);
} catch(e) {
if (e.result != Cr.NS_ERROR_MALFORMED_URI) {
throw e;
}
}
result.push({
title: currentStyleSheet.title,
disabled: currentStyleSheet.disabled,
href: sentURI,
});
if (URI) {
// We won't send data URIs all of the way up to the parent, as these
// can be arbitrarily large.
let sentURI = URI.scheme == "data" ? null : URI.spec;
result.push({
title: currentStyleSheet.title,
disabled: currentStyleSheet.disabled,
href: sentURI,
});
}
}
return result;

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

@ -7,5 +7,5 @@
@AB_CD@.jar:
% locale branding @AB_CD@ %locale/branding/
locale/branding/brand.dtd (%brand.dtd)
* locale/branding/brand.properties (%brand.properties)
* locale/branding/browserconfig.properties
locale/branding/brand.properties (%brand.properties)
locale/branding/browserconfig.properties

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

@ -55,6 +55,13 @@ const kSubviewEvents = [
*/
var kVersion = 4;
/**
* Buttons removed from built-ins by version they were removed. kVersion must be
* bumped any time a new id is added to this. Use the button id as key, and
* version the button is removed in as the value. e.g. "pocket-button": 5
*/
var ObsoleteBuiltinButtons = {};
/**
* gPalette is a map of every widget that CustomizableUI.jsm knows about, keyed
* on their IDs.
@ -154,6 +161,7 @@ var CustomizableUIInternal = {
this._defineBuiltInWidgets();
this.loadSavedState();
this._introduceNewBuiltinWidgets();
this._markObsoleteBuiltinButtonsSeen();
let panelPlacements = [
"edit-controls",
@ -352,6 +360,26 @@ var CustomizableUIInternal = {
}
},
/**
* _markObsoleteBuiltinButtonsSeen
* when upgrading, ensure obsoleted buttons are in seen state.
*/
_markObsoleteBuiltinButtonsSeen: function() {
if (!gSavedState)
return;
let currentVersion = gSavedState.currentVersion;
if (currentVersion >= kVersion)
return;
// we're upgrading, update state if necessary
for (let id in ObsoleteBuiltinButtons) {
let version = ObsoleteBuiltinButtons[id]
if (version == kVersion) {
gSeenWidgets.add(id);
gDirty = true;
}
}
},
_placeNewDefaultWidgetsInArea: function(aArea) {
let futurePlacedWidgets = gFuturePlacements.get(aArea);
let savedPlacements = gSavedState && gSavedState.placements && gSavedState.placements[aArea];
@ -589,7 +617,7 @@ var CustomizableUIInternal = {
legacyState = legacyState.split(",").filter(s => s);
}
// Manually restore the state here, so the legacy state can be converted.
// Manually restore the state here, so the legacy state can be converted.
this.restoreStateForArea(area, legacyState);
placements = gPlacements.get(area);
}
@ -1620,7 +1648,7 @@ var CustomizableUIInternal = {
// We can't use event.target because we might have passed a panelview
// anonymous content boundary as well, and so target points to the
// panelmultiview in that case. Unfortunately, this means we get
// anonymous child nodes instead of the real ones, so looking for the
// anonymous child nodes instead of the real ones, so looking for the
// 'stoooop, don't close me' attributes is more involved.
let target = aEvent.originalTarget;
let closemenu = "auto";
@ -1863,7 +1891,7 @@ var CustomizableUIInternal = {
// Note that this does not populate gPlacements, which is done lazily so that
// the legacy state can be migrated, which is only available once a browser
// window is openned.
// The panel area is an exception here, since it has no legacy state and is
// The panel area is an exception here, since it has no legacy state and is
// built lazily - and therefore wouldn't otherwise result in restoring its
// state immediately when a browser window opens, which is important for
// other consumers of this API.
@ -3843,7 +3871,7 @@ function XULWidgetGroupWrapper(aWidgetId) {
}
/**
* A XULWidgetSingleWrapper is a wrapper around a single instance of a XUL
* A XULWidgetSingleWrapper is a wrapper around a single instance of a XUL
* widget in a particular window.
*/
function XULWidgetSingleWrapper(aWidgetId, aNode, aDocument) {

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

@ -788,8 +788,8 @@ nsDefaultCommandLineHandler.prototype = {
// * Cortana voice searches use "FORM=WNSBOX" or direct results, or "FORM=WNSFC2"
// for "see more results on Bing.com")
// * Cortana voice searches started from "Hey, Cortana" use "form=WNSHCO"
// or "form=WNSSSV"
var allowedParams = ["WNSGPH", "WNSBOX", "WNSFC2", "WNSHCO", "WNSSSV"];
// or "form=WNSSSV" or "form=WNSSCX"
var allowedParams = ["WNSGPH", "WNSBOX", "WNSFC2", "WNSHCO", "WNSSCX", "WNSSSV"];
var formParam = params.get("form");
if (!formParam) {
formParam = params.get("FORM");

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

@ -219,6 +219,15 @@ FrameTreeInternal.prototype = {
return;
}
// onStateChange will be fired when loading the initial about:blank URI for
// a browser, which we don't actually care about. This is particularly for
// the case of unrestored background tabs, where the content has not yet
// been restored: we don't want to accidentally send any updates to the
// parent when the about:blank placeholder page has loaded.
if (!this._chromeGlobal.docShell.hasLoadedNonBlankURI) {
return;
}
if (stateFlags & Ci.nsIWebProgressListener.STATE_START) {
// Clear the list of frames until we can recollect it.
this._frames.clear();

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

@ -3,8 +3,9 @@
"use strict";
const URL = ROOT + "browser_scrollPositions_sample.html";
const URL_FRAMESET = ROOT + "browser_scrollPositions_sample_frameset.html";
const BASE = "http://example.com/browser/browser/components/sessionstore/test/"
const URL = BASE + "browser_scrollPositions_sample.html";
const URL_FRAMESET = BASE + "browser_scrollPositions_sample_frameset.html";
// Randomized set of scroll positions we will use in this test.
const SCROLL_X = Math.round(100 * (1 + Math.random()));
@ -102,6 +103,53 @@ add_task(function test_scroll_nested() {
yield promiseRemoveTab(tab2);
});
/**
* Test that scroll positions persist after restoring background tabs in
* a restored window (bug 1228518).
*/
add_task(function test_scroll_background_tabs() {
pushPrefs(["browser.sessionstore.restore_on_demand", true]);
let newWin = yield BrowserTestUtils.openNewBrowserWindow();
let tab = newWin.gBrowser.addTab(URL);
let browser = tab.linkedBrowser;
yield BrowserTestUtils.browserLoaded(browser);
// Scroll down a little.
yield sendMessage(browser, "ss-test:setScrollPosition", {x: SCROLL_X, y: SCROLL_Y});
yield checkScroll(tab, {scroll: SCROLL_STR}, "scroll is fine");
// Close the window
yield BrowserTestUtils.closeWindow(newWin);
// Now restore the window
newWin = ss.undoCloseWindow(0);
// Make sure to wait for the window to be restored.
yield BrowserTestUtils.waitForEvent(newWin, "SSWindowStateReady");
is(newWin.gBrowser.tabs.length, 2, "There should be two tabs");
// The second tab should be the one we loaded URL at still
tab = newWin.gBrowser.tabs[1];
yield promiseTabRestoring(tab);
ok(tab.hasAttribute("pending"), "Tab should be pending");
browser = tab.linkedBrowser;
// Ensure there are no pending queued messages in the child.
yield TabStateFlusher.flush(browser);
// Now check to see if the background tab remembers where it
// should be scrolled to.
newWin.gBrowser.selectedTab = tab;
yield promiseTabRestored(tab);
yield checkScroll(tab, {scroll: SCROLL_STR}, "scroll is still fine");
yield BrowserTestUtils.closeWindow(newWin);
});
function* checkScroll(tab, expected, msg) {
let browser = tab.linkedBrowser;
yield TabStateFlusher.flush(browser);

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

@ -18,5 +18,6 @@ export MOZ_PACKAGE_JSSHELL=1
ac_add_options --with-branding=browser/branding/nightly
. "$topsrcdir/build/unix/mozconfig.rust"
. "$topsrcdir/build/mozconfig.common.override"
. "$topsrcdir/build/mozconfig.cache"

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

@ -10,5 +10,6 @@ STRIP_FLAGS="--strip-debug"
ac_add_options --with-branding=browser/branding/nightly
. "$topsrcdir/build/unix/mozconfig.rust"
. "$topsrcdir/build/mozconfig.common.override"
. "$topsrcdir/build/mozconfig.cache"

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

@ -40,6 +40,7 @@ whitelist['nightly']['linux64'] += [
'STRIP_FLAGS="--strip-debug"',
'ac_add_options --with-ccache=/usr/bin/ccache',
'. "$topsrcdir/build/mozconfig.cache"',
'. "$topsrcdir/build/unix/mozconfig.rust"',
]
whitelist['nightly']['macosx-universal'] += [

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

@ -19,5 +19,12 @@
"algorithm": "sha512",
"filename": "sccache.tar.bz2",
"unpack": true
},
{
"size": 73029932,
"digest": "ef1818acf065838dcb72554e521f9fd7098f0a3690cb6a3106d7bf18f46c342bfdd5a2b7d86e92ee3ddb9e478380343e58ecf8fd242807b8881a2d53fbec5ab3",
"algorithm": "sha512",
"filename": "rustc.tar.xz",
"unpack": true
}
]

4
browser/extensions/loop/bootstrap.js поставляемый
Просмотреть файл

@ -508,7 +508,7 @@ var WindowListener = {
let box = gBrowser.getNotificationBox();
let paused = false;
let bar = box.appendNotification(
this._getString("infobar_screenshare_browser_message"),
this._getString("infobar_screenshare_browser_message2"),
kBrowserSharingNotificationId,
// Icon is defined in browser theme CSS.
null,
@ -520,7 +520,7 @@ var WindowListener = {
callback: (event, buttonInfo, buttonNode) => {
paused = !paused;
bar.label = paused ? this._getString("infobar_screenshare_paused_browser_message") :
this._getString("infobar_screenshare_browser_message");
this._getString("infobar_screenshare_browser_message2");
bar.classList.toggle("paused", paused);
buttonNode.label = paused ? this._getString("infobar_button_resume_label") :
this._getString("infobar_button_pause_label");

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

@ -151,7 +151,11 @@ var loop = loop || {};
return;
}
gSubscriptionsMap[eventName].forEach(function(cb) {
cb.apply(null, message.data[1]);
var data = message.data[1];
if (!Array.isArray(data)) {
data = [data];
}
cb.apply(null, data);
});
});
}

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

@ -10,7 +10,7 @@ FINAL_TARGET_FILES += [
'bootstrap.js'
]
DIST_FILES += [
FINAL_TARGET_PP_FILES += [
'install.rdf.in'
]

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

@ -16,7 +16,7 @@ LOOPDIR=browser/extensions/loop
ESLINT=standalone/node_modules/.bin/eslint
if [ -x "${LOOPDIR}/${ESLINT}" ]; then
echo 'running eslint; see http://eslint.org/docs/rules/ for error info'
(cd ${LOOPDIR} && ./${ESLINT} --ext .js --ext .jsm --ext .jsx .)
(./${LOOPDIR}/${ESLINT} --ext .js --ext .jsm --ext .jsx ${LOOPDIR})
if [ $? != 0 ]; then
exit 1;
fi

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

@ -243,6 +243,16 @@ describe("loopapi-client", function() {
sinon.assert.calledOnce(stub3);
sinon.assert.calledWithExactly(stub3, "Foo", "Bar");
});
it("should invoke subscription with non-array arguments too", function() {
var stub = sinon.stub();
loop.subscribe("LoopStatusChanged", stub);
sendMessage({ data: ["LoopStatusChanged", "Foo"] });
sinon.assert.calledOnce(stub);
sinon.assert.calledWithExactly(stub, "Foo");
});
});
describe("unsubscribe", function() {

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

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

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

@ -12,6 +12,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* jshint esnext:true */
/* globals Components, Services, XPCOMUtils, PdfjsChromeUtils,
PdfjsContentUtils, DEFAULT_PREFERENCES, PdfStreamConverter */
'use strict';
var EXPORTED_SYMBOLS = ['PdfJs'];

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

@ -12,6 +12,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* jshint esnext:true */
/* globals Components, Services, XPCOMUtils, DEFAULT_PREFERENCES */
'use strict';
var EXPORTED_SYMBOLS = ['PdfjsChromeUtils'];

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

@ -20,8 +20,8 @@ if (typeof PDFJS === 'undefined') {
(typeof window !== 'undefined' ? window : this).PDFJS = {};
}
PDFJS.version = '1.3.14';
PDFJS.build = 'df46b64';
PDFJS.version = '1.3.42';
PDFJS.build = '84a47f8';
(function pdfjsWrapper() {
// Use strict in our context only - users might not want it
@ -60,6 +60,19 @@ var AnnotationType = {
LINK: 3
};
var AnnotationFlag = {
INVISIBLE: 0x01,
HIDDEN: 0x02,
PRINT: 0x04,
NOZOOM: 0x08,
NOROTATE: 0x10,
NOVIEW: 0x20,
READONLY: 0x40,
LOCKED: 0x80,
TOGGLENOVIEW: 0x100,
LOCKEDCONTENTS: 0x200
};
var AnnotationBorderStyleType = {
SOLID: 1,
DASHED: 2,
@ -1186,26 +1199,20 @@ PDFJS.createObjectURL = (function createObjectURLClosure() {
};
})();
function MessageHandler(name, comObj) {
this.name = name;
function MessageHandler(sourceName, targetName, comObj) {
this.sourceName = sourceName;
this.targetName = targetName;
this.comObj = comObj;
this.callbackIndex = 1;
this.postMessageTransfers = true;
var callbacksCapabilities = this.callbacksCapabilities = {};
var ah = this.actionHandler = {};
ah['console_log'] = [function ahConsoleLog(data) {
console.log.apply(console, data);
}];
ah['console_error'] = [function ahConsoleError(data) {
console.error.apply(console, data);
}];
ah['_unsupported_feature'] = [function ah_unsupportedFeature(data) {
UnsupportedManager.notify(data);
}];
comObj.onmessage = function messageHandlerComObjOnMessage(event) {
this._onComObjOnMessage = function messageHandlerComObjOnMessage(event) {
var data = event.data;
if (data.targetName !== this.sourceName) {
return;
}
if (data.isReply) {
var callbackId = data.callbackId;
if (data.callbackId in callbacksCapabilities) {
@ -1222,10 +1229,14 @@ function MessageHandler(name, comObj) {
} else if (data.action in ah) {
var action = ah[data.action];
if (data.callbackId) {
var sourceName = this.sourceName;
var targetName = data.sourceName;
Promise.resolve().then(function () {
return action[0].call(action[1], data.data);
}).then(function (result) {
comObj.postMessage({
sourceName: sourceName,
targetName: targetName,
isReply: true,
callbackId: data.callbackId,
data: result
@ -1236,6 +1247,8 @@ function MessageHandler(name, comObj) {
reason = reason + '';
}
comObj.postMessage({
sourceName: sourceName,
targetName: targetName,
isReply: true,
callbackId: data.callbackId,
error: reason
@ -1247,7 +1260,8 @@ function MessageHandler(name, comObj) {
} else {
error('Unknown action from worker: ' + data.action);
}
};
}.bind(this);
comObj.addEventListener('message', this._onComObjOnMessage);
}
MessageHandler.prototype = {
@ -1266,6 +1280,8 @@ MessageHandler.prototype = {
*/
send: function messageHandlerSend(actionName, data, transfers) {
var message = {
sourceName: this.sourceName,
targetName: this.targetName,
action: actionName,
data: data
};
@ -1283,6 +1299,8 @@ MessageHandler.prototype = {
function messageHandlerSendWithPromise(actionName, data, transfers) {
var callbackId = this.callbackIndex++;
var message = {
sourceName: this.sourceName,
targetName: this.targetName,
action: actionName,
data: data,
callbackId: callbackId
@ -1308,6 +1326,10 @@ MessageHandler.prototype = {
} else {
this.comObj.postMessage(message);
}
},
destroy: function () {
this.comObj.removeEventListener('message', this._onComObjOnMessage);
}
};
@ -1476,6 +1498,9 @@ PDFJS.maxCanvasPixels = (PDFJS.maxCanvasPixels === undefined ?
/**
* (Deprecated) Opens external links in a new window if enabled.
* The default behavior opens external links in the PDF.js window.
*
* NOTE: This property has been deprecated, please use
* `PDFJS.externalLinkTarget = PDFJS.LinkTarget.BLANK` instead.
* @var {boolean}
*/
PDFJS.openExternalLinksInNewWindow = (
@ -1525,6 +1550,8 @@ PDFJS.isEvalSupported = (PDFJS.isEvalSupported === undefined ?
* @property {number} rangeChunkSize - Optional parameter to specify
* maximum number of bytes fetched per range request. The default value is
* 2^16 = 65536.
* @property {PDFWorker} worker - The worker that will be used for the loading
* and parsing of the PDF data.
*/
/**
@ -1587,7 +1614,6 @@ PDFJS.getDocument = function getDocument(src,
task.onPassword = passwordCallback || null;
task.onProgress = progressCallback || null;
var workerInitializedCapability, transport;
var source;
if (typeof src === 'string') {
source = { url: src };
@ -1608,12 +1634,18 @@ PDFJS.getDocument = function getDocument(src,
}
var params = {};
var rangeTransport = null;
var worker = null;
for (var key in source) {
if (key === 'url' && typeof window !== 'undefined') {
// The full path is required in the 'url' field.
params[key] = combineUrl(window.location.href, source[key]);
continue;
} else if (key === 'range') {
rangeTransport = source[key];
continue;
} else if (key === 'worker') {
worker = source[key];
continue;
} else if (key === 'data' && !(source[key] instanceof Uint8Array)) {
// Converting string or array-like data to Uint8Array.
@ -1634,27 +1666,98 @@ PDFJS.getDocument = function getDocument(src,
params[key] = source[key];
}
params.rangeChunkSize = source.rangeChunkSize || DEFAULT_RANGE_CHUNK_SIZE;
params.rangeChunkSize = params.rangeChunkSize || DEFAULT_RANGE_CHUNK_SIZE;
workerInitializedCapability = createPromiseCapability();
transport = new WorkerTransport(workerInitializedCapability, source.range);
workerInitializedCapability.promise.then(function transportInitialized() {
transport.fetchDocument(task, params);
});
task._transport = transport;
if (!worker) {
// Worker was not provided -- creating and owning our own.
worker = new PDFWorker();
task._worker = worker;
}
var docId = task.docId;
worker.promise.then(function () {
if (task.destroyed) {
throw new Error('Loading aborted');
}
return _fetchDocument(worker, params, rangeTransport, docId).then(
function (workerId) {
if (task.destroyed) {
throw new Error('Loading aborted');
}
var messageHandler = new MessageHandler(docId, workerId, worker.port);
messageHandler.send('Ready', null);
var transport = new WorkerTransport(messageHandler, task, rangeTransport);
task._transport = transport;
});
}, task._capability.reject);
return task;
};
/**
* Starts fetching of specified PDF document/data.
* @param {PDFWorker} worker
* @param {Object} source
* @param {PDFDataRangeTransport} pdfDataRangeTransport
* @param {string} docId Unique document id, used as MessageHandler id.
* @returns {Promise} The promise, which is resolved when worker id of
* MessageHandler is known.
* @private
*/
function _fetchDocument(worker, source, pdfDataRangeTransport, docId) {
if (worker.destroyed) {
return Promise.reject(new Error('Worker was destroyed'));
}
source.disableAutoFetch = PDFJS.disableAutoFetch;
source.disableStream = PDFJS.disableStream;
source.chunkedViewerLoading = !!pdfDataRangeTransport;
if (pdfDataRangeTransport) {
source.length = pdfDataRangeTransport.length;
source.initialData = pdfDataRangeTransport.initialData;
}
return worker.messageHandler.sendWithPromise('GetDocRequest', {
docId: docId,
source: source,
disableRange: PDFJS.disableRange,
maxImageSize: PDFJS.maxImageSize,
cMapUrl: PDFJS.cMapUrl,
cMapPacked: PDFJS.cMapPacked,
disableFontFace: PDFJS.disableFontFace,
disableCreateObjectURL: PDFJS.disableCreateObjectURL,
verbosity: PDFJS.verbosity
}).then(function (workerId) {
if (worker.destroyed) {
throw new Error('Worker was destroyed');
}
return workerId;
});
}
/**
* PDF document loading operation.
* @class
* @alias PDFDocumentLoadingTask
*/
var PDFDocumentLoadingTask = (function PDFDocumentLoadingTaskClosure() {
var nextDocumentId = 0;
/** @constructs PDFDocumentLoadingTask */
function PDFDocumentLoadingTask() {
this._capability = createPromiseCapability();
this._transport = null;
this._worker = null;
/**
* Unique document loading task id -- used in MessageHandlers.
* @type {string}
*/
this.docId = 'd' + (nextDocumentId++);
/**
* Shows if loading task is destroyed.
* @type {boolean}
*/
this.destroyed = false;
/**
* Callback to request a password if wrong or no password was provided.
@ -1686,7 +1789,17 @@ var PDFDocumentLoadingTask = (function PDFDocumentLoadingTaskClosure() {
* is completed.
*/
destroy: function () {
return this._transport.destroy();
this.destroyed = true;
var transportDestroyed = !this._transport ? Promise.resolve() :
this._transport.destroy();
return transportDestroyed.then(function () {
this._transport = null;
if (this._worker) {
this._worker.destroy();
this._worker = null;
}
}.bind(this));
},
/**
@ -1915,12 +2028,20 @@ var PDFDocumentProxy = (function PDFDocumentProxyClosure() {
* Destroys current document instance and terminates worker.
*/
destroy: function PDFDocumentProxy_destroy() {
return this.transport.destroy();
return this.loadingTask.destroy();
}
};
return PDFDocumentProxy;
})();
/**
* Page getTextContent parameters.
*
* @typedef {Object} getTextContentParameters
* @param {boolean} normalizeWhitespace - replaces all occurrences of
* whitespace with standard spaces (0x20). The default value is `false`.
*/
/**
* Page text content.
*
@ -1952,6 +2073,16 @@ var PDFDocumentProxy = (function PDFDocumentProxyClosure() {
* @property {string} fontFamily - possible font family
*/
/**
* Page annotation parameters.
*
* @typedef {Object} GetAnnotationsParameters
* @param {string} intent - Determines the annotations that will be fetched,
* can be either 'display' (viewable annotations) or 'print'
* (printable annotations).
* If the parameter is omitted, all annotations are fetched.
*/
/**
* Page render parameters.
*
@ -2040,12 +2171,17 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
return new PDFJS.PageViewport(this.view, scale, rotate, 0, 0);
},
/**
* @param {GetAnnotationsParameters} params - Annotation parameters.
* @return {Promise} A promise that is resolved with an {Array} of the
* annotation objects.
*/
getAnnotations: function PDFPageProxy_getAnnotations() {
if (!this.annotationsPromise) {
this.annotationsPromise = this.transport.getAnnotations(this.pageIndex);
getAnnotations: function PDFPageProxy_getAnnotations(params) {
var intent = (params && params.intent) || null;
if (!this.annotationsPromise || this.annotationsIntent !== intent) {
this.annotationsPromise = this.transport.getAnnotations(this.pageIndex,
intent);
this.annotationsIntent = intent;
}
return this.annotationsPromise;
},
@ -2184,12 +2320,16 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
},
/**
* @param {getTextContentParameters} params - getTextContent parameters.
* @return {Promise} That is resolved a {@link TextContent}
* object that represent the page text content.
*/
getTextContent: function PDFPageProxy_getTextContent() {
getTextContent: function PDFPageProxy_getTextContent(params) {
var normalizeWhitespace = (params && params.normalizeWhitespace) || false;
return this.transport.messageHandler.sendWithPromise('GetTextContent', {
pageIndex: this.pageNumber - 1
pageIndex: this.pageNumber - 1,
normalizeWhitespace: normalizeWhitespace,
});
},
@ -2296,17 +2436,202 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
return PDFPageProxy;
})();
/**
* PDF.js web worker abstraction, it controls instantiation of PDF documents and
* WorkerTransport for them. If creation of a web worker is not possible,
* a "fake" worker will be used instead.
* @class
*/
var PDFWorker = (function PDFWorkerClosure() {
var nextFakeWorkerId = 0;
// Loads worker code into main thread.
function setupFakeWorkerGlobal() {
if (!PDFJS.fakeWorkerFilesLoadedCapability) {
PDFJS.fakeWorkerFilesLoadedCapability = createPromiseCapability();
// In the developer build load worker_loader which in turn loads all the
// other files and resolves the promise. In production only the
// pdf.worker.js file is needed.
Util.loadScript(PDFJS.workerSrc, function() {
PDFJS.fakeWorkerFilesLoadedCapability.resolve();
});
}
return PDFJS.fakeWorkerFilesLoadedCapability.promise;
}
function PDFWorker(name) {
this.name = name;
this.destroyed = false;
this._readyCapability = createPromiseCapability();
this._port = null;
this._webWorker = null;
this._messageHandler = null;
this._initialize();
}
PDFWorker.prototype = /** @lends PDFWorker.prototype */ {
get promise() {
return this._readyCapability.promise;
},
get port() {
return this._port;
},
get messageHandler() {
return this._messageHandler;
},
_initialize: function PDFWorker_initialize() {
// If worker support isn't disabled explicit and the browser has worker
// support, create a new web worker and test if it/the browser fullfills
// all requirements to run parts of pdf.js in a web worker.
// Right now, the requirement is, that an Uint8Array is still an
// Uint8Array as it arrives on the worker. (Chrome added this with v.15.)
if (!globalScope.PDFJS.disableWorker && typeof Worker !== 'undefined') {
var workerSrc = PDFJS.workerSrc;
if (!workerSrc) {
error('No PDFJS.workerSrc specified');
}
try {
// Some versions of FF can't create a worker on localhost, see:
// https://bugzilla.mozilla.org/show_bug.cgi?id=683280
var worker = new Worker(workerSrc);
var messageHandler = new MessageHandler('main', 'worker', worker);
messageHandler.on('test', function PDFWorker_test(data) {
if (this.destroyed) {
this._readyCapability.reject(new Error('Worker was destroyed'));
messageHandler.destroy();
worker.terminate();
return; // worker was destroyed
}
var supportTypedArray = data && data.supportTypedArray;
if (supportTypedArray) {
this._messageHandler = messageHandler;
this._port = worker;
this._webWorker = worker;
if (!data.supportTransfers) {
PDFJS.postMessageTransfers = false;
}
this._readyCapability.resolve();
} else {
this._setupFakeWorker();
messageHandler.destroy();
worker.terminate();
}
}.bind(this));
messageHandler.on('console_log', function (data) {
console.log.apply(console, data);
});
messageHandler.on('console_error', function (data) {
console.error.apply(console, data);
});
messageHandler.on('_unsupported_feature', function (data) {
UnsupportedManager.notify(data);
});
var testObj = new Uint8Array([PDFJS.postMessageTransfers ? 255 : 0]);
// Some versions of Opera throw a DATA_CLONE_ERR on serializing the
// typed array. Also, checking if we can use transfers.
try {
messageHandler.send('test', testObj, [testObj.buffer]);
} catch (ex) {
info('Cannot use postMessage transfers');
testObj[0] = 0;
messageHandler.send('test', testObj);
}
return;
} catch (e) {
info('The worker has been disabled.');
}
}
// Either workers are disabled, not supported or have thrown an exception.
// Thus, we fallback to a faked worker.
this._setupFakeWorker();
},
_setupFakeWorker: function PDFWorker_setupFakeWorker() {
warn('Setting up fake worker.');
globalScope.PDFJS.disableWorker = true;
setupFakeWorkerGlobal().then(function () {
if (this.destroyed) {
this._readyCapability.reject(new Error('Worker was destroyed'));
return;
}
// If we don't use a worker, just post/sendMessage to the main thread.
var port = {
_listeners: [],
postMessage: function (obj) {
var e = {data: obj};
this._listeners.forEach(function (listener) {
listener.call(this, e);
}, this);
},
addEventListener: function (name, listener) {
this._listeners.push(listener);
},
removeEventListener: function (name, listener) {
var i = this._listeners.indexOf(listener);
this._listeners.splice(i, 1);
},
terminate: function () {}
};
this._port = port;
// All fake workers use the same port, making id unique.
var id = 'fake' + (nextFakeWorkerId++);
// If the main thread is our worker, setup the handling for the
// messages -- the main thread sends to it self.
var workerHandler = new MessageHandler(id + '_worker', id, port);
PDFJS.WorkerMessageHandler.setup(workerHandler, port);
var messageHandler = new MessageHandler(id, id + '_worker', port);
this._messageHandler = messageHandler;
this._readyCapability.resolve();
}.bind(this));
},
/**
* Destroys the worker instance.
*/
destroy: function PDFWorker_destroy() {
this.destroyed = true;
if (this._webWorker) {
// We need to terminate only web worker created resource.
this._webWorker.terminate();
this._webWorker = null;
}
this._port = null;
if (this._messageHandler) {
this._messageHandler.destroy();
this._messageHandler = null;
}
}
};
return PDFWorker;
})();
PDFJS.PDFWorker = PDFWorker;
/**
* For internal use only.
* @ignore
*/
var WorkerTransport = (function WorkerTransportClosure() {
function WorkerTransport(workerInitializedCapability, pdfDataRangeTransport) {
function WorkerTransport(messageHandler, loadingTask, pdfDataRangeTransport) {
this.messageHandler = messageHandler;
this.loadingTask = loadingTask;
this.pdfDataRangeTransport = pdfDataRangeTransport;
this.workerInitializedCapability = workerInitializedCapability;
this.commonObjs = new PDFObjects();
this.fontLoader = new FontLoader(loadingTask.docId);
this.loadingTask = null;
this.destroyed = false;
this.destroyCapability = null;
@ -2314,56 +2639,7 @@ var WorkerTransport = (function WorkerTransportClosure() {
this.pagePromises = [];
this.downloadInfoCapability = createPromiseCapability();
// If worker support isn't disabled explicit and the browser has worker
// support, create a new web worker and test if it/the browser fullfills
// all requirements to run parts of pdf.js in a web worker.
// Right now, the requirement is, that an Uint8Array is still an Uint8Array
// as it arrives on the worker. Chrome added this with version 15.
if (!globalScope.PDFJS.disableWorker && typeof Worker !== 'undefined') {
var workerSrc = PDFJS.workerSrc;
if (!workerSrc) {
error('No PDFJS.workerSrc specified');
}
try {
// Some versions of FF can't create a worker on localhost, see:
// https://bugzilla.mozilla.org/show_bug.cgi?id=683280
var worker = new Worker(workerSrc);
var messageHandler = new MessageHandler('main', worker);
this.messageHandler = messageHandler;
messageHandler.on('test', function transportTest(data) {
var supportTypedArray = data && data.supportTypedArray;
if (supportTypedArray) {
this.worker = worker;
if (!data.supportTransfers) {
PDFJS.postMessageTransfers = false;
}
this.setupMessageHandler(messageHandler);
workerInitializedCapability.resolve();
} else {
this.setupFakeWorker();
}
}.bind(this));
var testObj = new Uint8Array([PDFJS.postMessageTransfers ? 255 : 0]);
// Some versions of Opera throw a DATA_CLONE_ERR on serializing the
// typed array. Also, checking if we can use transfers.
try {
messageHandler.send('test', testObj, [testObj.buffer]);
} catch (ex) {
info('Cannot use postMessage transfers');
testObj[0] = 0;
messageHandler.send('test', testObj);
}
return;
} catch (e) {
info('The worker has been disabled.');
}
}
// Either workers are disabled, not supported or have thrown an exception.
// Thus, we fallback to a faked worker.
this.setupFakeWorker();
this.setupMessageHandler();
}
WorkerTransport.prototype = {
destroy: function WorkerTransport_destroy() {
@ -2389,56 +2665,23 @@ var WorkerTransport = (function WorkerTransportClosure() {
var terminated = this.messageHandler.sendWithPromise('Terminate', null);
waitOn.push(terminated);
Promise.all(waitOn).then(function () {
FontLoader.clear();
if (self.worker) {
self.worker.terminate();
}
self.fontLoader.clear();
if (self.pdfDataRangeTransport) {
self.pdfDataRangeTransport.abort();
self.pdfDataRangeTransport = null;
}
self.messageHandler = null;
if (self.messageHandler) {
self.messageHandler.destroy();
self.messageHandler = null;
}
self.destroyCapability.resolve();
}, this.destroyCapability.reject);
return this.destroyCapability.promise;
},
setupFakeWorker: function WorkerTransport_setupFakeWorker() {
globalScope.PDFJS.disableWorker = true;
if (!PDFJS.fakeWorkerFilesLoadedCapability) {
PDFJS.fakeWorkerFilesLoadedCapability = createPromiseCapability();
// In the developer build load worker_loader which in turn loads all the
// other files and resolves the promise. In production only the
// pdf.worker.js file is needed.
Util.loadScript(PDFJS.workerSrc, function() {
PDFJS.fakeWorkerFilesLoadedCapability.resolve();
});
}
PDFJS.fakeWorkerFilesLoadedCapability.promise.then(function () {
warn('Setting up fake worker.');
// If we don't use a worker, just post/sendMessage to the main thread.
var fakeWorker = {
postMessage: function WorkerTransport_postMessage(obj) {
fakeWorker.onmessage({data: obj});
},
terminate: function WorkerTransport_terminate() {}
};
var messageHandler = new MessageHandler('main', fakeWorker);
this.setupMessageHandler(messageHandler);
// If the main thread is our worker, setup the handling for the messages
// the main thread sends to it self.
PDFJS.WorkerMessageHandler.setup(messageHandler);
this.workerInitializedCapability.resolve();
}.bind(this));
},
setupMessageHandler:
function WorkerTransport_setupMessageHandler(messageHandler) {
this.messageHandler = messageHandler;
function WorkerTransport_setupMessageHandler() {
var messageHandler = this.messageHandler;
function updatePassword(password) {
messageHandler.send('UpdatePassword', password);
@ -2578,7 +2821,7 @@ var WorkerTransport = (function WorkerTransportClosure() {
font = new FontFaceObject(exportedData);
}
FontLoader.bind(
this.fontLoader.bind(
[font],
function fontReady(fontObjs) {
this.commonObjs.resolve(id, font);
@ -2703,34 +2946,6 @@ var WorkerTransport = (function WorkerTransportClosure() {
}, this);
},
fetchDocument: function WorkerTransport_fetchDocument(loadingTask, source) {
if (this.destroyed) {
loadingTask._capability.reject(new Error('Loading aborted'));
this.destroyCapability.resolve();
return;
}
this.loadingTask = loadingTask;
source.disableAutoFetch = PDFJS.disableAutoFetch;
source.disableStream = PDFJS.disableStream;
source.chunkedViewerLoading = !!this.pdfDataRangeTransport;
if (this.pdfDataRangeTransport) {
source.length = this.pdfDataRangeTransport.length;
source.initialData = this.pdfDataRangeTransport.initialData;
}
this.messageHandler.send('GetDocRequest', {
source: source,
disableRange: PDFJS.disableRange,
maxImageSize: PDFJS.maxImageSize,
cMapUrl: PDFJS.cMapUrl,
cMapPacked: PDFJS.cMapPacked,
disableFontFace: PDFJS.disableFontFace,
disableCreateObjectURL: PDFJS.disableCreateObjectURL,
verbosity: PDFJS.verbosity
});
},
getData: function WorkerTransport_getData() {
return this.messageHandler.sendWithPromise('GetData', null);
},
@ -2763,9 +2978,11 @@ var WorkerTransport = (function WorkerTransportClosure() {
return this.messageHandler.sendWithPromise('GetPageIndex', { ref: ref });
},
getAnnotations: function WorkerTransport_getAnnotations(pageIndex) {
return this.messageHandler.sendWithPromise('GetAnnotations',
{ pageIndex: pageIndex });
getAnnotations: function WorkerTransport_getAnnotations(pageIndex, intent) {
return this.messageHandler.sendWithPromise('GetAnnotations', {
pageIndex: pageIndex,
intent: intent,
});
},
getDestinations: function WorkerTransport_getDestinations() {
@ -2773,7 +2990,7 @@ var WorkerTransport = (function WorkerTransportClosure() {
},
getDestination: function WorkerTransport_getDestination(id) {
return this.messageHandler.sendWithPromise('GetDestination', { id: id } );
return this.messageHandler.sendWithPromise('GetDestination', { id: id });
},
getAttachments: function WorkerTransport_getAttachments() {
@ -2812,7 +3029,7 @@ var WorkerTransport = (function WorkerTransportClosure() {
}
}
this.commonObjs.clear();
FontLoader.clear();
this.fontLoader.clear();
}.bind(this));
}
};
@ -6161,12 +6378,16 @@ var TilingPattern = (function TilingPatternClosure() {
PDFJS.disableFontFace = false;
var FontLoader = {
function FontLoader(docId) {
this.docId = docId;
this.styleElement = null;
}
FontLoader.prototype = {
insertRule: function fontLoaderInsertRule(rule) {
var styleElement = document.getElementById('PDFJS_FONT_STYLE_TAG');
var styleElement = this.styleElement;
if (!styleElement) {
styleElement = document.createElement('style');
styleElement.id = 'PDFJS_FONT_STYLE_TAG';
styleElement = this.styleElement = document.createElement('style');
styleElement.id = 'PDFJS_FONT_STYLE_TAG_' + this.docId;
document.documentElement.getElementsByTagName('head')[0].appendChild(
styleElement);
}
@ -6176,7 +6397,7 @@ var FontLoader = {
},
clear: function fontLoaderClear() {
var styleElement = document.getElementById('PDFJS_FONT_STYLE_TAG');
var styleElement = this.styleElement;
if (styleElement) {
styleElement.parentNode.removeChild(styleElement);
}
@ -6191,7 +6412,10 @@ var FontLoader = {
}
font.attached = true;
font.bindDOM()
var rule = font.createFontFaceRule();
if (rule) {
this.insertRule(rule);
}
}
setTimeout(callback);
@ -6199,20 +6423,31 @@ var FontLoader = {
};
var FontFaceObject = (function FontFaceObjectClosure() {
function FontFaceObject(name, file, properties) {
function FontFaceObject(translatedData) {
this.compiledGlyphs = {};
if (arguments.length === 1) {
// importing translated data
var data = arguments[0];
for (var i in data) {
this[i] = data[i];
}
return;
// importing translated data
for (var i in translatedData) {
this[i] = translatedData[i];
}
}
Object.defineProperty(FontFaceObject, 'isEvalSupported', {
get: function () {
var evalSupport = false;
if (PDFJS.isEvalSupported) {
try {
/* jshint evil: true */
new Function('');
evalSupport = true;
} catch (e) {}
}
return shadow(this, 'isEvalSupported', evalSupport);
},
enumerable: true,
configurable: true
});
FontFaceObject.prototype = {
bindDOM: function FontFaceObject_bindDOM() {
createFontFaceRule: function FontFaceObject_createFontFaceRule() {
if (!this.data) {
return null;
}
@ -6229,7 +6464,6 @@ var FontFaceObject = (function FontFaceObjectClosure() {
var url = ('url(data:' + this.mimetype + ';base64,' +
window.btoa(data) + ');');
var rule = '@font-face { font-family:"' + fontName + '";src:' + url + '}';
FontLoader.insertRule(rule);
if (PDFJS.pdfBug && 'FontInspector' in globalScope &&
globalScope['FontInspector'].enabled) {
@ -6239,13 +6473,14 @@ var FontFaceObject = (function FontFaceObjectClosure() {
return rule;
},
getPathGenerator: function FontLoader_getPathGenerator(objs, character) {
getPathGenerator:
function FontFaceObject_getPathGenerator(objs, character) {
if (!(character in this.compiledGlyphs)) {
var cmds = objs.get(this.loadedName + '_path_' + character);
var current, i, len;
// If we can, compile cmds into JS for MAXIMUM SPEED
if (FontLoader.isEvalSupported) {
if (FontFaceObject.isEvalSupported) {
var args, js = '';
for (i = 0, len = cmds.length; i < len; i++) {
current = cmds[i];

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

@ -20,8 +20,8 @@ if (typeof PDFJS === 'undefined') {
(typeof window !== 'undefined' ? window : this).PDFJS = {};
}
PDFJS.version = '1.3.14';
PDFJS.build = 'df46b64';
PDFJS.version = '1.3.42';
PDFJS.build = '84a47f8';
(function pdfjsWrapper() {
// Use strict in our context only - users might not want it
@ -60,6 +60,19 @@ var AnnotationType = {
LINK: 3
};
var AnnotationFlag = {
INVISIBLE: 0x01,
HIDDEN: 0x02,
PRINT: 0x04,
NOZOOM: 0x08,
NOROTATE: 0x10,
NOVIEW: 0x20,
READONLY: 0x40,
LOCKED: 0x80,
TOGGLENOVIEW: 0x100,
LOCKEDCONTENTS: 0x200
};
var AnnotationBorderStyleType = {
SOLID: 1,
DASHED: 2,
@ -1186,26 +1199,20 @@ PDFJS.createObjectURL = (function createObjectURLClosure() {
};
})();
function MessageHandler(name, comObj) {
this.name = name;
function MessageHandler(sourceName, targetName, comObj) {
this.sourceName = sourceName;
this.targetName = targetName;
this.comObj = comObj;
this.callbackIndex = 1;
this.postMessageTransfers = true;
var callbacksCapabilities = this.callbacksCapabilities = {};
var ah = this.actionHandler = {};
ah['console_log'] = [function ahConsoleLog(data) {
console.log.apply(console, data);
}];
ah['console_error'] = [function ahConsoleError(data) {
console.error.apply(console, data);
}];
ah['_unsupported_feature'] = [function ah_unsupportedFeature(data) {
UnsupportedManager.notify(data);
}];
comObj.onmessage = function messageHandlerComObjOnMessage(event) {
this._onComObjOnMessage = function messageHandlerComObjOnMessage(event) {
var data = event.data;
if (data.targetName !== this.sourceName) {
return;
}
if (data.isReply) {
var callbackId = data.callbackId;
if (data.callbackId in callbacksCapabilities) {
@ -1222,10 +1229,14 @@ function MessageHandler(name, comObj) {
} else if (data.action in ah) {
var action = ah[data.action];
if (data.callbackId) {
var sourceName = this.sourceName;
var targetName = data.sourceName;
Promise.resolve().then(function () {
return action[0].call(action[1], data.data);
}).then(function (result) {
comObj.postMessage({
sourceName: sourceName,
targetName: targetName,
isReply: true,
callbackId: data.callbackId,
data: result
@ -1236,6 +1247,8 @@ function MessageHandler(name, comObj) {
reason = reason + '';
}
comObj.postMessage({
sourceName: sourceName,
targetName: targetName,
isReply: true,
callbackId: data.callbackId,
error: reason
@ -1247,7 +1260,8 @@ function MessageHandler(name, comObj) {
} else {
error('Unknown action from worker: ' + data.action);
}
};
}.bind(this);
comObj.addEventListener('message', this._onComObjOnMessage);
}
MessageHandler.prototype = {
@ -1266,6 +1280,8 @@ MessageHandler.prototype = {
*/
send: function messageHandlerSend(actionName, data, transfers) {
var message = {
sourceName: this.sourceName,
targetName: this.targetName,
action: actionName,
data: data
};
@ -1283,6 +1299,8 @@ MessageHandler.prototype = {
function messageHandlerSendWithPromise(actionName, data, transfers) {
var callbackId = this.callbackIndex++;
var message = {
sourceName: this.sourceName,
targetName: this.targetName,
action: actionName,
data: data,
callbackId: callbackId
@ -1308,6 +1326,10 @@ MessageHandler.prototype = {
} else {
this.comObj.postMessage(message);
}
},
destroy: function () {
this.comObj.removeEventListener('message', this._onComObjOnMessage);
}
};
@ -1861,6 +1883,10 @@ var BasePdfManager = (function BasePdfManagerClosure() {
}
BasePdfManager.prototype = {
get docId() {
return this._docId;
},
onLoadedStream: function BasePdfManager_onLoadedStream() {
throw new NotImplementedException();
},
@ -1922,7 +1948,8 @@ var BasePdfManager = (function BasePdfManagerClosure() {
})();
var LocalPdfManager = (function LocalPdfManagerClosure() {
function LocalPdfManager(data, password) {
function LocalPdfManager(docId, data, password) {
this._docId = docId;
var stream = new Stream(data);
this.pdfDocument = new PDFDocument(this, stream, password);
this._loadedStreamCapability = createPromiseCapability();
@ -1973,8 +2000,8 @@ var LocalPdfManager = (function LocalPdfManagerClosure() {
})();
var NetworkPdfManager = (function NetworkPdfManagerClosure() {
function NetworkPdfManager(args, msgHandler) {
function NetworkPdfManager(docId, args, msgHandler) {
this._docId = docId;
this.msgHandler = msgHandler;
var params = {
@ -2251,7 +2278,8 @@ var Page = (function PageClosure() {
});
},
extractTextContent: function Page_extractTextContent(task) {
extractTextContent: function Page_extractTextContent(task,
normalizeWhitespace) {
var handler = {
on: function nullHandlerOn() {},
send: function nullHandlerSend() {}
@ -2281,14 +2309,22 @@ var Page = (function PageClosure() {
return partialEvaluator.getTextContent(contentStream,
task,
self.resources);
self.resources,
/* stateManager = */ null,
normalizeWhitespace);
});
},
getAnnotationsData: function Page_getAnnotationsData() {
getAnnotationsData: function Page_getAnnotationsData(intent) {
var annotations = this.annotations;
var annotationsData = [];
for (var i = 0, n = annotations.length; i < n; ++i) {
if (intent) {
if (!(intent === 'display' && annotations[i].viewable) &&
!(intent === 'print' && annotations[i].printable)) {
continue;
}
}
annotationsData.push(annotations[i].data);
}
return annotationsData;
@ -2301,8 +2337,7 @@ var Page = (function PageClosure() {
for (var i = 0, n = annotationRefs.length; i < n; ++i) {
var annotationRef = annotationRefs[i];
var annotation = annotationFactory.create(this.xref, annotationRef);
if (annotation &&
(annotation.isViewable() || annotation.isPrintable())) {
if (annotation) {
annotations.push(annotation);
}
}
@ -4511,7 +4546,9 @@ var Annotation = (function AnnotationClosure() {
var data = this.data = {};
data.subtype = dict.get('Subtype').name;
data.annotationFlags = dict.get('F');
this.setFlags(dict.get('F'));
data.annotationFlags = this.flags;
this.setRectangle(dict.get('Rect'));
data.rect = this.rectangle;
@ -4528,6 +4565,64 @@ var Annotation = (function AnnotationClosure() {
}
Annotation.prototype = {
/**
* @return {boolean}
*/
get viewable() {
if (this.flags) {
return !this.hasFlag(AnnotationFlag.INVISIBLE) &&
!this.hasFlag(AnnotationFlag.HIDDEN) &&
!this.hasFlag(AnnotationFlag.NOVIEW);
}
return true;
},
/**
* @return {boolean}
*/
get printable() {
if (this.flags) {
return this.hasFlag(AnnotationFlag.PRINT) &&
!this.hasFlag(AnnotationFlag.INVISIBLE) &&
!this.hasFlag(AnnotationFlag.HIDDEN);
}
return false;
},
/**
* Set the flags.
*
* @public
* @memberof Annotation
* @param {number} flags - Unsigned 32-bit integer specifying annotation
* characteristics
* @see {@link shared/util.js}
*/
setFlags: function Annotation_setFlags(flags) {
if (isInt(flags)) {
this.flags = flags;
} else {
this.flags = 0;
}
},
/**
* Check if a provided flag is set.
*
* @public
* @memberof Annotation
* @param {number} flag - Hexadecimal representation for an annotation
* characteristic
* @return {boolean}
* @see {@link shared/util.js}
*/
hasFlag: function Annotation_hasFlag(flag) {
if (this.flags) {
return (this.flags & flag) > 0;
}
return false;
},
/**
* Set the rectangle.
*
@ -4627,32 +4722,6 @@ var Annotation = (function AnnotationClosure() {
}
},
isInvisible: function Annotation_isInvisible() {
var data = this.data;
return !!(data &&
data.annotationFlags && // Default: not invisible
data.annotationFlags & 0x1); // Invisible
},
isViewable: function Annotation_isViewable() {
var data = this.data;
return !!(!this.isInvisible() &&
data &&
(!data.annotationFlags ||
!(data.annotationFlags & 0x22)) && // Hidden or NoView
data.rect); // rectangle is necessary
},
isPrintable: function Annotation_isPrintable() {
var data = this.data;
return !!(!this.isInvisible() &&
data &&
data.annotationFlags && // Default: not printable
data.annotationFlags & 0x4 && // Print
!(data.annotationFlags & 0x2) && // Hidden
data.rect); // rectangle is necessary
},
loadResources: function Annotation_loadResources(keys) {
return new Promise(function (resolve, reject) {
this.appearance.dict.getAsync('Resources').then(function (resources) {
@ -4719,8 +4788,8 @@ var Annotation = (function AnnotationClosure() {
var annotationPromises = [];
for (var i = 0, n = annotations.length; i < n; ++i) {
if (intent === 'display' && annotations[i].isViewable() ||
intent === 'print' && annotations[i].isPrintable()) {
if (intent === 'display' && annotations[i].viewable ||
intent === 'print' && annotations[i].printable) {
annotationPromises.push(
annotations[i].getOperatorList(partialEvaluator, task));
}
@ -4896,6 +4965,12 @@ var WidgetAnnotation = (function WidgetAnnotationClosure() {
data.fieldFlags = Util.getInheritableProperty(dict, 'Ff') || 0;
this.fieldResources = Util.getInheritableProperty(dict, 'DR') || Dict.empty;
// Hide unsupported Widget signatures.
if (data.fieldType === 'Sig') {
warn('unimplemented annotation type: Widget signature');
this.setFlags(AnnotationFlag.HIDDEN);
}
// Building the full field name by collecting the field and
// its ancestors 'T' data and joining them using '.'.
var fieldName = [];
@ -4929,17 +5004,7 @@ var WidgetAnnotation = (function WidgetAnnotationClosure() {
data.fullName = fieldName.join('.');
}
var parent = Annotation.prototype;
Util.inherit(WidgetAnnotation, Annotation, {
isViewable: function WidgetAnnotation_isViewable() {
if (this.data.fieldType === 'Sig') {
warn('unimplemented annotation type: Widget signature');
return false;
}
return parent.isViewable.call(this);
}
});
Util.inherit(WidgetAnnotation, Annotation, {});
return WidgetAnnotation;
})();
@ -5038,7 +5103,7 @@ var LinkAnnotation = (function LinkAnnotationClosure() {
if (!isValidUrl(url, false)) {
url = '';
}
// According to ISO 32000-1:2008, section 12.6.4.7,
// According to ISO 32000-1:2008, section 12.6.4.7,
// URI should to be encoded in 7-bit ASCII.
// Some bad PDFs may have URIs in UTF-8 encoding, see Bugzilla 1122280.
try {
@ -10562,6 +10627,9 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
return translated.loadType3Data(self, resources, operatorList, task).
then(function () {
return translated;
}, function (reason) {
return new TranslatedFont('g_font_error',
new ErrorFont('Type3 font load error: ' + reason), translated.font);
});
}).then(function (translated) {
state.font = translated.font;
@ -10770,7 +10838,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
// Keep track of each font we translated so the caller can
// load them asynchronously before calling display on a page.
font.loadedName = 'g_font_' + (fontRefIsDict ?
font.loadedName = 'g_' + this.pdfManager.docId + '_f' + (fontRefIsDict ?
fontName.replace(/\W/g, '') : fontID);
font.translated = fontCapability.promise;
@ -11149,12 +11217,15 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
});
},
getTextContent: function PartialEvaluator_getTextContent(stream, task,
resources,
stateManager) {
getTextContent:
function PartialEvaluator_getTextContent(stream, task, resources,
stateManager,
normalizeWhitespace) {
stateManager = (stateManager || new StateManager(new TextState()));
var WhitespaceRegexp = /\s/g;
var textContent = {
items: [],
styles: Object.create(null)
@ -11268,11 +11339,23 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
return textContentItem;
}
function replaceWhitespace(str) {
// Replaces all whitespaces with standard spaces (0x20), to avoid
// alignment issues between the textLayer and the canvas if the text
// contains e.g. tabs (fixes issue6612.pdf).
var i = 0, ii = str.length, code;
while (i < ii && (code = str.charCodeAt(i)) >= 0x20 && code <= 0x7F) {
i++;
}
return (i < ii ? str.replace(WhitespaceRegexp, ' ') : str);
}
function runBidiTransform(textChunk) {
var str = textChunk.str.join('');
var bidiResult = PDFJS.bidi(str, -1, textChunk.vertical);
return {
str: bidiResult.str,
str: (normalizeWhitespace ? replaceWhitespace(bidiResult.str) :
bidiResult.str),
dir: bidiResult.dir,
width: textChunk.width,
height: textChunk.height,
@ -11593,8 +11676,8 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
}
return self.getTextContent(xobj, task,
xobj.dict.get('Resources') || resources, stateManager).
then(function (formTextContent) {
xobj.dict.get('Resources') || resources, stateManager,
normalizeWhitespace).then(function (formTextContent) {
Util.appendToArray(textContent.items, formTextContent.items);
Util.extendObj(textContent.styles, formTextContent.styles);
stateManager.restore();
@ -33837,12 +33920,51 @@ var WorkerTask = (function WorkerTaskClosure() {
})();
var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
setup: function wphSetup(handler) {
setup: function wphSetup(handler, port) {
handler.on('test', function wphSetupTest(data) {
// check if Uint8Array can be sent to worker
if (!(data instanceof Uint8Array)) {
handler.send('test', 'main', false);
return;
}
// making sure postMessage transfers are working
var supportTransfers = data[0] === 255;
handler.postMessageTransfers = supportTransfers;
// check if the response property is supported by xhr
var xhr = new XMLHttpRequest();
var responseExists = 'response' in xhr;
// check if the property is actually implemented
try {
var dummy = xhr.responseType;
} catch (e) {
responseExists = false;
}
if (!responseExists) {
handler.send('test', false);
return;
}
handler.send('test', {
supportTypedArray: true,
supportTransfers: supportTransfers
});
});
handler.on('GetDocRequest', function wphSetupDoc(data) {
return WorkerMessageHandler.createDocumentHandler(data, port);
});
},
createDocumentHandler: function wphCreateDocumentHandler(docParams, port) {
// This context is actually holds references on pdfManager and handler,
// until the latter is destroyed.
var pdfManager;
var terminated = false;
var cancelXHRs = null;
var WorkerTasks = [];
var docId = docParams.docId;
var workerHandlerName = docParams.docId + '_worker';
var handler = new MessageHandler(workerHandlerName, docId, port);
function ensureNotTerminated() {
if (terminated) {
throw new Error('Worker was terminated');
@ -33900,7 +34022,7 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
var disableRange = data.disableRange;
if (source.data) {
try {
pdfManager = new LocalPdfManager(source.data, source.password);
pdfManager = new LocalPdfManager(docId, source.data, source.password);
pdfManagerCapability.resolve(pdfManager);
} catch (ex) {
pdfManagerCapability.reject(ex);
@ -33908,7 +34030,7 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
return pdfManagerCapability.promise;
} else if (source.chunkedViewerLoading) {
try {
pdfManager = new NetworkPdfManager(source, handler);
pdfManager = new NetworkPdfManager(docId, source, handler);
pdfManagerCapability.resolve(pdfManager);
} catch (ex) {
pdfManagerCapability.reject(ex);
@ -33965,7 +34087,7 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
}
try {
pdfManager = new NetworkPdfManager(source, handler);
pdfManager = new NetworkPdfManager(docId, source, handler);
pdfManagerCapability.resolve(pdfManager);
} catch (ex) {
pdfManagerCapability.reject(ex);
@ -34010,7 +34132,7 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
// the data is array, instantiating directly from it
try {
pdfManager = new LocalPdfManager(pdfFile, source.password);
pdfManager = new LocalPdfManager(docId, pdfFile, source.password);
pdfManagerCapability.resolve(pdfManager);
} catch (ex) {
pdfManagerCapability.reject(ex);
@ -34048,35 +34170,7 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
return pdfManagerCapability.promise;
}
handler.on('test', function wphSetupTest(data) {
// check if Uint8Array can be sent to worker
if (!(data instanceof Uint8Array)) {
handler.send('test', false);
return;
}
// making sure postMessage transfers are working
var supportTransfers = data[0] === 255;
handler.postMessageTransfers = supportTransfers;
// check if the response property is supported by xhr
var xhr = new XMLHttpRequest();
var responseExists = 'response' in xhr;
// check if the property is actually implemented
try {
var dummy = xhr.responseType;
} catch (e) {
responseExists = false;
}
if (!responseExists) {
handler.send('test', false);
return;
}
handler.send('test', {
supportTypedArray: true,
supportTransfers: supportTransfers
});
});
handler.on('GetDocRequest', function wphSetupDoc(data) {
var setupDoc = function(data) {
var onSuccess = function(doc) {
ensureNotTerminated();
handler.send('GetDoc', { pdfInfo: doc });
@ -34121,7 +34215,6 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
}
pdfManager = newPdfManager;
handler.send('PDFManagerReady', null);
pdfManager.onLoadedStream().then(function(stream) {
handler.send('DataLoaded', { length: stream.bytes.byteLength });
@ -34152,7 +34245,7 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
});
}, onFailure);
}, onFailure);
});
};
handler.on('GetPage', function wphSetupGetPage(data) {
return pdfManager.getPage(data.pageIndex).then(function(page) {
@ -34185,7 +34278,7 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
handler.on('GetDestination',
function wphSetupGetDestination(data) {
return pdfManager.ensureCatalog('getDestination', [ data.id ]);
return pdfManager.ensureCatalog('getDestination', [data.id]);
}
);
@ -34233,7 +34326,7 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
handler.on('GetAnnotations', function wphSetupGetAnnotations(data) {
return pdfManager.getPage(data.pageIndex).then(function(page) {
return pdfManager.ensure(page, 'getAnnotationsData', []);
return pdfManager.ensure(page, 'getAnnotationsData', [data.intent]);
});
});
@ -34292,12 +34385,14 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
handler.on('GetTextContent', function wphExtractText(data) {
var pageIndex = data.pageIndex;
var normalizeWhitespace = data.normalizeWhitespace;
return pdfManager.getPage(pageIndex).then(function(page) {
var task = new WorkerTask('GetTextContent: page ' + pageIndex);
startWorkerTask(task);
var pageNum = pageIndex + 1;
var start = Date.now();
return page.extractTextContent(task).then(function(textContent) {
return page.extractTextContent(task, normalizeWhitespace).then(
function(textContent) {
finishWorkerTask(task);
info('text indexing: page=' + pageNum + ' - time=' +
(Date.now() - start) + 'ms');
@ -34332,8 +34427,19 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
task.terminate();
});
return Promise.all(waitOn).then(function () {});
return Promise.all(waitOn).then(function () {
// Notice that even if we destroying handler, resolved response promise
// must be sent back.
handler.destroy();
handler = null;
});
});
handler.on('Ready', function wphReady(data) {
setupDoc(docParams);
docParams = null; // we don't need docParams anymore -- saving memory.
});
return workerHandlerName;
}
};
@ -34343,6 +34449,7 @@ var workerConsole = {
log: function log() {
var args = Array.prototype.slice.call(arguments);
globalScope.postMessage({
targetName: 'main',
action: 'console_log',
data: args
});
@ -34351,6 +34458,7 @@ var workerConsole = {
error: function error() {
var args = Array.prototype.slice.call(arguments);
globalScope.postMessage({
targetName: 'main',
action: 'console_error',
data: args
});
@ -34380,13 +34488,14 @@ if (typeof window === 'undefined') {
// Listen for unsupported features so we can pass them on to the main thread.
PDFJS.UnsupportedManager.listen(function (msg) {
globalScope.postMessage({
targetName: 'main',
action: '_unsupported_feature',
data: msg
});
});
var handler = new MessageHandler('worker_processor', this);
WorkerMessageHandler.setup(handler);
var handler = new MessageHandler('worker', 'main', this);
WorkerMessageHandler.setup(handler, this);
}

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

@ -12,6 +12,18 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* globals PDFJS, PDFBug, FirefoxCom, Stats, Cache, ProgressBar,
DownloadManager, getFileName, getPDFFileNameFromURL,
PDFHistory, Preferences, SidebarView, ViewHistory, Stats,
PDFThumbnailViewer, URL, noContextMenuHandler, SecondaryToolbar,
PasswordPrompt, PDFPresentationMode, PDFDocumentProperties, HandTool,
Promise, PDFLinkService, PDFOutlineView, PDFAttachmentView,
OverlayManager, PDFFindController, PDFFindBar, PDFViewer,
PDFRenderingQueue, PresentationModeState, parseQueryString,
RenderingStates, UNKNOWN_SCALE, DEFAULT_SCALE_VALUE,
IGNORE_CURRENT_POSITION_ON_ZOOM: true */
'use strict';
var DEFAULT_URL = 'compressed.tracemonkey-pldi-09.pdf';
var DEFAULT_SCALE_DELTA = 1.1;
@ -1027,7 +1039,6 @@ var PDFFindController = (function PDFFindControllerClosure() {
'\u00BC': '1/4', // Vulgar fraction one quarter
'\u00BD': '1/2', // Vulgar fraction one half
'\u00BE': '3/4', // Vulgar fraction three quarters
'\u00A0': ' ' // No-break space
};
this.findBar = options.findBar || null;
@ -3675,7 +3686,7 @@ var PDFPageView = (function PDFPageViewClosure() {
}
if (redrawAnnotations && this.annotationLayer) {
this.annotationLayer.setupAnnotations(this.viewport);
this.annotationLayer.setupAnnotations(this.viewport, 'display');
}
},
@ -3878,7 +3889,7 @@ var PDFPageView = (function PDFPageViewClosure() {
function pdfPageRenderCallback() {
pageViewDrawCallback(null);
if (textLayer) {
self.pdfPage.getTextContent().then(
self.pdfPage.getTextContent({ normalizeWhitespace: true }).then(
function textContentResolved(textContent) {
textLayer.setTextContent(textContent);
textLayer.render(TEXT_LAYER_RENDER_DELAY);
@ -3896,7 +3907,7 @@ var PDFPageView = (function PDFPageViewClosure() {
this.annotationLayer = this.annotationsLayerFactory.
createAnnotationsLayerBuilder(div, this.pdfPage);
}
this.annotationLayer.setupAnnotations(this.viewport);
this.annotationLayer.setupAnnotations(this.viewport, 'display');
}
div.setAttribute('data-loaded', true);
@ -4313,9 +4324,10 @@ var AnnotationsLayerBuilder = (function AnnotationsLayerBuilderClosure() {
/**
* @param {PageViewport} viewport
* @param {string} intent (default value is 'display')
*/
setupAnnotations:
function AnnotationsLayerBuilder_setupAnnotations(viewport) {
function AnnotationsLayerBuilder_setupAnnotations(viewport, intent) {
function bindLink(link, dest) {
link.href = linkService.getDestinationHash(dest);
link.onclick = function annotationsLayerBuilderLinksOnclick() {
@ -4341,8 +4353,12 @@ var AnnotationsLayerBuilder = (function AnnotationsLayerBuilderClosure() {
var linkService = this.linkService;
var pdfPage = this.pdfPage;
var self = this;
var getAnnotationsParams = {
intent: (intent === undefined ? 'display' : intent),
};
pdfPage.getAnnotations().then(function (annotationsData) {
pdfPage.getAnnotations(getAnnotationsParams).then(
function (annotationsData) {
viewport = viewport.clone({ dontFlip: true });
var transform = viewport.transform;
var transformStr = 'matrix(' + transform.join(',') + ')';
@ -4882,7 +4898,7 @@ var PDFViewer = (function pdfViewer() {
if (!this.pdfDocument) {
return;
}
var pageView = this._pages[pageNumber - 1];
if (this.isInPresentationMode) {
@ -5140,7 +5156,7 @@ var PDFViewer = (function pdfViewer() {
getPageTextContent: function (pageIndex) {
return this.pdfDocument.getPage(pageIndex + 1).then(function (page) {
return page.getTextContent();
return page.getTextContent({ normalizeWhitespace: true });
});
},
@ -7389,7 +7405,7 @@ document.addEventListener('textlayerrendered', function (e) {
if (pageView.textLayer && pageView.textLayer.textDivs &&
pageView.textLayer.textDivs.length > 0 &&
!PDFViewerApplication.supportsDocumentColors) {
console.error(mozL10n.get('document_colors_disabled', null,
console.error(mozL10n.get('document_colors_not_allowed', null,
'PDF documents are not allowed to use their own colors: ' +
'\'Allow pages to choose their own colors\' ' +
'is deactivated in the browser.'));

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

@ -15,3 +15,11 @@ reconnectDescription = Reconnect %S
# LOCALIZATION NOTE (verifyDescription) - %S = Email address of user's Firefox Account
verifyDescription = Verify %S
# These strings are shown in a flyout in the Sync preference panel after the
# user requests we resend a verification email.
verificationSentTitle = Verification Sent
# LOCALIZATION NOTE (verificationSentFull) - %S = Email address of user's Firefox Account
verificationSentFull = A verification link has been sent to %S. Please check your email and click the link to begin syncing.
verificationNotSentTitle = Unable to Send Verification
verificationNotSentFull = We are unable to send a verification mail at this time, please try again later.

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

@ -198,7 +198,7 @@ room_name_untitled_page=Untitled Page
# Infobar strings
infobar_screenshare_browser_message=You are sharing your tabs. Any tab you click on can be seen by your friends
infobar_screenshare_browser_message2=You are sharing your tabs. Any tab you click on can be seen by your friends
infobar_screenshare_paused_browser_message=Tab sharing is paused
infobar_button_pause_label=Pause
infobar_button_resume_label=Resume

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

@ -170,4 +170,4 @@ password_cancel=Cancel
printing_not_supported=Warning: Printing is not fully supported by this browser.
printing_not_ready=Warning: The PDF is not fully loaded for printing.
web_fonts_disabled=Web fonts are disabled: unable to use embedded PDF fonts.
document_colors_disabled=PDF documents are not allowed to use their own colors: \'Allow pages to choose their own colors\' is deactivated in the browser.
document_colors_not_allowed=PDF documents are not allowed to use their own colors: 'Allow pages to choose their own colors' is deactivated in the browser.

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

@ -8,11 +8,15 @@ import java.util.Iterator;
/**
* Class for iterating over an IterableJarLoadingURLClassLoader's classes.
*
* This class is not thread safe: use it only from a single thread.
*/
public class JarClassIterator implements Iterator<ClassWithOptions> {
private IterableJarLoadingURLClassLoader mTarget;
private Iterator<String> mTargetClassListIterator;
private ClassWithOptions lookAhead;
public JarClassIterator(IterableJarLoadingURLClassLoader aTarget) {
mTarget = aTarget;
mTargetClassListIterator = aTarget.classNames.iterator();
@ -20,11 +24,28 @@ public class JarClassIterator implements Iterator<ClassWithOptions> {
@Override
public boolean hasNext() {
return mTargetClassListIterator.hasNext();
return fillLookAheadIfPossible();
}
@Override
public ClassWithOptions next() {
if (!fillLookAheadIfPossible()) {
throw new IllegalStateException("Failed to look ahead in next()!");
}
ClassWithOptions next = lookAhead;
lookAhead = null;
return next;
}
private boolean fillLookAheadIfPossible() {
if (lookAhead != null) {
return true;
}
if (!mTargetClassListIterator.hasNext()) {
return false;
}
String className = mTargetClassListIterator.next();
try {
Class<?> ret = mTarget.loadClass(className);
@ -37,22 +58,23 @@ public class JarClassIterator implements Iterator<ClassWithOptions> {
try {
enclosingClass = ret.getEnclosingClass();
} catch (IncompatibleClassChangeError e) {
return next();
return fillLookAheadIfPossible();
}
if (enclosingClass != null) {
// Anonymous inner class - unsupported.
// Or named inner class, which will be processed when we process the outer class.
return next();
return fillLookAheadIfPossible();
}
return new ClassWithOptions(ret, ret.getSimpleName());
lookAhead = new ClassWithOptions(ret, ret.getSimpleName());
return true;
} catch (ClassNotFoundException e) {
System.err.println("Unable to enumerate class: " + className + ". Corrupted jar file?");
e.printStackTrace();
System.exit(2);
}
return null;
return false;
}
@Override

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

@ -73,6 +73,6 @@ if CONFIG['MOZ_ASAN'] and CONFIG['CLANG_CL']:
FINAL_TARGET_FILES += [CONFIG['MOZ_CLANG_RT_ASAN_LIB_PATH']]
if CONFIG['MOZ_APP_BASENAME']:
DIST_FILES += ['application.ini']
FINAL_TARGET_PP_FILES += ['application.ini']
if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'android' and CONFIG['MOZ_UPDATER']:
DIST_FILES += ['update-settings.ini']
FINAL_TARGET_PP_FILES += ['update-settings.ini']

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

@ -0,0 +1,9 @@
# Options to enable rust in automation builds.
# Tell configure to use the tooltool rustc.
# Assume this is compiled with --enable-rpath so we don't
# have to set LD_LIBRARY_PATH.
RUSTC="$topsrcdir/rustc/bin/rustc"
# Enable rust in the build.
ac_add_options --enable-rust

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

@ -6,17 +6,10 @@ includedir := $(includedir)/$(MOZ_APP_NAME)-$(MOZ_APP_VERSION)
idldir = $(datadir)/idl/$(MOZ_APP_NAME)-$(MOZ_APP_VERSION)
installdir = $(libdir)/$(MOZ_APP_NAME)-$(MOZ_APP_VERSION)
sdkdir = $(libdir)/$(MOZ_APP_NAME)-devel-$(MOZ_APP_VERSION)
ifndef TOP_DIST
TOP_DIST = dist
endif
ifneq (,$(filter /%,$(TOP_DIST)))
DIST = $(TOP_DIST)
else
ifeq (.,$(DEPTH))
DIST = $(TOP_DIST)
DIST = dist
else
DIST = $(DEPTH)/$(TOP_DIST)
endif
DIST = $(DEPTH)/dist
endif
# We do magic with OBJ_SUFFIX in config.mk, the following ensures we don't

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

@ -43,13 +43,20 @@ default: $(addprefix install-,$(INSTALL_MANIFESTS))
# Explicit files to be built for a default build
default: $(addprefix $(TOPOBJDIR)/,$(MANIFEST_TARGETS))
ifndef TEST_MOZBUILD
default: $(TOPOBJDIR)/dist/bin/platform.ini
endif
ifndef NO_XPIDL
# Targets from the recursive make backend to be built for a default build
default: $(TOPOBJDIR)/config/makefiles/xpidl/xpidl
endif
ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
# Mac builds require to copy things in dist/bin/*.app
# TODO: remove the MOZ_WIDGET_TOOLKIT and MOZ_BUILD_APP variables from
# faster/Makefile and python/mozbuild/mozbuild/test/backend/test_build.py
# when this is not required anymore.
default:
$(MAKE) -C $(TOPOBJDIR)/$(MOZ_BUILD_APP)/app repackage
endif
@ -77,6 +84,7 @@ $(TOPOBJDIR)/_virtualenv/%: ;
# if there is no other rule.
$(TOPOBJDIR)/dist/%:
rm -f $@
mkdir -p $(@D)
cp $< $@
# Refresh backend

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

@ -5,19 +5,6 @@
# 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/.
ifndef NO_DIST_INSTALL
ifdef SHARED_LIBRARY
ifdef IS_COMPONENT
target:: $(SUBMAKEFILES) $(SHARED_LIBRARY)
$(INSTALL) $(IFLAGS2) $(SHARED_LIBRARY) $(FINAL_TARGET)/components
ifndef NO_COMPONENTS_MANIFEST
$(call py_action,buildlist,$(FINAL_TARGET)/chrome.manifest 'manifest components/components.manifest')
$(call py_action,buildlist,$(FINAL_TARGET)/components/components.manifest 'binary-component $(SHARED_LIBRARY)')
endif
endif # IS_COMPONENT
endif # SHARED_LIBRARY
endif # !NO_DIST_INSTALL
ifndef NO_DIST_INSTALL
ifneq (,$(strip $(PROGRAM)$(SIMPLE_PROGRAMS)))
@ -37,12 +24,10 @@ endif # LIBRARY
ifdef SHARED_LIBRARY
ifndef IS_COMPONENT
SHARED_LIBRARY_FILES = $(SHARED_LIBRARY)
SHARED_LIBRARY_DEST ?= $(FINAL_TARGET)
SHARED_LIBRARY_DEST ?= $(FINAL_TARGET)$(if $(IS_COMPONENT),/components)
SHARED_LIBRARY_TARGET = target
INSTALL_TARGETS += SHARED_LIBRARY
endif # ! IS_COMPONENT
endif # SHARED_LIBRARY
ifneq (,$(strip $(HOST_SIMPLE_PROGRAMS)$(HOST_PROGRAM)))

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

@ -1138,9 +1138,8 @@ export:: $(FINAL_TARGET)
endif
################################################################################
# Copy each element of PREF_JS_EXPORTS
# The default location for PREF_JS_EXPORTS is the gre prefs directory.
# The default location for prefs is the gre prefs directory.
# PREF_DIR is used for L10N_PREF_JS_EXPORTS in various locales/ directories.
PREF_DIR = defaults/pref
# If DIST_SUBDIR is defined it indicates that app and gre dirs are
@ -1150,16 +1149,6 @@ ifneq (,$(DIST_SUBDIR)$(XPI_NAME))
PREF_DIR = defaults/preferences
endif
ifneq ($(PREF_JS_EXPORTS),)
ifndef NO_DIST_INSTALL
PREF_JS_EXPORTS_PATH := $(FINAL_TARGET)/$(PREF_DIR)
# We preprocess these, but they don't necessarily have preprocessor directives,
# so tell them preprocessor to not complain about that.
PREF_JS_EXPORTS_FLAGS := $(PREF_PPFLAGS) --silence-missing-directive-warnings
PP_TARGETS += PREF_JS_EXPORTS
endif
endif
################################################################################
# Copy each element of AUTOCFG_JS_EXPORTS to $(FINAL_TARGET)/defaults/autoconfig
@ -1172,33 +1161,6 @@ INSTALL_TARGETS += AUTOCFG_JS_EXPORTS
endif
endif
################################################################################
# Copy each element of EXTRA_COMPONENTS to $(FINAL_TARGET)/components
ifdef EXTRA_COMPONENTS
misc:: $(EXTRA_COMPONENTS)
ifndef NO_DIST_INSTALL
EXTRA_COMPONENTS_FILES := $(EXTRA_COMPONENTS)
EXTRA_COMPONENTS_DEST := $(FINAL_TARGET)/components
EXTRA_COMPONENTS_TARGET := misc
INSTALL_TARGETS += EXTRA_COMPONENTS
endif
endif
ifdef EXTRA_PP_COMPONENTS
ifndef NO_DIST_INSTALL
EXTRA_PP_COMPONENTS_PATH := $(FINAL_TARGET)/components
EXTRA_PP_COMPONENTS_TARGET := misc
PP_TARGETS += EXTRA_PP_COMPONENTS
endif
endif
EXTRA_MANIFESTS = $(filter %.manifest,$(EXTRA_COMPONENTS) $(EXTRA_PP_COMPONENTS))
ifneq (,$(EXTRA_MANIFESTS))
misc:: $(call mkdir_deps,$(FINAL_TARGET))
$(call py_action,buildlist,$(FINAL_TARGET)/chrome.manifest $(patsubst %,'manifest components/%',$(notdir $(EXTRA_MANIFESTS))))
endif
################################################################################
# SDK
@ -1268,14 +1230,6 @@ $(error $(srcdir) contains a jar.mn file but this file is not declared in a JAR_
endif
endif
ifneq ($(DIST_FILES),)
DIST_FILES_PATH := $(FINAL_TARGET)
# We preprocess these, but they don't necessarily have preprocessor directives,
# so tell them preprocessor to not complain about that.
DIST_FILES_FLAGS := --silence-missing-directive-warnings
PP_TARGETS += DIST_FILES
endif
# When you move this out of the tools tier, please remove the corresponding
# hacks in recursivemake.py that check if Makefile.in sets the variable.
ifneq ($(XPI_PKGNAME),)
@ -1592,8 +1546,6 @@ FREEZE_VARIABLES = \
DIRS \
LIBRARY \
MODULE \
EXTRA_COMPONENTS \
EXTRA_PP_COMPONENTS \
$(NULL)
$(foreach var,$(FREEZE_VARIABLES),$(eval $(var)_FROZEN := '$($(var))'))

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

@ -1328,6 +1328,7 @@ xlocale.h
#ifdef MOZ_SHARED_ICU
unicode/locid.h
unicode/numsys.h
unicode/timezone.h
unicode/ucal.h
unicode/uchar.h
unicode/uclean.h

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

@ -672,7 +672,7 @@ See https://developer.mozilla.org/en/Windows_Build_Prerequisites.])
fi
if test "$WRAP_STL_INCLUDES" = "1"; then
STL_FLAGS='-I$(DIST)/stl_wrappers'
STL_FLAGS="-I${DIST}/stl_wrappers"
fi
CFLAGS="$CFLAGS -D_HAS_EXCEPTIONS=0"
CXXFLAGS="$CXXFLAGS -D_HAS_EXCEPTIONS=0"
@ -2583,7 +2583,7 @@ if test "$GNU_CC" -a "$OS_TARGET" != WINNT; then
VISIBILITY_FLAGS='-fvisibility=hidden -fvisibility-inlines-hidden'
;;
*)
VISIBILITY_FLAGS='-I$(DIST)/system_wrappers -include $(MOZILLA_DIR)/config/gcc_hidden.h'
VISIBILITY_FLAGS="-I${DIST}/system_wrappers -include ${_topsrcdir}/config/gcc_hidden.h"
WRAP_SYSTEM_INCLUDES=1
;;
esac
@ -2598,13 +2598,13 @@ case "${OS_TARGET}" in
WINNT|Darwin|Android)
;;
*)
STL_FLAGS='-I$(DIST)/stl_wrappers'
STL_FLAGS="-I${DIST}/stl_wrappers"
WRAP_STL_INCLUDES=1
;;
esac
AC_SUBST(WRAP_SYSTEM_INCLUDES)
AC_SUBST(VISIBILITY_FLAGS)
AC_SUBST_LIST(VISIBILITY_FLAGS)
dnl Checks for header files.
dnl ========================================================
@ -8143,12 +8143,8 @@ fi
if test "$MOZ_TREE_PIXMAN"; then
AC_DEFINE(MOZ_TREE_PIXMAN)
else
PKG_CHECK_MODULES(PIXMAN, pixman-1 >= 0.19.2)
MOZ_PIXMAN_CFLAGS="$PIXMAN_CFLAGS"
MOZ_PIXMAN_LIBS="$PIXMAN_LIBS"
PKG_CHECK_MODULES(MOZ_PIXMAN, pixman-1 >= 0.19.2)
fi
AC_SUBST(MOZ_PIXMAN_CFLAGS)
AC_SUBST_LIST(MOZ_PIXMAN_LIBS)
# Check for headers defining standard int types.
if test -n "$COMPILE_ENVIRONMENT"; then
@ -8988,11 +8984,6 @@ AC_SUBST(DMG_TOOL)
dnl Host JavaScript runtime, if any, to use during cross compiles.
AC_SUBST(JS_BINARY)
if test "$MOZ_DEBUG"; then
MOZ_EM_DEBUG=1
fi
AC_SUBST(MOZ_EM_DEBUG)
AC_SUBST(NSS_EXTRA_SYMBOLS_FILE)
if test -n "$COMPILE_ENVIRONMENT"; then
@ -9280,6 +9271,7 @@ export MOZILLA_CENTRAL_PATH=$_topsrcdir
export STLPORT_CPPFLAGS
export STLPORT_LIBS
export JS_STANDALONE=no
export DIST
export MOZ_LINKER
export ZLIB_IN_MOZGLUE
export MOZ_MEMORY

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

@ -308,24 +308,36 @@ var PerformanceController = {
this.emit(EVENTS.RECORDING_EXPORTED, recording, file);
}),
/**
* Clears all recordings from the list as well as the current recording.
* Emits `EVENTS.RECORDINGS_CLEARED` when complete so other components can clean up.
/**
* Clears all completed recordings from the list as well as the current non-console recording.
* Emits `EVENTS.RECORDING_DELETED` when complete so other components can clean up.
*/
clearRecordings: Task.async(function* () {
let latest = this.getLatestManualRecording();
if (latest && latest.isRecording()) {
yield this.stopRecording();
for (let i = this._recordings.length - 1; i >= 0; i--) {
let model = this._recordings[i];
if (!model.isConsole() && model.isRecording()) {
yield this.stopRecording();
}
// If last recording is not recording, but finalizing itself,
// wait for that to finish
if (!model.isRecording() && !model.isCompleted()) {
yield this.waitForStateChangeOnRecording(model, "recording-stopped");
}
// If recording is completed,
// clean it up from UI and remove it from the _recordings array.
if (model.isCompleted()) {
this.emit(EVENTS.RECORDING_DELETED, model);
this._recordings.splice(i, 1);
}
}
// If last recording is not recording, but finalizing itself,
// wait for that to finish
if (latest && !latest.isCompleted()) {
yield this.waitForStateChangeOnRecording(latest, "recording-stopped");
if (this._recordings.length > 0) {
if (!this._recordings.includes(this.getCurrentRecording())) {
this.setCurrentRecording(this._recordings[0]);
}
}
else {
this.setCurrentRecording(null);
}
this._recordings.length = 0;
this.setCurrentRecording(null);
this.emit(EVENTS.RECORDINGS_CLEARED);
}),
/**

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

@ -15,10 +15,22 @@ var test = Task.async(function*() {
yield startRecording(panel);
let deleted = Promise.defer();
let deleteCount = 0;
function onDeleted () {
if (++deleteCount === 2) {
deleted.resolve();
PerformanceController.off(EVENTS.RECORDING_DELETED, onDeleted);
}
}
PerformanceController.on(EVENTS.RECORDING_DELETED, onDeleted);
let stopped = Promise.all([
once(PerformanceController, EVENTS.RECORDING_STOPPED),
once(PerformanceController, EVENTS.RECORDINGS_CLEARED)
deleted.promise
]);
PerformanceController.clearRecordings();
yield stopped;

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

@ -3,7 +3,7 @@
/**
* Tests that an error is not thrown when clearing out the recordings if there's
* an in-progress console profile.
* an in-progress console profile and that console profiles are not cleared if in progress.
*/
function* spawnTest() {
@ -12,10 +12,15 @@ function* spawnTest() {
let win = panel.panelWin;
let { gFront, PerformanceController } = win;
yield startRecording(panel);
yield stopRecording(panel);
info("Starting console.profile()...");
yield consoleProfile(win);
yield PerformanceController.clearRecordings();
let recordings = PerformanceController.getRecordings();
is(recordings.length, 1, "1 recording found");
is(recordings[0].isConsole(), true, "recording from console.profile is not cleared.");
info("Ending console.profileEnd()...");
consoleMethod("profileEnd");
// Wait for the front to receive the stopped event
@ -26,6 +31,11 @@ function* spawnTest() {
yield idleWait(100);
ok(true, "Stopping an in-progress console profile after clearing recordings does not throw.");
yield PerformanceController.clearRecordings();
is(recordings.length, 0, "No recordings found");
is(PerformanceController.getCurrentRecording(), null,
"There should be no current recording.");
yield teardown(panel);
finish();
}

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

@ -17,14 +17,14 @@ var RecordingsView = Heritage.extend(WidgetMethods, {
this._onRecordingStateChange = this._onRecordingStateChange.bind(this);
this._onNewRecording = this._onNewRecording.bind(this);
this._onSaveButtonClick = this._onSaveButtonClick.bind(this);
this._onRecordingsCleared = this._onRecordingsCleared.bind(this);
this._onRecordingDeleted = this._onRecordingDeleted.bind(this);
this._onRecordingExported = this._onRecordingExported.bind(this);
this.emptyText = L10N.getStr("noRecordingsText");
PerformanceController.on(EVENTS.RECORDING_STATE_CHANGE, this._onRecordingStateChange);
PerformanceController.on(EVENTS.NEW_RECORDING, this._onNewRecording);
PerformanceController.on(EVENTS.RECORDINGS_CLEARED, this._onRecordingsCleared);
PerformanceController.on(EVENTS.RECORDING_DELETED, this._onRecordingDeleted);
PerformanceController.on(EVENTS.RECORDING_EXPORTED, this._onRecordingExported);
this.widget.addEventListener("select", this._onSelect, false);
},
@ -35,7 +35,7 @@ var RecordingsView = Heritage.extend(WidgetMethods, {
destroy: function() {
PerformanceController.off(EVENTS.RECORDING_STATE_CHANGE, this._onRecordingStateChange);
PerformanceController.off(EVENTS.NEW_RECORDING, this._onNewRecording);
PerformanceController.off(EVENTS.RECORDINGS_CLEARED, this._onRecordingsCleared);
PerformanceController.off(EVENTS.RECORDING_DELETED, this._onRecordingDeleted);
PerformanceController.off(EVENTS.RECORDING_EXPORTED, this._onRecordingExported);
this.widget.removeEventListener("select", this._onSelect, false);
},
@ -143,10 +143,11 @@ var RecordingsView = Heritage.extend(WidgetMethods, {
},
/**
* Clears out all recordings.
* Clears out all non-console recordings.
*/
_onRecordingsCleared: function () {
this.empty();
_onRecordingDeleted: function (_, recording) {
let recordingItem = this.getItemForPredicate(e => e.attachment === recording);
this.remove(recordingItem);
},
/**

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

@ -4,6 +4,6 @@
# 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/.
JS_PREFERENCE_FILES += [
JS_PREFERENCE_PP_FILES += [
'devtools.js',
]

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

@ -240,10 +240,9 @@ input {
}
#toggle-presets {
background: url(chrome://devtools/skin/images/pseudo-class.svg#pseudo-class);
background: url(chrome://devtools/skin/images/pseudo-class.svg);
}
.show-presets #toggle-presets {
background: url(chrome://devtools/skin/images/pseudo-class.svg#pseudo-class-checked);
filter: none;
filter: url(chrome://devtools/skin/images/filters.svg#checked-icon-state);
}

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

@ -192,6 +192,7 @@ skip-if = e10s # Bug 1042253 - webconsole tests disabled with e10s
skip-if = e10s # Bug 1042253 - webconsole tests disabled with e10s
[browser_eval_in_debugger_stackframe2.js]
[browser_jsterm_inspect.js]
skip-if = e10s && debug && os == 'win'
[browser_longstring_hang.js]
[browser_output_breaks_after_console_dir_uninspectable.js]
[browser_output_longstring_expand.js]

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

@ -18,6 +18,6 @@ MOCHITEST_CHROME_MANIFESTS += [
'test/chrome.ini'
]
JS_PREFERENCE_FILES += [
JS_PREFERENCE_PP_FILES += [
'webide-prefs.js',
]

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

@ -4,7 +4,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/devtools/DominatorTree.h"
#include "js/Debug.h"
#include "mozilla/CycleCollectedJSRuntime.h"
#include "mozilla/dom/DominatorTreeBinding.h"
@ -12,6 +11,18 @@
namespace mozilla {
namespace devtools {
static MallocSizeOf
getCurrentThreadDebuggerMallocSizeOf()
{
auto ccrt = CycleCollectedJSRuntime::Get();
MOZ_ASSERT(ccrt);
auto rt = ccrt->Runtime();
MOZ_ASSERT(rt);
auto mallocSizeOf = JS::dbg::GetDebuggerMallocSizeOf(rt);
MOZ_ASSERT(mallocSizeOf);
return mallocSizeOf;
}
dom::Nullable<uint64_t>
DominatorTree::GetRetainedSize(uint64_t aNodeId, ErrorResult& aRv)
{
@ -20,13 +31,7 @@ DominatorTree::GetRetainedSize(uint64_t aNodeId, ErrorResult& aRv)
if (node.isNothing())
return dom::Nullable<uint64_t>();
auto ccrt = CycleCollectedJSRuntime::Get();
MOZ_ASSERT(ccrt);
auto rt = ccrt->Runtime();
MOZ_ASSERT(rt);
auto mallocSizeOf = JS::dbg::GetDebuggerMallocSizeOf(rt);
MOZ_ASSERT(mallocSizeOf);
auto mallocSizeOf = getCurrentThreadDebuggerMallocSizeOf();
JS::ubi::Node::Size size = 0;
if (!mDominatorTree.getRetainedSize(*node, mallocSizeOf, size)) {
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
@ -38,6 +43,94 @@ DominatorTree::GetRetainedSize(uint64_t aNodeId, ErrorResult& aRv)
return dom::Nullable<uint64_t>(size);
}
struct NodeAndRetainedSize
{
JS::ubi::Node mNode;
JS::ubi::Node::Size mSize;
NodeAndRetainedSize(const JS::ubi::Node& aNode, JS::ubi::Node::Size aSize)
: mNode(aNode)
, mSize(aSize)
{ }
struct Comparator
{
static bool
Equals(const NodeAndRetainedSize& aLhs, const NodeAndRetainedSize& aRhs)
{
return aLhs.mSize == aRhs.mSize;
}
static bool
LessThan(const NodeAndRetainedSize& aLhs, const NodeAndRetainedSize& aRhs)
{
// Use > because we want to sort from greatest to least retained size.
return aLhs.mSize > aRhs.mSize;
}
};
};
void
DominatorTree::GetImmediatelyDominated(uint64_t aNodeId,
dom::Nullable<nsTArray<uint64_t>>& aOutResult,
ErrorResult& aRv)
{
MOZ_ASSERT(aOutResult.IsNull());
JS::ubi::Node::Id id(aNodeId);
Maybe<JS::ubi::Node> node = mHeapSnapshot->getNodeById(id);
if (node.isNothing())
return;
// Get all immediately dominated nodes and their retained sizes.
MallocSizeOf mallocSizeOf = getCurrentThreadDebuggerMallocSizeOf();
Maybe<JS::ubi::DominatorTree::DominatedSetRange> range = mDominatorTree.getDominatedSet(*node);
MOZ_ASSERT(range.isSome(), "The node should be known, since we got it from the heap snapshot.");
size_t length = range->length();
nsTArray<NodeAndRetainedSize> dominatedNodes(length);
for (const JS::ubi::Node& dominatedNode : *range) {
JS::ubi::Node::Size retainedSize = 0;
if (NS_WARN_IF(!mDominatorTree.getRetainedSize(dominatedNode, mallocSizeOf, retainedSize))) {
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
return;
}
MOZ_ASSERT(retainedSize != 0,
"retainedSize should not be zero since we know the node is in the dominator tree.");
dominatedNodes.AppendElement(NodeAndRetainedSize(dominatedNode, retainedSize));
}
// Sort them by retained size.
NodeAndRetainedSize::Comparator comparator;
dominatedNodes.Sort(comparator);
// Fill the result with the nodes' ids.
JS::ubi::Node root = mDominatorTree.root();
aOutResult.SetValue(nsTArray<uint64_t>(length));
for (const NodeAndRetainedSize& entry : dominatedNodes) {
// The root dominates itself, but we don't want to expose that to JS.
if (entry.mNode == root)
continue;
aOutResult.Value().AppendElement(entry.mNode.identifier());
}
}
dom::Nullable<uint64_t>
DominatorTree::GetImmediateDominator(uint64_t aNodeId) const
{
JS::ubi::Node::Id id(aNodeId);
Maybe<JS::ubi::Node> node = mHeapSnapshot->getNodeById(id);
if (node.isNothing())
return dom::Nullable<uint64_t>();
JS::ubi::Node dominator = mDominatorTree.getImmediateDominator(*node);
if (!dominator || dominator == *node)
return dom::Nullable<uint64_t>();
return dom::Nullable<uint64_t>(dominator.identifier());
}
/*** Cycle Collection Boilerplate *****************************************************************/

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

@ -52,6 +52,13 @@ public:
// [Throws] NodeSize getRetainedSize(NodeId node)
dom::Nullable<uint64_t> GetRetainedSize(uint64_t aNodeId, ErrorResult& aRv);
// [Throws] sequence<NodeId>? getImmediatelyDominated(NodeId node);
void GetImmediatelyDominated(uint64_t aNodeId, dom::Nullable<nsTArray<uint64_t>>& aOutDominated,
ErrorResult& aRv);
// NodeId? getImmediateDominator(NodeId node);
dom::Nullable<uint64_t> GetImmediateDominator(uint64_t aNodeId) const;
};
} // namespace devtools

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

@ -0,0 +1,75 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Test that we can get the set of immediately dominated nodes for any given
// node and that this forms a tree.
function run_test() {
var dominatorTree = saveHeapSnapshotAndComputeDominatorTree();
equal(typeof dominatorTree.getImmediatelyDominated, "function",
"getImmediatelyDominated should be a function");
// Do a traversal of the dominator tree.
//
// Note that we don't assert directly, only if we get an unexpected
// value. There are just way too many nodes in the heap graph to assert for
// every one. This test would constantly time out and assertion messages would
// overflow the log size.
var root = dominatorTree.root;
equal(dominatorTree.getImmediateDominator(root), null,
"The root should not have a parent");
var seen = new Set();
var stack = [root];
while (stack.length > 0) {
var top = stack.pop();
if (seen.has(top)) {
ok(false,
"This is a tree, not a graph: we shouldn't have multiple edges to the same node");
}
seen.add(top);
if (seen.size % 1000 === 0) {
dumpn("Progress update: seen size = " + seen.size);
}
var newNodes = dominatorTree.getImmediatelyDominated(top);
if (Object.prototype.toString.call(newNodes) !== "[object Array]") {
ok(false, "getImmediatelyDominated should return an array for known node ids");
}
var topSize = dominatorTree.getRetainedSize(top);
var lastSize = Infinity;
for (var i = 0; i < newNodes.length; i++) {
if (typeof newNodes[i] !== "number") {
ok(false, "Every dominated id should be a number");
}
if (dominatorTree.getImmediateDominator(newNodes[i]) !== top) {
ok(false, "child's parent should be the expected parent");
}
var thisSize = dominatorTree.getRetainedSize(newNodes[i]);
if (thisSize >= topSize) {
ok(false, "the size of children in the dominator tree should always be less than that of their parent");
}
if (thisSize > lastSize) {
ok(false,
"children should be sorted by greatest to least retained size, "
+ "lastSize = " + lastSize + ", thisSize = " + thisSize);
}
lastSize = thisSize;
stack.push(newNodes[i]);
}
}
ok(true, "Successfully walked the tree");
dumpn("Walked " + seen.size + " nodes");
do_test_finished();
}

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

@ -32,6 +32,7 @@ support-files =
[test_DominatorTree_02.js]
[test_DominatorTree_03.js]
[test_DominatorTree_04.js]
[test_DominatorTree_05.js]
[test_HeapAnalyses_getCreationTime_01.js]
[test_HeapAnalyses_readHeapSnapshot_01.js]
[test_HeapAnalyses_takeCensusDiff_01.js]

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

@ -13486,7 +13486,7 @@ nsDocShell::OnLinkClickSync(nsIContent* aContent,
// if per element referrer is enabled, the element referrer overrules
// the document wide referrer
if (IsElementAnchor(aContent)) {
net::ReferrerPolicy refPolEnum = aContent->AsElement()->GetReferrerPolicy();
net::ReferrerPolicy refPolEnum = aContent->AsElement()->GetReferrerPolicyAsEnum();
if (refPolEnum != net::RP_Unset) {
refererPolicy = refPolEnum;
}

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

@ -883,6 +883,14 @@ this.InterAppCommService = {
if (DEBUG) {
debug("Unregistering message port for " + manifestURL);
}
let receiver = identity.isPublisher ? identity.pair.subscriber
: identity.pair.publisher;
receiver.target.sendAsyncMessage("InterAppMessagePort:OnClose",
{ manifestURL: receiver.manifestURL,
pageURL: receiver.pageURL,
messagePortID: messagePortID });
delete this._messagePortPairs[messagePortID];
},
@ -901,7 +909,7 @@ this.InterAppCommService = {
messagePortIDs.push(messagePortID);
// Send a shutdown message to the part of the pair that is still alive.
let actor = pair.publisher.target === aTarget ? pair.subscriber
: pair.publisher;
: pair.publisher;
actor.target.sendAsyncMessage("InterAppMessagePort:Shutdown",
{ manifestURL: actor.manifestURL,
pageURL: actor.pageURL,

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

@ -30,7 +30,8 @@ XPCOMUtils.defineLazyServiceGetter(this, "appsService",
"@mozilla.org/AppsService;1",
"nsIAppsService");
const kMessages = ["InterAppMessagePort:OnMessage",
const kMessages = ["InterAppMessagePort:OnClose",
"InterAppMessagePort:OnMessage",
"InterAppMessagePort:Shutdown"];
function InterAppMessagePort() {
@ -66,6 +67,7 @@ InterAppMessagePort.prototype = {
this._started = false;
this._closed = false;
this._messageQueue = [];
this._deferredClose = false;
},
// WebIDL implementation for constructor.
@ -131,6 +133,10 @@ InterAppMessagePort.prototype = {
let message = this._messageQueue.shift();
this._dispatchMessage(message);
}
if (this._deferredClose) {
this._dispatchClose();
}
},
close: function() {
@ -143,6 +149,7 @@ InterAppMessagePort.prototype = {
}
this._closed = true;
this._deferredClose = false;
this._messageQueue.length = 0;
// When this method called on a local port that is entangled with another
@ -152,6 +159,8 @@ InterAppMessagePort.prototype = {
manifestURL: this._manifestURL });
this.removeMessageListeners(kMessages);
this._dispatchClose();
},
get onmessage() {
@ -176,6 +185,16 @@ InterAppMessagePort.prototype = {
this.start();
},
get onclose() {
if (DEBUG) debug("Getting onclose handler.");
return this.__DOM_IMPL__.getEventHandler("onclose");
},
set onclose(aHandler) {
if (DEBUG) debug("Setting onclose handler.");
this.__DOM_IMPL__.setEventHandler("onclose", aHandler);
},
_dispatchMessage: function _dispatchMessage(aMessage) {
let wrappedMessage = Cu.cloneInto(aMessage, this._window);
if (DEBUG) {
@ -189,6 +208,15 @@ InterAppMessagePort.prototype = {
this.__DOM_IMPL__.dispatchEvent(event);
},
_dispatchClose() {
if (DEBUG) debug("_dispatchClose");
let event = new this._window.Event("close", {
bubbles: true,
cancelable: true
});
this.__DOM_IMPL__.dispatchEvent(event);
},
receiveMessage: function(aMessage) {
if (DEBUG) debug("receiveMessage: name: " + aMessage.name);
@ -217,11 +245,32 @@ InterAppMessagePort.prototype = {
this._dispatchMessage(message.message);
break;
case "InterAppMessagePort:OnClose":
if (this._closed) {
if (DEBUG) debug("close() has been called. Drop the message.");
return;
}
// It is possible that one side of the port posts messages and calls
// close() before calling start() or setting the onmessage handler. In
// that case we need to queue the messages and defer the onclose event
// until the messages are delivered to the other side of the port.
if (!this._started) {
if (DEBUG) debug("Not yet called start(). Defer close notification.");
this._deferredClose = true;
return;
}
this._dispatchClose();
break;
case "InterAppMessagePort:Shutdown":
this.close();
break;
default:
if (DEBUG) debug("Error! Shouldn't fall into this case.");
dump("WARNING - Invalid InterAppMessagePort message type " +
aMessage.name + "\n");
break;
}
}

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

@ -8,7 +8,10 @@ XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini']
MOCHITEST_MANIFESTS += ['tests/mochitest.ini']
MOCHITEST_CHROME_MANIFESTS += ['tests/chrome.ini']
MOCHITEST_CHROME_MANIFESTS += [
'tests/b2g_chrome.ini',
'tests/chrome.ini'
]
EXPORTS.mozilla.dom += [
'InterAppComm.h',

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

@ -0,0 +1,6 @@
[DEFAULT]
skip-if = buildapp != 'b2g'
support-files =
iac/*
[test_iac.html]

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

@ -13,5 +13,5 @@ skip-if = os != 'linux'
[test_operator_app_install.js]
[test_operator_app_install.xul]
# bug 928262
skip-if = os == "win"
skip-if = os == 'win'
[test_packaged_app_asmjs.html]

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

@ -1,6 +1,6 @@
{
"name": "Certified hosted app",
"description": "An app that can't only be installed in dev mode.",
"description": "An app that can only be installed in dev mode.",
"launch_path": "/tests/dom/apps/tests/file_app.sjs?apptype=hosted",
"type": "certified"
}

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

@ -0,0 +1,3 @@
subscriber.list and publisher.zip contain the lists of files that are part of each app.
To update the packages of both apps when changing one of those files listed on *.list, run makezips.sh.

9
dom/apps/tests/iac/makezips.sh Executable file
Просмотреть файл

@ -0,0 +1,9 @@
#!/bin/sh
rm publisher/publisher.zip
rm subscriber/subscriber.zip
cd publisher
zip publisher.zip `cat publisher.list`
cd ../subscriber
zip subscriber.zip `cat subscriber.list`
cd ..

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

@ -0,0 +1,9 @@
<!DOCTYPE html>
<html>
<head>
<title>Publisher app for IAC API</title>
<script src="test.js"></script>
</head>
<body>
</body>
</html>

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

@ -0,0 +1,5 @@
{
"name": "IAC publisher app",
"launch_path": "/index.html",
"type": "certified"
}

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

@ -0,0 +1,3 @@
manifest.webapp
index.html
test.js

Двоичные данные
dom/apps/tests/iac/publisher/publisher.zip Normal file

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

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

@ -0,0 +1,46 @@
function ok(aCondition, aMessage) {
if (aCondition) {
alert("OK: " + aMessage);
} else {
alert("KO: " + aMessage);
}
}
function ready() {
alert("READY");
}
let _port = null;
let responseReceived = false;
function onmessage(message) {
responseReceived = (message.data == "response");
ok(responseReceived, "response received");
}
function onclose() {
ok(true, "onclose received");
if (responseReceived) {
ready();
}
}
(function makeConnection() {
ok(true, "Connecting");
navigator.mozApps.getSelf().onsuccess = event => {
ok(true, "Got self");
let app = event.target.result;
app.connect("a-connection").then(ports => {
if (!ports || !ports.length) {
return ok(false, "No ports");
}
ok(true, "Got port");
_port = ports[0];
_port.onmessage = onmessage;
_port.onclose = onclose;
_port.postMessage('something');
}).catch(error => {
ok(false, "Unexpected " + error);
});
};
})();

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

@ -0,0 +1,6 @@
{
"name": "IAC publisher app",
"launch_path": "/index.html",
"package_path": "publisher.zip",
"type": "certified"
}

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

@ -0,0 +1 @@
Content-Type: application/x-web-app-manifest+json

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

@ -0,0 +1,9 @@
<!DOCTYPE html>
<html>
<head>
<title>Subscriber app for IAC API</title>
<script src="test.js"></script>
</head>
<body>
</body>
</html>

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

@ -0,0 +1,11 @@
{
"name": "IAC subscriber app",
"launch_path": "/index.html",
"type": "certified",
"connections": {
"a-connection": {
"description": "A connection",
"rules": {}
}
}
}

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

@ -0,0 +1,3 @@
manifest.webapp
index.html
test.js

Двоичные данные
dom/apps/tests/iac/subscriber/subscriber.zip Normal file

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

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

@ -0,0 +1,9 @@
let port;
navigator.mozSetMessageHandler('connection', request => {
port = request.port;
port.onmessage = () => {
port.postMessage('response');
port.close();
};
});
alert('READY');

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

@ -0,0 +1,12 @@
{
"name": "IAC subscriber app",
"launch_path": "/index.html",
"type": "certified",
"package_path": "subscriber.zip",
"connections": {
"a-connection": {
"description": "A connection",
"rules": {}
}
}
}

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

@ -0,0 +1 @@
Content-Type: application/x-web-app-manifest+json

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

@ -46,6 +46,7 @@ skip-if = os == "android" || toolkit == "gonk" || e10s # embed-apps doesn't work
[test_bug_795164.html]
[test_bug_1168300.html]
skip-if = toolkit == "gonk" || e10s # see bug 1175784
[test_checkInstalled.html]
[test_import_export.html]
[test_install_dev_mode.html]
[test_install_multiple_apps_origin.html]
@ -69,4 +70,3 @@ skip-if = os == "android" || toolkit == "gonk" || e10s # embed-apps doesn't work
skip-if = os == "android" || toolkit == "gonk" || e10s # embed-apps doesn't work in mochitest app
[test_widget_browser.html]
skip-if = os == "android" || toolkit == "gonk" || e10s # embed-apps doesn't work in mochitest app
[test_checkInstalled.html]

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

@ -0,0 +1,237 @@
<!DOCTYPE html>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=915880
-->
<head>
<title>Test for IAC API</title>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/chrome-harness.js"></script>
<script type="application/javascript"
src="http://test/chrome/dom/activities/tests/mochi/common.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id={915880}">Mozilla Bug {915880}</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="application/javascript;version=1.7">
SimpleTest.waitForExplicitFinish();
const gURL = "http://test/chrome/dom/apps/tests/iac/";
const IAC_UI_GLUE_CID =
Components.ID("{384afeee-f1d2-4819-9d2e-9b62f6b0e382}");
function registerComponent(aObject, aDescription, aContract, aCid) {
info("Registering " + aCid);
var componentManager =
Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
componentManager.registerFactory(aCid, aDescription, aContract, aObject);
// Keep the id on the object so we can unregister later.
aObject.cid = aCid;
}
function unregisterComponent(aObject) {
info("Unregistering " + aObject.cid);
var componentManager =
Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
componentManager.unregisterFactory(aObject.cid, aObject);
}
let InterAppCommUIGlue = {
// nsISupports implementation.
QueryInterface: function(iid) {
if (iid.equals(Ci.nsISupports) ||
iid.equals(Ci.nsIFactory) ||
iid.equals(Ci.nsIInterAppCommUIGlue)) {
return this;
}
throw Cr.NS_ERROR_NO_INTERFACE;
},
// nsIFactory implementation.
createInstance: function(outer, iid) {
return this.QueryInterface(iid);
},
// nsIInterAppCommUIGlue implementation
selectApps(aCallerID, aPubAppManifestURL, aKeyword, aAppsToSelect) {
return Promise.resolve({
callerID: aCallerID,
keyword: aKeyword,
manifestURL: aPubAppManifestURL,
selectedApps: aAppsToSelect
});
}
};
registerComponent(InterAppCommUIGlue,
"InterAppComm UI Glue",
"@mozilla.org/dom/apps/inter-app-comm-ui-glue;1",
IAC_UI_GLUE_CID);
function finish() {
unregisterComponent(InterAppCommUIGlue);
SimpleTest.finish();
}
function cbError(aEvent) {
ok(false, "Error callback invoked " +
aEvent.target.error.name + " " + aEvent.target.error.message);
finish();
}
let subscriber = null;
let publisher = null;
function installApp(path) {
return new Promise((resolve, reject) => {
let request = navigator.mozApps.installPackage(gURL + path);
request.onerror = () => {
ok(false, request.error.name);
reject();
};
request.onsuccess = () => {
let app = request.result;
ok(app, "App is not null");
if (app.installState == "installed") {
return resolve(app);
}
app.ondownloadapplied = () => {
resolve(app);
};
app.ondownloaderror = () => {
ok(false, "Unexpected download error");
reject();
};
};
});
}
function launchApp(app) {
if (!app) {
ok(false, "No app to launch");
return Promise.reject();
}
return new Promise((resolve, reject) => {
let iframe = document.createElement("iframe");
iframe.setAttribute("mozbrowser", "true");
iframe.setAttribute("mozapp", app.manifestURL);
iframe.addEventListener("mozbrowsershowmodalprompt", e => {
let message = e.detail.message;
if (/OK/.exec(message)) {
ok(true, "Message from app: " + message);
} else if (/KO/.exec(message)) {
ok(false, "Message from app: " + message);
} else if (/READY/.exec(message)) {
ok(true, "Message from app: " + message);
resolve();
} else {
ok(false, "Unexpected message received: " + message);
}
}, false);
let domParent = document.getElementById("container");
domParent.appendChild(iframe);
SpecialPowers.wrap(iframe.contentWindow).location =
app.origin + app.manifest.launch_path;
});
}
const tests = [() => {
info("Test start");
SpecialPowers.setAllAppsLaunchable(true);
SpecialPowers.autoConfirmAppInstall(() => {
SpecialPowers.autoConfirmAppUninstall(next);
});
}, () => {
info("Installing subscriber app");
installApp("subscriber/update.webapp").then(app => {
subscriber = app;
next();
}).catch(() => {
ok(false, "Unable to install app");
finish();
});
}, () => {
info("Launching " + subscriber.manifest.name);
launchApp(subscriber).then(next);
}, () => {
info("Installing publisher app");
installApp("publisher/update.webapp").then(app => {
publisher = app;
next();
}).catch(() => {
ok(false, "Unable to install app");
finish();
});
}, () => {
info("Launching " + publisher.manifest.name);
launchApp(publisher).then(next);
}, () => {
navigator.mozApps.mgmt.onuninstall = event => {
let app = event.application;
next();
};
let request = navigator.mozApps.mgmt.uninstall(subscriber);
request.onerror = cbError;
}, () => {
navigator.mozApps.mgmt.onuninstall = event => {
let app = event.application;
next();
};
let request = navigator.mozApps.mgmt.uninstall(publisher);
request.onerror = cbError;
}];
const next = () => {
let step = tests.shift();
if (!step) {
return finish();
}
try {
step();
} catch(e) {
ok(false, "Test threw: " + e);
}
}
SpecialPowers.pushPermissions([{
"type": "webapps-manage",
"allow": 1,
"context": document
}, {
"type": "browser",
"allow": 1,
"context": document
}, {
"type": "embed-apps",
"allow": 1,
"context": document
}], () => {
// IAC is only allowed for certified apps. We use dev mode to
// skip the security checks.
SpecialPowers.pushPrefEnv({
"set": [
["dom.mozApps.debug", true],
["dom.apps.developer_mode", true],
["dom.mozBrowserFramesEnabled", true],
["dom.sysmsg.enabled", true]
]
}, next);
});
</script>
<div id="container"></div>
</pre>
</body>
</html>

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

@ -155,7 +155,7 @@ var steps = [
PackagedTestHelper.gAppName);
},
function() {
PackagedTestHelper.setAppVersion(1, PackagedTestHelper.next);
PackagedTestHelper.setAppVersion(1, PackagedTestHelper.next);
},
function() {
// Test mini-manifest app name is different from the webapp manifest name.

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

@ -13,6 +13,7 @@
#include "mozilla/dom/Event.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/ScriptSettings.h"
#include "jsfriendapi.h"
using mozilla::dom::AnyCallback;
using mozilla::dom::DOMError;
@ -206,14 +207,16 @@ DOMRequest::RootResultVal()
mozilla::HoldJSObjects(this);
}
already_AddRefed<Promise>
void
DOMRequest::Then(JSContext* aCx, AnyCallback* aResolveCallback,
AnyCallback* aRejectCallback, mozilla::ErrorResult& aRv)
AnyCallback* aRejectCallback,
JS::MutableHandle<JS::Value> aRetval,
mozilla::ErrorResult& aRv)
{
if (!mPromise) {
mPromise = Promise::Create(DOMEventTargetHelper::GetParentObject(), aRv);
if (aRv.Failed()) {
return nullptr;
return;
}
if (mDone) {
// Since we create mPromise lazily, it's possible that the DOMRequest object
@ -228,7 +231,10 @@ DOMRequest::Then(JSContext* aCx, AnyCallback* aResolveCallback,
}
}
return mPromise->Then(aCx, aResolveCallback, aRejectCallback, aRv);
// Just use the global of the Promise itself as the callee global.
JS::Rooted<JSObject*> global(aCx, mPromise->GetWrapper());
global = js::GetGlobalForObjectCrossCompartment(global);
mPromise->Then(aCx, global, aResolveCallback, aRejectCallback, aRetval, aRv);
}
NS_IMPL_ISUPPORTS(DOMRequestService, nsIDOMRequestService)

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

@ -74,9 +74,11 @@ public:
IMPL_EVENT_HANDLER(success)
IMPL_EVENT_HANDLER(error)
already_AddRefed<mozilla::dom::Promise>
void
Then(JSContext* aCx, AnyCallback* aResolveCallback,
AnyCallback* aRejectCallback, mozilla::ErrorResult& aRv);
AnyCallback* aRejectCallback,
JS::MutableHandle<JS::Value> aRetval,
mozilla::ErrorResult& aRv);
void FireSuccess(JS::Handle<JS::Value> aResult);
void FireError(const nsAString& aError);

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

@ -3606,11 +3606,11 @@ Element::FontSizeInflation()
}
net::ReferrerPolicy
Element::GetReferrerPolicy()
Element::GetReferrerPolicyAsEnum()
{
if (Preferences::GetBool("network.http.enablePerElementReferrer", false) &&
IsHTMLElement()) {
const nsAttrValue* referrerValue = GetParsedAttr(nsGkAtoms::referrer);
const nsAttrValue* referrerValue = GetParsedAttr(nsGkAtoms::referrerpolicy);
if (referrerValue && referrerValue->Type() == nsAttrValue::eEnum) {
return net::ReferrerPolicy(referrerValue->GetEnumValue());
}

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

@ -1074,7 +1074,7 @@ public:
*/
float FontSizeInflation();
net::ReferrerPolicy GetReferrerPolicy();
net::ReferrerPolicy GetReferrerPolicyAsEnum();
protected:
/*

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

@ -168,7 +168,7 @@ PerformanceObserver::Observe(const PerformanceObserverInit& aOptions,
return;
}
mEntryTypes = validEntryTypes;
mEntryTypes.SwapElements(validEntryTypes);
mPerformance->AddObserver(this);
mConnected = true;

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

@ -184,8 +184,6 @@ ThirdPartyUtil::IsThirdPartyChannel(nsIChannel* aChannel,
nsresult rv;
bool doForce = false;
bool checkWindowChain = true;
bool parentIsThird = false;
nsCOMPtr<nsIHttpChannelInternal> httpChannelInternal =
do_QueryInterface(aChannel);
if (httpChannelInternal) {
@ -203,109 +201,50 @@ ThirdPartyUtil::IsThirdPartyChannel(nsIChannel* aChannel,
*aResult = false;
return NS_OK;
}
if (flags & nsIHttpChannelInternal::THIRD_PARTY_PARENT_IS_THIRD_PARTY) {
// Check that the two PARENT_IS_{THIRD,SAME}_PARTY are mutually exclusive.
MOZ_ASSERT(!(flags & nsIHttpChannelInternal::THIRD_PARTY_PARENT_IS_SAME_PARTY));
// If we're not forcing and we know that the window chain of the channel
// is third party, then we know now that we're third party.
if (!doForce) {
*aResult = true;
return NS_OK;
}
checkWindowChain = false;
parentIsThird = true;
} else {
// In e10s, we can't check the parent chain in the parent, so we do so
// in the child and send the result to the parent.
// Note that we only check the window chain if neither
// THIRD_PARTY_PARENT_IS_* flag is set.
checkWindowChain = !(flags & nsIHttpChannelInternal::THIRD_PARTY_PARENT_IS_SAME_PARTY);
parentIsThird = false;
}
}
bool parentIsThird = false;
// Obtain the URI from the channel, and its base domain.
nsCOMPtr<nsIURI> channelURI;
aChannel->GetURI(getter_AddRefs(channelURI));
NS_ENSURE_TRUE(channelURI, NS_ERROR_INVALID_ARG);
rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(channelURI));
if (NS_FAILED(rv))
return rv;
nsCString channelDomain;
rv = GetBaseDomain(channelURI, channelDomain);
if (NS_FAILED(rv))
return rv;
if (aURI) {
// Determine whether aURI is foreign with respect to channelURI.
bool result;
rv = IsThirdPartyInternal(channelDomain, aURI, &result);
if (NS_FAILED(rv))
return rv;
// If it's foreign, or we're forcing, we're done.
if (result || doForce) {
*aResult = result;
return NS_OK;
if (!doForce) {
if (nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo()) {
parentIsThird = loadInfo->GetIsInThirdPartyContext();
if (!parentIsThird &&
loadInfo->GetExternalContentPolicyType() != nsIContentPolicy::TYPE_DOCUMENT) {
// Check if the channel itself is third-party to its own requestor.
// Unforunately, we have to go through the loading principal.
nsCOMPtr<nsIURI> parentURI;
loadInfo->LoadingPrincipal()->GetURI(getter_AddRefs(parentURI));
rv = IsThirdPartyInternal(channelDomain, parentURI, &parentIsThird);
if (NS_FAILED(rv))
return rv;
}
} else {
NS_WARNING("Found channel with no loadinfo, assuming third-party request");
parentIsThird = true;
}
}
// If we've already computed this in the child process, we're done.
if (!checkWindowChain) {
// If we're not comparing to a URI, we have our answer. Otherwise, if
// parentIsThird, we're not forcing and we know that we're a third-party
// request.
if (!aURI || parentIsThird) {
*aResult = parentIsThird;
return NS_OK;
}
// Find the associated window and its parent window.
nsCOMPtr<nsILoadContext> ctx;
NS_QueryNotificationCallbacks(aChannel, ctx);
if (!ctx) return NS_ERROR_INVALID_ARG;
// If there is no window, the consumer kicking off the load didn't provide one
// to the channel. This is limited to loads of certain types of resources. If
// those loads require cookies, the forceAllowThirdPartyCookie property should
// be set on the channel.
nsCOMPtr<nsIDOMWindow> ourWin, parentWin;
ctx->GetAssociatedWindow(getter_AddRefs(ourWin));
if (!ourWin) return NS_ERROR_INVALID_ARG;
nsCOMPtr<nsPIDOMWindow> piOurWin = do_QueryInterface(ourWin);
MOZ_ASSERT(piOurWin);
// We use GetScriptableParent rather than GetParent because we consider
// <iframe mozbrowser/mozapp> to be a top-level frame.
parentWin = piOurWin->GetScriptableParent();
NS_ENSURE_TRUE(parentWin, NS_ERROR_INVALID_ARG);
// Check whether this is the document channel for this window (representing a
// load of a new page). In that situation we want to avoid comparing
// channelURI to ourWin, since what's in ourWin right now will be replaced as
// the channel loads. This covers the case of a freshly kicked-off load
// (e.g. the user typing something in the location bar, or clicking on a
// bookmark), where the window's URI hasn't yet been set, and will be bogus.
// It also covers situations where a subframe is navigated to someting that
// is same-origin with all its ancestors. This is a bit of a nasty hack, but
// we will hopefully flag these channels better later.
nsLoadFlags flags;
rv = aChannel->GetLoadFlags(&flags);
NS_ENSURE_SUCCESS(rv, rv);
if (flags & nsIChannel::LOAD_DOCUMENT_URI) {
if (SameCOMIdentity(ourWin, parentWin)) {
// We only need to compare aURI to the channel URI -- the window's will be
// bogus. We already know the answer.
*aResult = false;
return NS_OK;
}
// Make sure to still compare to ourWin's ancestors
ourWin = parentWin;
}
// Check the window hierarchy. This covers most cases for an ordinary page
// load from the location bar.
return IsThirdPartyWindow(ourWin, channelURI, aResult);
// Determine whether aURI is foreign with respect to channelURI.
return IsThirdPartyInternal(channelDomain, aURI, aResult);
}
NS_IMETHODIMP

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

@ -12,9 +12,7 @@
//
// (b) a comment, which is a line that begins with "//"
//
// (c) an #if/ifdef/else/endif preprocessor directive
//
// (d) one of three possible use counter declarations:
// (c) one of three possible use counter declarations:
//
// method <IDL interface name>.<IDL operation name>
// attribute <IDL interface name>.<IDL attribute name>

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

@ -846,8 +846,7 @@ nsDOMMutationObserver::HandleMutation()
}
ClearPendingRecords();
mozilla::ErrorResult rv;
mCallback->Call(this, mutations, *this, rv);
mCallback->Call(this, mutations, *this);
}
class AsyncMutationHandler : public nsRunnable

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

@ -1438,18 +1438,44 @@ nsHTMLCopyEncoder::SetSelection(nsISelection* aSelection)
break;
}
#ifdef MOZ_THUNDERBIRD
else if (selContent->IsElement()) {
RefPtr<nsStyleContext> styleContext =
nsComputedDOMStyle::GetStyleContextForElementNoFlush(
selContent->AsElement(), nullptr, nullptr);
if (styleContext) {
const nsStyleText* textStyle = styleContext->StyleText();
if (textStyle->mWhiteSpace == NS_STYLE_WHITESPACE_PRE_WRAP) {
mIsTextWidget = true;
}
else if (selContent->IsHTMLElement(nsGkAtoms::body)) {
// Currently, setting mIsTextWidget to 'true' will result in the selection
// being encoded/copied as pre-formatted plain text.
// This is fine for copying pre-formatted plain text with Firefox, it is
// already not correct for copying pre-formatted "rich" text (bold, colour)
// with Firefox. As long as the serialisers aren't fixed, copying
// pre-formatted text in Firefox is broken. If we set mIsTextWidget,
// pre-formatted plain text is copied, but pre-formatted "rich" text loses
// the "rich" formatting. If we don't set mIsTextWidget, "rich" text
// attributes aren't lost, but white-space is lost.
// So far the story for Firefox.
//
// Thunderbird has two *conflicting* requirements.
// Case 1:
// When selecting and copying text, even pre-formatted text, as a quote
// to be placed into a reply, we *always* expect HTML to be copied.
// Case 2:
// When copying text in a so-called "plain text" message, that is
// one where the body carries style "white-space:pre-wrap", the text should
// be copied as pre-formatted plain text.
//
// Therefore the following code checks for "pre-wrap" on the body.
// This is a terrible hack.
//
// The proper fix would be this:
// For case 1:
// Communicate the fact that HTML is required to EncodeToString(),
// bug 1141786.
// For case 2:
// Wait for Firefox to get fixed to detect pre-formatting correctly,
// bug 1174452.
nsAutoString styleVal;
if (selContent->GetAttr(kNameSpaceID_None, nsGkAtoms::style, styleVal) &&
styleVal.Find(NS_LITERAL_STRING("pre-wrap")) != kNotFound) {
mIsTextWidget = true;
break;
}
}
break;
#endif
}

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

@ -411,7 +411,7 @@ nsFrameLoader::ReallyStartLoadingInternal()
net::ReferrerPolicy referrerPolicy = mOwnerContent->OwnerDoc()->GetReferrerPolicy();
HTMLIFrameElement* iframe = HTMLIFrameElement::FromContent(mOwnerContent);
if (iframe) {
net::ReferrerPolicy iframeReferrerPolicy = iframe->GetReferrerPolicy();
net::ReferrerPolicy iframeReferrerPolicy = iframe->GetReferrerPolicyAsEnum();
if (iframeReferrerPolicy != net::RP_Unset) {
referrerPolicy = iframeReferrerPolicy;
}

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