merge mozilla-inbound to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2015-12-01 15:25:14 +01:00
Родитель e224f27637 5c46934990
Коммит f3e1aec951
545 изменённых файлов: 15177 добавлений и 11213 удалений

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

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

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

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

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

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

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

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

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

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

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

@ -9,6 +9,9 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# Makefile.in uses a misc target through test_addons_TARGET.
HAS_MISC_RULE = True
BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
JETPACK_PACKAGE_MANIFESTS += ['source/test/jetpack-package.ini']
JETPACK_ADDON_MANIFESTS += ['source/test/addons/jetpack-addon.ini']

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

@ -4,6 +4,9 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# Makefile.in uses a misc target through test_addons_TARGET.
HAS_MISC_RULE = True
BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
JETPACK_PACKAGE_MANIFESTS += ['source/test/jetpack-package.ini']
JETPACK_ADDON_MANIFESTS += ['source/test/addons/jetpack-addon.ini']

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

@ -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

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

@ -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");

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

@ -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
}
]

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

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

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

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

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

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

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

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

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

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

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

@ -5,19 +5,6 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
ifndef NO_DIST_INSTALL
ifdef SHARED_LIBRARY
ifdef IS_COMPONENT
target:: $(SUBMAKEFILES) $(SHARED_LIBRARY)
$(INSTALL) $(IFLAGS2) $(SHARED_LIBRARY) $(FINAL_TARGET)/components
ifndef NO_COMPONENTS_MANIFEST
$(call py_action,buildlist,$(FINAL_TARGET)/chrome.manifest 'manifest components/components.manifest')
$(call py_action,buildlist,$(FINAL_TARGET)/components/components.manifest 'binary-component $(SHARED_LIBRARY)')
endif
endif # IS_COMPONENT
endif # SHARED_LIBRARY
endif # !NO_DIST_INSTALL
ifndef NO_DIST_INSTALL
ifneq (,$(strip $(PROGRAM)$(SIMPLE_PROGRAMS)))
@ -37,12 +24,10 @@ endif # LIBRARY
ifdef SHARED_LIBRARY
ifndef IS_COMPONENT
SHARED_LIBRARY_FILES = $(SHARED_LIBRARY)
SHARED_LIBRARY_DEST ?= $(FINAL_TARGET)
SHARED_LIBRARY_DEST ?= $(FINAL_TARGET)$(if $(IS_COMPONENT),/components)
SHARED_LIBRARY_TARGET = target
INSTALL_TARGETS += SHARED_LIBRARY
endif # ! IS_COMPONENT
endif # SHARED_LIBRARY
ifneq (,$(strip $(HOST_SIMPLE_PROGRAMS)$(HOST_PROGRAM)))

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

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

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

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

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

@ -672,7 +672,7 @@ See https://developer.mozilla.org/en/Windows_Build_Prerequisites.])
fi
if test "$WRAP_STL_INCLUDES" = "1"; then
STL_FLAGS='-I$(DIST)/stl_wrappers'
STL_FLAGS="-I${DIST}/stl_wrappers"
fi
CFLAGS="$CFLAGS -D_HAS_EXCEPTIONS=0"
CXXFLAGS="$CXXFLAGS -D_HAS_EXCEPTIONS=0"
@ -2583,7 +2583,7 @@ if test "$GNU_CC" -a "$OS_TARGET" != WINNT; then
VISIBILITY_FLAGS='-fvisibility=hidden -fvisibility-inlines-hidden'
;;
*)
VISIBILITY_FLAGS='-I$(DIST)/system_wrappers -include $(MOZILLA_DIR)/config/gcc_hidden.h'
VISIBILITY_FLAGS="-I${DIST}/system_wrappers -include ${_topsrcdir}/config/gcc_hidden.h"
WRAP_SYSTEM_INCLUDES=1
;;
esac
@ -2598,13 +2598,13 @@ case "${OS_TARGET}" in
WINNT|Darwin|Android)
;;
*)
STL_FLAGS='-I$(DIST)/stl_wrappers'
STL_FLAGS="-I${DIST}/stl_wrappers"
WRAP_STL_INCLUDES=1
;;
esac
AC_SUBST(WRAP_SYSTEM_INCLUDES)
AC_SUBST(VISIBILITY_FLAGS)
AC_SUBST_LIST(VISIBILITY_FLAGS)
dnl Checks for header files.
dnl ========================================================
@ -8143,12 +8143,8 @@ fi
if test "$MOZ_TREE_PIXMAN"; then
AC_DEFINE(MOZ_TREE_PIXMAN)
else
PKG_CHECK_MODULES(PIXMAN, pixman-1 >= 0.19.2)
MOZ_PIXMAN_CFLAGS="$PIXMAN_CFLAGS"
MOZ_PIXMAN_LIBS="$PIXMAN_LIBS"
PKG_CHECK_MODULES(MOZ_PIXMAN, pixman-1 >= 0.19.2)
fi
AC_SUBST(MOZ_PIXMAN_CFLAGS)
AC_SUBST_LIST(MOZ_PIXMAN_LIBS)
# Check for headers defining standard int types.
if test -n "$COMPILE_ENVIRONMENT"; then
@ -9275,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

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

@ -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',
]

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

@ -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")

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

