mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-12 12:55:46 +00:00
Merge mozilla-central to b2g-inbound
This commit is contained in:
commit
31b570ce3c
@ -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;
|
||||
for (auto iter = aCache.Iter(); !iter.Done(); iter.Next()) {
|
||||
T* accessible = iter.Data();
|
||||
MOZ_ASSERT(accessible && !accessible->IsDefunct());
|
||||
accessible->Document()->UnbindFromDocument(accessible);
|
||||
iter.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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
@ -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,9 +513,18 @@ var PageStyleHandler = {
|
||||
}
|
||||
}
|
||||
|
||||
let URI;
|
||||
try {
|
||||
URI = Services.io.newURI(currentStyleSheet.href, null, null);
|
||||
} catch(e) {
|
||||
if (e.result != Cr.NS_ERROR_MALFORMED_URI) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
if (URI) {
|
||||
// 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;
|
||||
|
||||
result.push({
|
||||
@ -524,6 +533,7 @@ var PageStyleHandler = {
|
||||
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];
|
||||
|
@ -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
vendored
4
browser/extensions/loop/bootstrap.js
vendored
@ -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);
|
||||
});
|
||||
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,
|
||||
});
|
||||
},
|
||||
|
||||
@ -2297,28 +2437,58 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
|
||||
})();
|
||||
|
||||
/**
|
||||
* For internal use only.
|
||||
* @ignore
|
||||
* 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 WorkerTransport = (function WorkerTransportClosure() {
|
||||
function WorkerTransport(workerInitializedCapability, pdfDataRangeTransport) {
|
||||
this.pdfDataRangeTransport = pdfDataRangeTransport;
|
||||
this.workerInitializedCapability = workerInitializedCapability;
|
||||
this.commonObjs = new PDFObjects();
|
||||
var PDFWorker = (function PDFWorkerClosure() {
|
||||
var nextFakeWorkerId = 0;
|
||||
|
||||
this.loadingTask = null;
|
||||
// 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.destroyCapability = null;
|
||||
|
||||
this.pageCache = [];
|
||||
this.pagePromises = [];
|
||||
this.downloadInfoCapability = createPromiseCapability();
|
||||
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 version 15.
|
||||
// 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) {
|
||||
@ -2329,23 +2499,41 @@ var WorkerTransport = (function WorkerTransportClosure() {
|
||||
// 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;
|
||||
var messageHandler = new MessageHandler('main', 'worker', worker);
|
||||
|
||||
messageHandler.on('test', function transportTest(data) {
|
||||
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.worker = worker;
|
||||
this._messageHandler = messageHandler;
|
||||
this._port = worker;
|
||||
this._webWorker = worker;
|
||||
if (!data.supportTransfers) {
|
||||
PDFJS.postMessageTransfers = false;
|
||||
}
|
||||
this.setupMessageHandler(messageHandler);
|
||||
workerInitializedCapability.resolve();
|
||||
this._readyCapability.resolve();
|
||||
} else {
|
||||
this.setupFakeWorker();
|
||||
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.
|
||||
@ -2363,7 +2551,95 @@ var WorkerTransport = (function WorkerTransportClosure() {
|
||||
}
|
||||
// Either workers are disabled, not supported or have thrown an exception.
|
||||
// Thus, we fallback to a faked worker.
|
||||
this.setupFakeWorker();
|
||||
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(messageHandler, loadingTask, pdfDataRangeTransport) {
|
||||
this.messageHandler = messageHandler;
|
||||
this.loadingTask = loadingTask;
|
||||
this.pdfDataRangeTransport = pdfDataRangeTransport;
|
||||
this.commonObjs = new PDFObjects();
|
||||
this.fontLoader = new FontLoader(loadingTask.docId);
|
||||
|
||||
this.destroyed = false;
|
||||
this.destroyCapability = null;
|
||||
|
||||
this.pageCache = [];
|
||||
this.pagePromises = [];
|
||||
this.downloadInfoCapability = createPromiseCapability();
|
||||
|
||||
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;
|
||||
}
|
||||
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() {
|
||||
@ -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;
|
||||
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];
|
||||
|
333
browser/extensions/pdfjs/content/build/pdf.worker.js
vendored
333
browser/extensions/pdfjs/content/build/pdf.worker.js
vendored
@ -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;
|
||||
})();
|
||||
@ -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) {
|
||||
@ -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(',') + ')';
|
||||
@ -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']
|
||||
|
9
build/unix/mozconfig.rust
Normal file
9
build/unix/mozconfig.rust
Normal file
@ -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
|
||||
|
20
configure.in
20
configure.in
@ -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
|
||||
|
@ -309,23 +309,35 @@ var PerformanceController = {
|
||||
}),
|
||||
|
||||
/**
|
||||
* 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()) {
|
||||
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 (latest && !latest.isCompleted()) {
|
||||
yield this.waitForStateChangeOnRecording(latest, "recording-stopped");
|
||||
if (!model.isRecording() && !model.isCompleted()) {
|
||||
yield this.waitForStateChangeOnRecording(model, "recording-stopped");
|
||||
}
|
||||
|
||||
this._recordings.length = 0;
|
||||
// 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 (this._recordings.length > 0) {
|
||||
if (!this._recordings.includes(this.getCurrentRecording())) {
|
||||
this.setCurrentRecording(this._recordings[0]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
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];
|
||||
},
|
||||
|
||||
|
@ -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',
|
||||
|
6
dom/apps/tests/b2g_chrome.ini
Normal file
6
dom/apps/tests/b2g_chrome.ini
Normal file
@ -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"
|
||||
}
|
||||
|
3
dom/apps/tests/iac/README.txt
Normal file
3
dom/apps/tests/iac/README.txt
Normal file
@ -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
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 ..
|
9
dom/apps/tests/iac/publisher/index.html
Normal file
9
dom/apps/tests/iac/publisher/index.html
Normal file
@ -0,0 +1,9 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Publisher app for IAC API</title>
|
||||
<script src="test.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
5
dom/apps/tests/iac/publisher/manifest.webapp
Normal file
5
dom/apps/tests/iac/publisher/manifest.webapp
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"name": "IAC publisher app",
|
||||
"launch_path": "/index.html",
|
||||
"type": "certified"
|
||||
}
|
3
dom/apps/tests/iac/publisher/publisher.list
Normal file
3
dom/apps/tests/iac/publisher/publisher.list
Normal file
@ -0,0 +1,3 @@
|
||||
manifest.webapp
|
||||
index.html
|
||||
test.js
|
BIN
dom/apps/tests/iac/publisher/publisher.zip
Normal file
BIN
dom/apps/tests/iac/publisher/publisher.zip
Normal file
Binary file not shown.
46
dom/apps/tests/iac/publisher/test.js
Normal file
46
dom/apps/tests/iac/publisher/test.js
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);
|
||||
});
|
||||
};
|
||||
})();
|
6
dom/apps/tests/iac/publisher/update.webapp
Normal file
6
dom/apps/tests/iac/publisher/update.webapp
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"name": "IAC publisher app",
|
||||
"launch_path": "/index.html",
|
||||
"package_path": "publisher.zip",
|
||||
"type": "certified"
|
||||
}
|
1
dom/apps/tests/iac/publisher/update.webapp^headers^
Normal file
1
dom/apps/tests/iac/publisher/update.webapp^headers^
Normal file
@ -0,0 +1 @@
|
||||
Content-Type: application/x-web-app-manifest+json
|
9
dom/apps/tests/iac/subscriber/index.html
Normal file
9
dom/apps/tests/iac/subscriber/index.html
Normal file
@ -0,0 +1,9 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Subscriber app for IAC API</title>
|
||||
<script src="test.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
11
dom/apps/tests/iac/subscriber/manifest.webapp
Normal file
11
dom/apps/tests/iac/subscriber/manifest.webapp
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"name": "IAC subscriber app",
|
||||
"launch_path": "/index.html",
|
||||
"type": "certified",
|
||||
"connections": {
|
||||
"a-connection": {
|
||||
"description": "A connection",
|
||||
"rules": {}
|
||||
}
|
||||
}
|
||||
}
|
3
dom/apps/tests/iac/subscriber/subscriber.list
Normal file
3
dom/apps/tests/iac/subscriber/subscriber.list
Normal file
@ -0,0 +1,3 @@
|
||||
manifest.webapp
|
||||
index.html
|
||||
test.js
|
BIN
dom/apps/tests/iac/subscriber/subscriber.zip
Normal file
BIN
dom/apps/tests/iac/subscriber/subscriber.zip
Normal file
Binary file not shown.
9
dom/apps/tests/iac/subscriber/test.js
Normal file
9
dom/apps/tests/iac/subscriber/test.js
Normal file
@ -0,0 +1,9 @@
|
||||
let port;
|
||||
navigator.mozSetMessageHandler('connection', request => {
|
||||
port = request.port;
|
||||
port.onmessage = () => {
|
||||
port.postMessage('response');
|
||||
port.close();
|
||||
};
|
||||
});
|
||||
alert('READY');
|
12
dom/apps/tests/iac/subscriber/update.webapp
Normal file
12
dom/apps/tests/iac/subscriber/update.webapp
Normal file
@ -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": {}
|
||||
}
|
||||
}
|
||||
}
|
1
dom/apps/tests/iac/subscriber/update.webapp^headers^
Normal file
1
dom/apps/tests/iac/subscriber/update.webapp^headers^
Normal file
@ -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]
|
||||
|
237
dom/apps/tests/test_iac.html
Normal file
237
dom/apps/tests/test_iac.html
Normal file
@ -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>
|
@ -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 (!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;
|
||||
|
||||
// If it's foreign, or we're forcing, we're done.
|
||||
if (result || doForce) {
|
||||
*aResult = result;
|
||||
return NS_OK;
|
||||
}
|
||||
} 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) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
#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;
|
||||
}
|
||||
|
@ -594,6 +594,7 @@ GK_ATOM(menuseparator, "menuseparator")
|
||||
GK_ATOM(message, "message")
|
||||
GK_ATOM(meta, "meta")
|
||||
GK_ATOM(referrer, "referrer")
|
||||
GK_ATOM(referrerpolicy, "referrerpolicy")
|
||||
GK_ATOM(meter, "meter")
|
||||
GK_ATOM(method, "method")
|
||||
GK_ATOM(microdataProperties, "microdataProperties")
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user