@ -1668,7 +1668,8 @@ nsXMLHttpRequest::Open(const nsACString& inMethod, const nsACString& url,
nsCOMPtr<nsILoadGroup> loadGroup = GetLoadGroup();
nsSecurityFlags secFlags;
nsLoadFlags loadFlags = nsIRequest::LOAD_BACKGROUND;
nsLoadFlags loadFlags = nsIRequest::LOAD_BACKGROUND |
nsIChannel::LOAD_CLASSIFY_URI;
if (nsContentUtils::IsSystemPrincipal(mPrincipal)) {
// When chrome is loading we want to make sure to sandbox any potential
// result document. We also want to allow cross-origin loads.

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

@ -14,7 +14,7 @@ function createTestPage(aHead, aImgPolicy, aName) {
<html>'+
aHead +
'<body>\n\
<img src="' + _createTestUrl('img') + '" referrer="' + aImgPolicy + '" id="image"></img>\n\
<img src="' + _createTestUrl('img') + '" referrerpolicy="' + aImgPolicy + '" id="image"></img>\n\
<script>' +
// LOAD EVENT (of the test)
@ -52,9 +52,9 @@ function createTest3(aImgPolicy1, aImgPolicy2, aImgPolicy3, aName) {
return '<!DOCTYPE HTML>\n\
<html>\n\
<body>\n\
<img src="' + createTestUrl(aImgPolicy1, 'test', aName + aImgPolicy1) + '" referrer="' + aImgPolicy1 + '" id="image"></img>\n\
<img src="' + createTestUrl(aImgPolicy2, 'test', aName + aImgPolicy2) + '" referrer="' + aImgPolicy2 + '" id="image"></img>\n\
<img src="' + createTestUrl(aImgPolicy3, 'test', aName + aImgPolicy3) + '" referrer="' + aImgPolicy3 + '" id="image"></img>\n\
<img src="' + createTestUrl(aImgPolicy1, 'test', aName + aImgPolicy1) + '" referrerpolicy="' + aImgPolicy1 + '" id="image"></img>\n\
<img src="' + createTestUrl(aImgPolicy2, 'test', aName + aImgPolicy2) + '" referrerpolicy="' + aImgPolicy2 + '" id="image"></img>\n\
<img src="' + createTestUrl(aImgPolicy3, 'test', aName + aImgPolicy3) + '" referrerpolicy="' + aImgPolicy3 + '" id="image"></img>\n\
<script>\n\
var _numLoads = 0;' +

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

@ -33,11 +33,11 @@ function createIframeTestPageUsingRefferer(aMetaPolicy, aAttributePolicy, aNewAt
}
var changeString = "";
if (aChangingMethod === "setAttribute") {
changeString = `document.getElementById("myframe").setAttribute("referrer", "${aNewAttributePolicy}")`;
changeString = `document.getElementById("myframe").setAttribute("referrerpolicy", "${aNewAttributePolicy}")`;
} else if (aChangingMethod === "property") {
changeString = `document.getElementById("myframe").referrer = "${aNewAttributePolicy}"`;
changeString = `document.getElementById("myframe").referrerPolicy = "${aNewAttributePolicy}"`;
}
var iFrameString = `<iframe src="" id="myframe" ${aAttributePolicy ? ` referrer="${aAttributePolicy}"` : ""}>iframe</iframe>`;
var iFrameString = `<iframe src="" id="myframe" ${aAttributePolicy ? ` referrerpolicy="${aAttributePolicy}"` : ""}>iframe</iframe>`;
var iframeUrl = "";
if (aParams) {
aParams.delete("ACTION");
@ -69,7 +69,7 @@ function createIframeTestPageUsingRefferer(aMetaPolicy, aAttributePolicy, aNewAt
function buildAnchorString(aMetaPolicy, aReferrerPolicy, aName, aRelString){
if (aReferrerPolicy) {
return `<a href="${createTestUrl(aReferrerPolicy, 'test', aName, 'link')}" referrer="${aReferrerPolicy}" id="link" ${aRelString}>${aReferrerPolicy}</a>`;
return `<a href="${createTestUrl(aReferrerPolicy, 'test', aName, 'link')}" referrerpolicy="${aReferrerPolicy}" id="link" ${aRelString}>${aReferrerPolicy}</a>`;
}
return `<a href="${createTestUrl(aMetaPolicy, 'test', aName, 'link')}" id="link" ${aRelString}>link</a>`;
}
@ -78,7 +78,7 @@ function buildAreaString(aMetaPolicy, aReferrerPolicy, aName, aRelString){
var result = `<img src="file_mozfiledataurl_img.jpg" alt="image" usemap="#imageMap">`;
result += `<map name="imageMap">`;
if (aReferrerPolicy) {
result += `<area shape="circle" coords="1,1,1" href="${createTestUrl(aReferrerPolicy, 'test', aName, 'link')}" alt="theArea" referrer="${aReferrerPolicy}" id="link" ${aRelString}>`;
result += `<area shape="circle" coords="1,1,1" href="${createTestUrl(aReferrerPolicy, 'test', aName, 'link')}" alt="theArea" referrerpolicy="${aReferrerPolicy}" id="link" ${aRelString}>`;
} else {
result += `<area shape="circle" coords="1,1,1" href="${createTestUrl(aMetaPolicy, 'test', aName, 'link')}" alt="theArea" id="link" ${aRelString}>`;
}
@ -95,9 +95,9 @@ function createAETestPageUsingRefferer(aMetaPolicy, aAttributePolicy, aNewAttrib
}
var changeString = "";
if (aChangingMethod === "setAttribute") {
changeString = `document.getElementById("link").setAttribute("referrer", "${aNewAttributePolicy}")`;
changeString = `document.getElementById("link").setAttribute("referrerpolicy", "${aNewAttributePolicy}")`;
} else if (aChangingMethod === "property") {
changeString = `document.getElementById("link").referrer = "${aNewAttributePolicy}"`;
changeString = `document.getElementById("link").referrerPolicy = "${aNewAttributePolicy}"`;
}
var relString = "";
if (aRel) {
@ -138,7 +138,7 @@ function createRedirectImgTestCase(aParams, aAttributePolicy) {
<title>Test referrer policies on redirect (img)</title>
</head>
<body>
<img id="testImg" src="${imgUrl}" ${aAttributePolicy ? ` referrer="${aAttributePolicy}"` : ""}>
<img id="testImg" src="${imgUrl}" ${aAttributePolicy ? ` referrerpolicy="${aAttributePolicy}"` : ""}>
<script>
window.addEventListener("load", function() {
parent.postMessage("childLoadComplete", "http://mochi.test:8888");

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

@ -67,17 +67,17 @@ function run_test() {
NS_ERROR_INVALID_ARG);
// We can't test isThirdPartyWindow since we can't really set up a window
// heirarchy. We leave that to mochitests.
// hierarchy. We leave that to mochitests.
// Test isThirdPartyChannel. As above, we can't test the bits that require
// a load context or window heirarchy.
// a load context or window heirarchy. Because of that, the code assumes
// that these are all third-party loads.
do_check_throws(function() { util.isThirdPartyChannel(null); },
NS_ERROR_INVALID_ARG);
do_check_throws(function() { util.isThirdPartyChannel(channel1); },
NS_ERROR_INVALID_ARG);
do_check_throws(function() { util.isThirdPartyChannel(channel1, uri1); },
NS_ERROR_INVALID_ARG);
do_check_true(util.isThirdPartyChannel(channel1));
do_check_true(util.isThirdPartyChannel(channel1, uri1));
do_check_true(util.isThirdPartyChannel(channel1, uri2));
let httpchannel1 = channel1.QueryInterface(Ci.nsIHttpChannelInternal);
httpchannel1.forceAllowThirdPartyCookie = true;
do_check_false(util.isThirdPartyChannel(channel1));

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

@ -8,18 +8,9 @@ import re
import StringIO
import sys
from mozbuild.preprocessor import preprocess
def read_conf(conf_filename):
# Invoking the preprocessor ourselves is easier than writing build rules
# to do it for us.
processed = StringIO.StringIO()
preprocess(includes=[conf_filename],
defines=buildconfig.defines,
output=processed)
# Can't read/write from a single StringIO, so make a new one for reading.
stream = StringIO.StringIO(processed.getvalue())
stream = open(conf_filename, 'rU')
def parse_counters(stream):
for line_num, line in enumerate(stream):

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

@ -2761,8 +2761,17 @@ ConvertExceptionToPromise(JSContext* cx,
}
JS_ClearPendingException(cx);
nsCOMPtr<nsIGlobalObject> globalObj =
do_QueryInterface(global.GetAsSupports());
if (!globalObj) {
ErrorResult rv;
rv.Throw(NS_ERROR_UNEXPECTED);
return !rv.MaybeSetPendingException(cx);
}
ErrorResult rv;
RefPtr<Promise> promise = Promise::Reject(global, exn, rv);
RefPtr<Promise> promise = Promise::Reject(globalObj, cx, exn, rv);
if (rv.MaybeSetPendingException(cx)) {
// We just give up. We put the exception from the ErrorResult on
// the JSContext just to make sure to not leak memory on the

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

@ -1949,7 +1949,13 @@ DOMInterfaces = {
# Keep this in sync with TestExampleInterface
'headerFile': 'TestBindingHeader.h',
'register': False
}
},
'TestInterfaceWithPromiseConstructorArg' : {
'headerFile': 'TestBindingHeader.h',
'register': False,
},
}
# These are temporary, until they've been converted to use new DOM bindings

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

@ -2779,7 +2779,7 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
for pref, ptr in prefCacheData]
prefCache = CGWrapper(CGIndenter(CGList(prefCacheData)),
pre=("static bool sPrefCachesInited = false;\n"
"if (!sPrefCachesInited) {\n"
"if (!sPrefCachesInited && NS_IsMainThread()) {\n"
" sPrefCachesInited = true;\n"),
post="}\n")
else:
@ -2979,6 +2979,21 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
else:
unforgeableHolderSetup = None
if self.descriptor.name == "Promise":
speciesSetup = CGGeneric(fill(
"""
JS::Rooted<JSObject*> promiseConstructor(aCx, *interfaceCache);
JS::Rooted<jsid> species(aCx,
SYMBOL_TO_JSID(JS::GetWellKnownSymbol(aCx, JS::SymbolCode::species)));
if (!JS_DefinePropertyById(aCx, promiseConstructor, species, JS::UndefinedHandleValue,
JSPROP_SHARED, Promise::PromiseSpecies, nullptr)) {
$*{failureCode}
}
""",
failureCode=failureCode))
else:
speciesSetup = None
if (self.descriptor.interface.isOnGlobalProtoChain() and
needInterfacePrototypeObject):
makeProtoPrototypeImmutable = CGGeneric(fill(
@ -3004,7 +3019,7 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
return CGList(
[getParentProto, CGGeneric(getConstructorProto), initIds,
prefCache, CGGeneric(call), defineAliases, unforgeableHolderSetup,
makeProtoPrototypeImmutable],
speciesSetup, makeProtoPrototypeImmutable],
"\n").define()
@ -5078,24 +5093,124 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
templateBody += 'static_assert(IsRefcounted<%s>::value, "We can only store refcounted classes.");' % typeName
if isPromise:
# Per spec, what we're supposed to do is take the original
# Promise.resolve and call it with the original Promise as this
# value to make a Promise out of whatever value we actually have
# here. The question is which global we should use. There are
# several cases to consider:
#
# 1) Normal call to API with a Promise argument. This is a case the
# spec covers, and we should be using the current Realm's
# Promise. That means the current compartment.
# 2) Call to API with a Promise argument over Xrays. In practice,
# this sort of thing seems to be used for giving an API
# implementation a way to wait for conclusion of an asyc
# operation, _not_ to expose the Promise to content code. So we
# probably want to allow callers to use such an API in a
# "natural" way, by passing chrome-side promises; indeed, that
# may be all that the caller has to represent their async
# operation. That means we really need to do the
# Promise.resolve() in the caller (chrome) compartment: if we do
# it in the content compartment, we will try to call .then() on
# the chrome promise while in the content compartment, which will
# throw and we'll just get a rejected Promise. Note that this is
# also the reason why a caller who has a chrome Promise
# representing an async operation can't itself convert it to a
# content-side Promise (at least not without some serious
# gyrations).
# 3) Promise return value from a callback or callback interface.
# This is in theory a case the spec covers but in practice it
# really doesn't define behavior here because it doesn't define
# what Realm we're in after the callback returns, which is when
# the argument conversion happens. We will use the current
# compartment, which is the compartment of the callable (which
# may itself be a cross-compartment wrapper itself), which makes
# as much sense as anything else. In practice, such an API would
# once again be providing a Promise to signal completion of an
# operation, which would then not be exposed to anyone other than
# our own implementation code.
# 4) Return value from a JS-implemented interface. In this case we
# have a problem. Our current compartment is the compartment of
# the JS implementation. But if the JS implementation returned
# a page-side Promise (which is a totally sane thing to do, and
# in fact the right thing to do given that this return value is
# going right to content script) then we don't want to
# Promise.resolve with our current compartment Promise, because
# that will wrap it up in a chrome-side Promise, which is
# decidedly _not_ what's desired here. So in that case we
# should really unwrap the return value and use the global of
# the result. CheckedUnwrap should be good enough for that; if
# it fails, then we're failing unwrap while in a
# system-privileged compartment, so presumably we have a dead
# object wrapper. Just error out. Do NOT fall back to using
# the current compartment instead: that will return a
# system-privileged rejected (because getting .then inside
# resolve() failed) Promise to the caller, which they won't be
# able to touch. That's not helpful. If we error out, on the
# other hand, they will get a content-side rejected promise.
# Same thing if the value returned is not even an object.
if isCallbackReturnValue == "JSImpl":
# Case 4 above. Note that globalObj defaults to the current
# compartment global. Note that we don't use $*{exceptionCode}
# here because that will try to aRv.Throw(NS_ERROR_UNEXPECTED)
# which we don't really want here.
assert exceptionCode == "aRv.Throw(NS_ERROR_UNEXPECTED);\nreturn nullptr;\n"
getPromiseGlobal = fill(
"""
if (!$${val}.isObject()) {
aRv.ThrowTypeError<MSG_NOT_OBJECT>(NS_LITERAL_STRING("${sourceDescription}"));
return nullptr;
}
JSObject* unwrappedVal = js::CheckedUnwrap(&$${val}.toObject());
if (!unwrappedVal) {
// A slight lie, but not much of one, for a dead object wrapper.
aRv.ThrowTypeError<MSG_NOT_OBJECT>(NS_LITERAL_STRING("${sourceDescription}"));
return nullptr;
}
globalObj = js::GetGlobalForObjectCrossCompartment(unwrappedVal);
""",
sourceDescription=sourceDescription)
else:
getPromiseGlobal = ""
templateBody = fill(
"""
{ // Scope for our GlobalObject and ErrorResult
{ // Scope for our GlobalObject, ErrorResult, JSAutoCompartment,
// etc.
// Might as well use CurrentGlobalOrNull here; that will at
// least give us the same behavior as if the caller just called
// Promise.resolve() themselves.
GlobalObject promiseGlobal(cx, JS::CurrentGlobalOrNull(cx));
JS::Rooted<JSObject*> globalObj(cx, JS::CurrentGlobalOrNull(cx));
$*{getPromiseGlobal}
JSAutoCompartment ac(cx, globalObj);
GlobalObject promiseGlobal(cx, globalObj);
if (promiseGlobal.Failed()) {
$*{exceptionCode}
}
ErrorResult promiseRv;
$${declName} = Promise::Resolve(promiseGlobal, $${val}, promiseRv);
JS::Handle<JSObject*> promiseCtor =
PromiseBinding::GetConstructorObjectHandle(cx, globalObj);
if (!promiseCtor) {
$*{exceptionCode}
}
JS::Rooted<JS::Value> resolveThisv(cx, JS::ObjectValue(*promiseCtor));
JS::Rooted<JS::Value> resolveResult(cx);
JS::Rooted<JS::Value> valueToResolve(cx, $${val});
if (!JS_WrapValue(cx, &valueToResolve)) {
$*{exceptionCode}
}
Promise::Resolve(promiseGlobal, resolveThisv, valueToResolve,
&resolveResult, promiseRv);
if (promiseRv.MaybeSetPendingException(cx)) {
$*{exceptionCode}
}
nsresult unwrapRv = UNWRAP_OBJECT(Promise, &resolveResult.toObject(), $${declName});
if (NS_FAILED(unwrapRv)) { // Quite odd
promiseRv.Throw(unwrapRv);
promiseRv.MaybeSetPendingException(cx);
$*{exceptionCode}
}
}
""",
getPromiseGlobal=getPromiseGlobal,
exceptionCode=exceptionCode)
elif not descriptor.skipGen and not descriptor.interface.isConsequential() and not descriptor.interface.isExternal():
if failureCode is not None:
@ -7032,16 +7147,59 @@ class CGPerSignatureCall(CGThing):
if needsCx:
argsPre.append("cx")
# Hack for making Promise.prototype.then work well over Xrays.
if (not static and
(descriptor.name == "Promise" or
descriptor.name == "MozAbortablePromise") and
idlNode.isMethod() and
idlNode.identifier.name == "then"):
cgThings.append(CGGeneric(dedent(
"""
JS::Rooted<JSObject*> calleeGlobal(cx, xpc::XrayAwareCalleeGlobal(&args.callee()));
""")))
argsPre.append("calleeGlobal")
needsUnwrap = False
argsPost = []
if isConstructor:
needsUnwrap = True
needsUnwrappedVar = False
unwrappedVar = "obj"
if descriptor.name == "Promise" or descriptor.name == "MozAbortablePromise":
# Hack for Promise for now: pass in our desired proto so the
# implementation can create the reflector with the right proto.
argsPost.append("desiredProto")
# Also, we do not want to enter the content compartment when the
# Promise constructor is called via Xrays, because we want to
# create our callback functions that we will hand to our caller
# in the Xray compartment. The reason we want to do that is the
# following situation, over Xrays:
#
# contentWindow.Promise.race([Promise.resolve(5)])
#
# Ideally this would work. Internally, race() does a
# contentWindow.Promise.resolve() on everything in the array.
# Per spec, to support subclassing,
# contentWindow.Promise.resolve has to do:
#
# var resolve, reject;
# var p = new contentWindow.Promise(function(a, b) {
# resolve = a;
# reject = b;
# });
# resolve(arg);
# return p;
#
# where "arg" is, in this case, the chrome-side return value of
# Promise.resolve(5). But if the "resolve" function in that
# case were created in the content compartment, then calling it
# would wrap "arg" in an opaque wrapper, and that function tries
# to get .then off the argument, which would throw. So we need
# to create the "resolve" function in the chrome compartment,
# and hence want to be running the entire Promise constructor
# (which creates that function) in the chrome compartment in
# this case. So don't set needsUnwrap here.
else:
needsUnwrap = True
needsUnwrappedVar = False
unwrappedVar = "obj"
elif descriptor.interface.isJSImplemented():
if not idlNode.isStatic():
needsUnwrap = True
@ -7054,6 +7212,11 @@ class CGPerSignatureCall(CGThing):
needsUnwrappedVar = True
argsPre.append("unwrappedObj ? *unwrappedObj : obj")
if static and not isConstructor and descriptor.name == "Promise":
# Hack for Promise for now: pass in the "this" value to
# Promise static methods.
argsPre.append("args.thisv()")
if needsUnwrap and needsUnwrappedVar:
# We cannot assign into obj because it's a Handle, not a
# MutableHandle, so we need a separate Rooted.
@ -8998,26 +9161,6 @@ class CGStaticMethodJitinfo(CGGeneric):
IDLToCIdentifier(method.identifier.name))))
class CGMethodIdentityTest(CGAbstractMethod):
"""
A class to generate a method-identity test for a given IDL operation.
"""
def __init__(self, descriptor, method):
self.method = method
name = "Is%sMethod" % MakeNativeName(method.identifier.name)
CGAbstractMethod.__init__(self, descriptor, name, 'bool',
[Argument('JS::Handle<JSObject*>', 'aObj')])
def definition_body(self):
return dedent(
"""
MOZ_ASSERT(aObj);
return js::IsFunctionObject(aObj) &&
js::FunctionObjectIsNative(aObj) &&
FUNCTION_VALUE_TO_JITINFO(JS::ObjectValue(*aObj)) == &%s_methodinfo;
""" % IDLToCIdentifier(self.method.identifier.name))
def getEnumValueName(value):
# Some enum values can be empty strings. Others might have weird
# characters in them. Deal with the former by returning "_empty",
@ -11649,8 +11792,6 @@ class CGDescriptor(CGThing):
cgThings.append(CGMemberJITInfo(descriptor, m))
if props.isCrossOriginMethod:
crossOriginMethods.add(m.identifier.name)
if m.getExtendedAttribute("MethodIdentityTestable"):
cgThings.append(CGMethodIdentityTest(descriptor, m))
# If we've hit the maplike/setlike member itself, go ahead and
# generate its convenience functions.
elif m.isMaplikeOrSetlike():
@ -14385,16 +14526,33 @@ class CGCallback(CGClass):
assert args[0].name == "cx" and args[0].argType == "JSContext*"
assert args[1].name == "aThisVal" and args[1].argType == "JS::Handle<JS::Value>"
args = args[2:]
# Now remember which index the ErrorResult argument is at;
# we'll need this below.
assert args[-1].name == "aRv" and args[-1].argType == "ErrorResult&"
rvIndex = len(args) - 1
assert rvIndex >= 0
# Record the names of all the arguments, so we can use them when we call
# the private method.
argnames = [arg.name for arg in args]
argnamesWithThis = ["s.GetContext()", "thisValJS"] + argnames
argnamesWithoutThis = ["s.GetContext()", "JS::UndefinedHandleValue"] + argnames
# Now that we've recorded the argnames for our call to our private
# method, insert our optional arguments for the execution reason and for
# deciding whether the CallSetup should re-throw exceptions on aRv.
# method, insert our optional argument for the execution reason.
args.append(Argument("const char*", "aExecutionReason",
"nullptr"))
# Make copies of the arg list for the two "without rv" overloads. Note
# that those don't need aExceptionHandling or aCompartment arguments
# because those would make not sense anyway: the only sane thing to do
# with exceptions in the "without rv" cases is to report them.
argsWithoutRv = list(args)
argsWithoutRv.pop(rvIndex)
argsWithoutThisAndRv = list(argsWithoutRv)
# Add the potional argument for deciding whether the CallSetup should
# re-throw exceptions on aRv.
args.append(Argument("ExceptionHandling", "aExceptionHandling",
"eReportExceptions"))
# And the argument for communicating when exceptions should really be
@ -14406,6 +14564,22 @@ class CGCallback(CGClass):
# And now insert our template argument.
argsWithoutThis = list(args)
args.insert(0, Argument("const T&", "thisVal"))
argsWithoutRv.insert(0, Argument("const T&", "thisVal"))
argnamesWithoutThisAndRv = [arg.name for arg in argsWithoutThisAndRv]
argnamesWithoutThisAndRv.insert(rvIndex, "rv");
# If we just leave things like that, and have no actual arguments in the
# IDL, we will end up trying to call the templated "without rv" overload
# with "rv" as the thisVal. That's no good. So explicitly append the
# aExceptionHandling and aCompartment values we need to end up matching
# the signature of our non-templated "with rv" overload.
argnamesWithoutThisAndRv.extend(["eReportExceptions", "nullptr"])
argnamesWithoutRv = [arg.name for arg in argsWithoutRv]
# Note that we need to insert at rvIndex + 1, since we inserted a
# thisVal arg at the start.
argnamesWithoutRv.insert(rvIndex + 1, "rv")
errorReturn = method.getDefaultRetval()
setupCall = fill(
@ -14445,6 +14619,20 @@ class CGCallback(CGClass):
errorReturn=errorReturn,
methodName=method.name,
callArgs=", ".join(argnamesWithoutThis))
bodyWithThisWithoutRv = fill(
"""
IgnoredErrorResult rv;
return ${methodName}(${callArgs});
""",
methodName=method.name,
callArgs=", ".join(argnamesWithoutRv))
bodyWithoutThisAndRv = fill(
"""
IgnoredErrorResult rv;
return ${methodName}(${callArgs});
""",
methodName=method.name,
callArgs=", ".join(argnamesWithoutThisAndRv))
return [ClassMethod(method.name, method.returnType, args,
bodyInHeader=True,
@ -14453,6 +14641,13 @@ class CGCallback(CGClass):
ClassMethod(method.name, method.returnType, argsWithoutThis,
bodyInHeader=True,
body=bodyWithoutThis),
ClassMethod(method.name, method.returnType, argsWithoutRv,
bodyInHeader=True,
templateArgs=["typename T"],
body=bodyWithThisWithoutRv),
ClassMethod(method.name, method.returnType, argsWithoutThisAndRv,
bodyInHeader=True,
body=bodyWithoutThisAndRv),
method]
def deps(self):

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

@ -398,6 +398,16 @@ private:
void operator=(const ErrorResult&) = delete;
};
// A class for use when an ErrorResult should just automatically be ignored.
class IgnoredErrorResult : public ErrorResult
{
public:
~IgnoredErrorResult()
{
SuppressException();
}
};
/******************************************************************************
** Macros for checking results
******************************************************************************/

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

@ -83,5 +83,11 @@ MSG_DEF(MSG_NOTIFICATION_PERMISSION_DENIED, 0, JSEXN_TYPEERR, "Permission to sho
MSG_DEF(MSG_NOTIFICATION_NO_CONSTRUCTOR_IN_SERVICEWORKER, 0, JSEXN_TYPEERR, "Notification constructor cannot be used in ServiceWorkerGlobalScope. Use registration.showNotification() instead.")
MSG_DEF(MSG_INVALID_SCOPE, 2, JSEXN_TYPEERR, "Invalid scope trying to resolve {0} with base URL {1}.")
MSG_DEF(MSG_INVALID_KEYFRAME_OFFSETS, 0, JSEXN_TYPEERR, "Keyframes with specified offsets must be in order and all be in the range [0, 1].")
MSG_DEF(MSG_ILLEGAL_PROMISE_CONSTRUCTOR, 0, JSEXN_TYPEERR, "Non-constructor value passed to NewPromiseCapability.")
MSG_DEF(MSG_PROMISE_CAPABILITY_HAS_SOMETHING_ALREADY, 0, JSEXN_TYPEERR, "GetCapabilitiesExecutor function already invoked with non-undefined values.")
MSG_DEF(MSG_PROMISE_RESOLVE_FUNCTION_NOT_CALLABLE, 0, JSEXN_TYPEERR, "A Promise subclass passed a non-callable value as the resolve function.")
MSG_DEF(MSG_PROMISE_REJECT_FUNCTION_NOT_CALLABLE, 0, JSEXN_TYPEERR, "A Promise subclass passed a non-callable value as the reject function.")
MSG_DEF(MSG_PROMISE_ARG_NOT_ITERABLE, 1, JSEXN_TYPEERR, "{0} is not iterable")
MSG_DEF(MSG_IS_NOT_PROMISE, 1, JSEXN_TYPEERR, "{0} is not a Promise")
MSG_DEF(MSG_SW_INSTALL_ERROR, 2, JSEXN_TYPEERR, "ServiceWorker script at {0} for scope {1} encountered an error during installation.")
MSG_DEF(MSG_SW_SCRIPT_THREW, 2, JSEXN_TYPEERR, "ServiceWorker script at {0} for scope {1} threw an exception during script evaluation.")

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

@ -4805,7 +4805,6 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
identifier == "CheckAnyPermissions" or
identifier == "CheckAllPermissions" or
identifier == "BinaryName" or
identifier == "MethodIdentityTestable" or
identifier == "StaticClassOverride"):
# Known attributes that we don't need to do anything with here
pass

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

@ -1371,6 +1371,18 @@ public:
virtual nsISupports* GetParentObject();
};
class TestInterfaceWithPromiseConstructorArg : public nsISupports, public nsWrapperCache
{
public:
NS_DECL_ISUPPORTS
static
already_AddRefed<TestInterfaceWithPromiseConstructorArg>
Constructor(const GlobalObject&, Promise&, ErrorResult&);
virtual nsISupports* GetParentObject();
};
} // namespace dom
} // namespace mozilla

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

@ -55,6 +55,7 @@ callback interface TestCallbackInterface {
void passVariadicNullableTypedArray(Float32Array?... arg);
Uint8Array receiveUint8Array();
attribute Uint8Array uint8ArrayAttr;
Promise<void> receivePromise();
};
callback interface TestSingleOperationCallbackInterface {
@ -1034,6 +1035,9 @@ dictionary Dict : ParentDict {
CustomEventInit customEventInit;
TestDictionaryTypedef dictionaryTypedef;
Promise<void> promise;
sequence<Promise<void>> promiseSequence;
};
dictionary ParentDict : GrandparentDict {
@ -1161,3 +1165,7 @@ interface TestDeprecatedInterface {
static void alsoDeprecated();
};
[Constructor(Promise<void> promise)]
interface TestInterfaceWithPromiseConstructorArg {
};

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

@ -124,12 +124,11 @@ TestInterfaceJS.prototype = {
},
testPromiseWithThrowingChromeThenable: function() {
// We need to produce a thing that has a "then" property in the page
// compartment, since we plan to call the page-provided resolve function.
var thenable = new this._win.Object();
Cu.waiveXrays(thenable).then = function() {
noSuchMethodExistsYo3()
}
var thenable = {
then: function() {
noSuchMethodExistsYo3()
}
};
return new this._win.Promise(function(resolve) {
resolve(thenable)
});
@ -144,13 +143,12 @@ TestInterfaceJS.prototype = {
},
testPromiseWithDOMExceptionThrowingThenable: function() {
// We need to produce a thing that has a "then" property in the page
// compartment, since we plan to call the page-provided resolve function.
var thenable = new this._win.Object();
Cu.waiveXrays(thenable).then = () => {
throw new this._win.DOMException("We are a fourth DOMException",
"TypeMismatchError");
}
var thenable = {
then: () => {
throw new this._win.DOMException("We are a fourth DOMException",
"TypeMismatchError");
}
};
return new this._win.Promise(function(resolve) {
resolve(thenable)
});

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

@ -65,7 +65,7 @@ if (!('BrowserElementIsPreloaded' in this)) {
Services.scriptloader.loadSubScript("chrome://global/content/BrowserElementChildPreload.js");
} else {
if (Services.prefs.getIntPref("dom.w3c_touch_events.enabled") == 1) {
if (Services.prefs.getIntPref("dom.w3c_touch_events.enabled") != 0) {
if (docShell.asyncPanZoomEnabled === false) {
ContentPanningAPZDisabled.init();
}

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

@ -325,6 +325,11 @@ WebGL2Context::GetActiveUniforms(WebGLProgram* program,
if (IsContextLost())
return;
if (pname == LOCAL_GL_UNIFORM_NAME_LENGTH) {
ErrorInvalidEnumInfo("getActiveUniforms: pname", pname);
return;
}
if (!ValidateObject("getActiveUniforms: program", program))
return;

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

@ -11,7 +11,7 @@ EXTRA_COMPONENTS += [
'DownloadsAPI.manifest',
]
EXTRA_PP_COMPONENTS = [
EXTRA_PP_COMPONENTS += [
'DownloadsAPI.js',
]

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

@ -910,7 +910,9 @@ DataTransfer::GetFilesAndDirectories(ErrorResult& aRv)
nsDependentSubstring dirname = Substring(path, 0, leafSeparatorIndex);
nsDependentSubstring basename = Substring(path, leafSeparatorIndex);
fs = MakeOrReuseFileSystem(dirname, fs, window);
filesAndDirsSeq[i].SetAsDirectory() = new Directory(fs, basename);
RefPtr<Directory> directory = new Directory(fs, basename);
directory->SetContentFilters(NS_LITERAL_STRING("filter-out-sensitive"));
filesAndDirsSeq[i].SetAsDirectory() = directory;
} else {
filesAndDirsSeq[i].SetAsFile() = mFiles->Item(i);
}

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

@ -245,6 +245,8 @@ FetchDriver::HttpFetch()
MOZ_ASSERT(mLoadGroup);
nsCOMPtr<nsIChannel> chan;
nsLoadFlags loadFlags = nsIRequest::LOAD_NORMAL | credentialsFlag |
bypassFlag | nsIChannel::LOAD_CLASSIFY_URI;
if (mDocument) {
MOZ_ASSERT(mDocument->NodePrincipal() == mPrincipal);
rv = NS_NewChannel(getter_AddRefs(chan),
@ -255,7 +257,7 @@ FetchDriver::HttpFetch()
mRequest->ContentPolicyType(),
mLoadGroup,
nullptr, /* aCallbacks */
nsIRequest::LOAD_NORMAL | credentialsFlag | bypassFlag,
loadFlags,
ios);
} else {
rv = NS_NewChannel(getter_AddRefs(chan),
@ -266,7 +268,7 @@ FetchDriver::HttpFetch()
mRequest->ContentPolicyType(),
mLoadGroup,
nullptr, /* aCallbacks */
nsIRequest::LOAD_NORMAL | credentialsFlag | bypassFlag,
loadFlags,
ios);
}
NS_ENSURE_SUCCESS(rv, rv);

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

@ -230,8 +230,7 @@ Directory::GetPath(nsAString& aRetval) const
// The Directory ctor removes any trailing '/'; this is the root directory.
aRetval.AssignLiteral(FILESYSTEM_DOM_PATH_SEPARATOR);
} else {
aRetval = Substring(mPath, 0,
mPath.RFindChar(FileSystemUtils::kSeparatorChar) + 1);
aRetval = mPath;
}
}
@ -242,7 +241,7 @@ Directory::GetFilesAndDirectories()
nsString realPath;
ErrorResult rv;
RefPtr<GetDirectoryListingTask> task =
new GetDirectoryListingTask(mFileSystem, mPath, rv);
new GetDirectoryListingTask(mFileSystem, mPath, mFilters, rv);
if (NS_WARN_IF(rv.Failed())) {
return nullptr;
}
@ -251,6 +250,12 @@ Directory::GetFilesAndDirectories()
return task->GetPromise();
}
void
Directory::SetContentFilters(const nsAString& aFilters)
{
mFilters = aFilters;
}
FileSystemBase*
Directory::GetFileSystem() const
{

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

@ -87,6 +87,31 @@ public:
// =========== End WebIDL bindings.============
/**
* Sets a semi-colon separated list of filters to filter-in or filter-out
* certain types of files when the contents of this directory are requested
* via a GetFilesAndDirectories() call.
*
* Currently supported keywords:
*
* * filter-out-sensitive
* This keyword filters out files or directories that we don't wish to
* make available to Web content because we are concerned that there is
* a risk that users may unwittingly give Web content access to them
* and suffer undesirable consequences. The details of what is
* filtered out can be found in GetDirectoryListingTask::Work.
*
* In future, we will likely support filtering based on filename extensions
* (for example, aFilters could be "*.jpg; *.jpeg; *.gif"), but that isn't
* supported yet. Once supported, files that don't match a specified
* extension (if any are specified) would be filtered out. This
* functionality would allow us to apply the 'accept' attribute from
* <input type=file directory accept="..."> to the results of a directory
* picker operation.
*/
void
SetContentFilters(const nsAString& aFilters);
FileSystemBase*
GetFileSystem() const;
private:
@ -108,6 +133,7 @@ private:
RefPtr<FileSystemBase> mFileSystem;
nsString mPath;
nsString mFilters;
};
} // namespace dom

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

@ -6,6 +6,7 @@
#include "GetDirectoryListingTask.h"
#include "HTMLSplitOnSpacesTokenizer.h"
#include "js/Value.h"
#include "mozilla/dom/Directory.h"
#include "mozilla/dom/File.h"
@ -22,9 +23,11 @@ namespace dom {
GetDirectoryListingTask::GetDirectoryListingTask(FileSystemBase* aFileSystem,
const nsAString& aTargetPath,
const nsAString& aFilters,
ErrorResult& aRv)
: FileSystemTaskBase(aFileSystem)
, mTargetRealPath(aTargetPath)
, mFilters(aFilters)
{
MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
MOZ_ASSERT(aFileSystem);
@ -40,12 +43,13 @@ GetDirectoryListingTask::GetDirectoryListingTask(FileSystemBase* aFileSystem,
const FileSystemGetDirectoryListingParams& aParam,
FileSystemRequestParent* aParent)
: FileSystemTaskBase(aFileSystem, aParam, aParent)
, mTargetRealPath(aParam.realPath())
, mFilters(aParam.filters())
{
MOZ_ASSERT(XRE_IsParentProcess(),
"Only call from parent process!");
MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
MOZ_ASSERT(aFileSystem);
mTargetRealPath = aParam.realPath();
}
GetDirectoryListingTask::~GetDirectoryListingTask()
@ -65,7 +69,8 @@ FileSystemParams
GetDirectoryListingTask::GetRequestParams(const nsString& aFileSystem) const
{
MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
return FileSystemGetDirectoryListingParams(aFileSystem, mTargetRealPath);
return FileSystemGetDirectoryListingParams(aFileSystem, mTargetRealPath,
mFilters);
}
FileSystemResponseValue
@ -155,6 +160,20 @@ GetDirectoryListingTask::Work()
return rv;
}
bool filterOutSensitive = false;
{
HTMLSplitOnSpacesTokenizer tokenizer(mFilters, ';');
nsAutoString token;
while (tokenizer.hasMoreTokens()) {
token = tokenizer.nextToken();
if (token.EqualsLiteral("filter-out-sensitive")) {
filterOutSensitive = true;
} else {
MOZ_CRASH("Unrecognized filter");
}
}
}
for (;;) {
bool hasMore = false;
if (NS_WARN_IF(NS_FAILED(entries->HasMoreElements(&hasMore))) || !hasMore) {
@ -179,6 +198,21 @@ GetDirectoryListingTask::Work()
!(isFile || isDir)) {
continue;
}
if (filterOutSensitive) {
bool isHidden;
if (NS_WARN_IF(NS_FAILED(currFile->IsHidden(&isHidden))) || isHidden) {
continue;
}
nsAutoString leafName;
if (NS_WARN_IF(NS_FAILED(currFile->GetLeafName(leafName)))) {
continue;
}
if (leafName[0] == char16_t('.')) {
continue;
}
}
BlobImplFile* impl = new BlobImplFile(currFile);
impl->LookupAndCacheIsDirectory();
mTargetBlobImpls.AppendElement(impl);
@ -226,7 +260,10 @@ GetDirectoryListingTask::HandlerCallback()
MOZ_ASSERT(exist);
}
#endif
listing[i].SetAsDirectory() = new Directory(mFileSystem, path);
RefPtr<Directory> directory = new Directory(mFileSystem, path);
// Propogate mFilter onto sub-Directory object:
directory->SetContentFilters(mFilters);
listing[i].SetAsDirectory() = directory;
} else {
listing[i].SetAsFile() = File::Create(mFileSystem->GetWindow(), mTargetBlobImpls[i]);
}

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