Merge mozilla-central to fx-team

This commit is contained in:
Carsten "Tomcat" Book 2016-09-29 11:49:24 +02:00
commit dc6ea2267a
473 changed files with 6554 additions and 4300 deletions

View File

@ -82,6 +82,7 @@ tasks:
features:
taskclusterProxy: true
chainOfTrust: true
# Note: This task is built server side without the context or tooling that
# exist in tree so we must hard code the version

View File

@ -172,7 +172,7 @@ faster: install-dist/idl
endif
.PHONY: tup
tup: install-manifests buildid.h
tup: install-manifests buildid.h source-repo.h
@$(TUP) $(if $(findstring s,$(filter-out --%,$(MAKEFLAGS))),,--verbose)
# process_install_manifest needs to be invoked with --no-remove when building

View File

@ -14,10 +14,8 @@ using namespace mozilla::a11y;
////////////////////////////////////////////////////////////////////////////////
IMPL_IUNKNOWN_QUERY_HEAD(ChildrenEnumVariant)
IMPL_IUNKNOWN_QUERY_IFACE(IEnumVARIANT);
IMPL_IUNKNOWN_QUERY_IFACE(IUnknown);
IMPL_IUNKNOWN_QUERY_AGGR_COND(mAnchorAcc, !mAnchorAcc->IsDefunct());
IMPL_IUNKNOWN_QUERY_TAIL
IMPL_IUNKNOWN_QUERY_IFACE(IEnumVARIANT)
IMPL_IUNKNOWN_QUERY_TAIL_AGGREGATED(mAnchorAcc)
STDMETHODIMP
ChildrenEnumVariant::Next(ULONG aCount, VARIANT FAR* aItems,

View File

@ -899,10 +899,8 @@ bin/libfreebl_32int64_3.so
#endif
; media
#ifdef MOZ_EME
@RESPATH@/gmp-clearkey/0.1/@DLL_PREFIX@clearkey@DLL_SUFFIX@
@RESPATH@/gmp-clearkey/0.1/clearkey.info
#endif
#ifdef PKG_LOCALE_MANIFEST
#include @PKG_LOCALE_MANIFEST@

View File

@ -972,16 +972,24 @@ pref("security.sandbox.windows.log.stackTraceDepth", 0);
#endif
#if defined(XP_MACOSX) && defined(MOZ_SANDBOX) && defined(MOZ_CONTENT_SANDBOX)
// This pref is discussed in bug 1083344, the naming is inspired from its Windows
// counterpart, but on Mac it's an integer which means:
// This pref is discussed in bug 1083344, the naming is inspired from its
// Windows counterpart, but on Mac it's an integer which means:
// 0 -> "no sandbox"
// 1 -> "an imperfect sandbox designed to allow firefox to run reasonably well"
// 2 -> "an ideal sandbox which may break many things"
// 1 -> "preliminary content sandboxing enabled: write access to
// home directory is prevented"
// 2 -> "preliminary content sandboxing enabled with profile protection:
// write access to home directory is prevented, read and write access
// to ~/Library and profile directories are prevented (excluding
// $PROFILE/{extensions,weave})"
// This setting is read when the content process is started. On Mac the content
// process is killed when all windows are closed, so a change will take effect
// when the 1st window is opened.
#if defined(NIGHTLY_BUILD)
pref("security.sandbox.content.level", 2);
#else
pref("security.sandbox.content.level", 1);
#endif
#endif
#if defined(XP_LINUX) && defined(MOZ_SANDBOX) && defined(MOZ_CONTENT_SANDBOX)
// This pref is introduced as part of bug 742434, the naming is inspired from

View File

@ -48,15 +48,22 @@
yield PlacesTestUtils.clearHistory();
// Add some visits.
let timeInMicroseconds = PlacesUtils.toPRTime(Date.now() - 10000);
function newTimeInMicroseconds() {
timeInMicroseconds = timeInMicroseconds + 1000;
return timeInMicroseconds;
}
let vtime = Date.now() * 1000;
const ttype = PlacesUtils.history.TRANSITION_TYPED;
let places =
[{ uri: Services.io.newURI("http://example.tld/", null, null),
visitDate: ++vtime, transition: ttype },
visitDate: newTimeInMicroseconds(), transition: ttype },
{ uri: Services.io.newURI("http://example2.tld/", null, null),
visitDate: ++vtime, transition: ttype },
visitDate: newTimeInMicroseconds(), transition: ttype },
{ uri: Services.io.newURI("http://example3.tld/", null, null),
visitDate: ++vtime, transition: ttype }];
visitDate: newTimeInMicroseconds(), transition: ttype }];
yield PlacesTestUtils.addVisits(places);
@ -85,7 +92,7 @@
is(rc, 3, "Found expected number of rows.");
// First check live-update of the view when adding visits.
places.forEach(place => place.visitDate = ++vtime);
places.forEach(place => place.visitDate = newTimeInMicroseconds());
yield PlacesTestUtils.addVisits(places);
for (let i = 0; i < rc; i++) {

View File

@ -5,8 +5,6 @@
<?xml-stylesheet href="chrome://global/skin/global.css"?>
<?xml-stylesheet href="chrome://mozapps/content/preferences/preferences.css"?>
<?xml-stylesheet href="chrome://browser/skin/preferences/preferences.css"?>
<?xml-stylesheet href="chrome://global/skin/in-content/common.css"?>
<?xml-stylesheet

View File

@ -11,11 +11,12 @@ var gSubDialog = {
_frame: null,
_overlay: null,
_box: null,
_injectedStyleSheets: ["chrome://mozapps/content/preferences/preferences.css",
"chrome://browser/skin/preferences/preferences.css",
"chrome://global/skin/in-content/common.css",
"chrome://browser/skin/preferences/in-content/preferences.css",
"chrome://browser/skin/preferences/in-content/dialog.css"],
_injectedStyleSheets: [
"chrome://browser/skin/preferences/preferences.css",
"chrome://global/skin/in-content/common.css",
"chrome://browser/skin/preferences/in-content/preferences.css",
"chrome://browser/skin/preferences/in-content/dialog.css",
],
_resizeObserver: null,
init: function() {

View File

@ -150,7 +150,6 @@ var Agent = {
let stateString = JSON.stringify(state);
let data = Encoder.encode(stateString);
let startWriteMs, stopWriteMs;
try {
@ -167,7 +166,7 @@ var Agent = {
File.move(this.Paths.clean, this.Paths.cleanBackup);
}
startWriteMs = Date.now();
let startWriteMs = Date.now();
if (options.isFinalWrite) {
// We are shutting down. At this stage, we know that
@ -198,7 +197,8 @@ var Agent = {
});
}
stopWriteMs = Date.now();
telemetry.FX_SESSION_RESTORE_WRITE_FILE_MS = Date.now() - startWriteMs;
telemetry.FX_SESSION_RESTORE_FILE_SIZE_BYTES = data.byteLength;
} catch (ex) {
// Don't throw immediately
@ -276,10 +276,7 @@ var Agent = {
result: {
upgradeBackup: upgradeBackupComplete
},
telemetry: {
FX_SESSION_RESTORE_WRITE_FILE_MS: stopWriteMs - startWriteMs,
FX_SESSION_RESTORE_FILE_SIZE_BYTES: data.byteLength,
}
telemetry: telemetry,
};
},

View File

@ -830,10 +830,8 @@ bin/libfreebl_32int64_3.so
; media
#ifdef MOZ_EME
@RESPATH@/gmp-clearkey/0.1/@DLL_PREFIX@clearkey@DLL_SUFFIX@
@RESPATH@/gmp-clearkey/0.1/clearkey.info
#endif
; gfx
#ifdef XP_WIN

View File

@ -346,238 +346,6 @@ menuitem.bookmark-item {
opacity: 0.7;
}
/* Stock icons for the menu bar items */
menuitem:not([type]):not(.menuitem-tooltip):not(.menuitem-iconic-tooltip) {
-moz-binding: url("chrome://global/content/bindings/menu.xml#menuitem-iconic");
}
#placesContext_open\:newwindow,
#menu_newNavigator,
#context-openlink,
#context-openframe {
list-style-image: url("chrome://browser/skin/Toolbar-small.png");
-moz-image-region: rect(0px 80px 16px 64px);
}
#placesContext_open\:newtab,
#placesContext_openContainer\:tabs,
#menu_newNavigatorTab,
#context-openlinkintab,
#context-openlinkincontainertab,
#context-openframeintab {
list-style-image: url("chrome://browser/skin/Toolbar-small.png");
-moz-image-region: rect(0px 64px 16px 48px);
}
#menu_openFile {
list-style-image: url("moz-icon://stock/gtk-open?size=menu");
}
#menu_close {
list-style-image: url("moz-icon://stock/gtk-close?size=menu");
}
#context-media-play {
list-style-image: url("moz-icon://stock/gtk-media-play?size=menu");
}
#context-media-pause {
list-style-image: url("moz-icon://stock/gtk-media-pause?size=menu");
}
#menu_savePage,
#context-savelink,
#context-saveimage,
#context-savevideo,
#context-saveaudio,
#context-savepage,
#context-saveframe {
list-style-image: url("moz-icon://stock/gtk-save-as?size=menu");
}
#menu_printPreview {
list-style-image: url("moz-icon://stock/gtk-print-preview?size=menu");
}
#menu_print,
#context-printframe {
list-style-image: url("moz-icon://stock/gtk-print?size=menu");
}
#menu_FileQuitItem {
list-style-image: url("moz-icon://stock/gtk-quit?size=menu");
}
#menu_undo,
#context-undo {
list-style-image: url("moz-icon://stock/gtk-undo?size=menu");
}
#menu_undo[disabled],
#context-undo[disabled] {
list-style-image: url("moz-icon://stock/gtk-undo?size=menu&state=disabled");
}
#menu_redo {
list-style-image: url("moz-icon://stock/gtk-redo?size=menu");
}
#menu_redo[disabled] {
list-style-image: url("moz-icon://stock/gtk-redo?size=menu&state=disabled");
}
#menu_cut,
#placesContext_cut,
#context-cut {
list-style-image: url("moz-icon://stock/gtk-cut?size=menu");
}
#menu_cut[disabled],
#placesContext_cut[disabled],
#context-cut[disabled] {
list-style-image: url("moz-icon://stock/gtk-cut?size=menu&state=disabled");
}
#menu_copy,
#placesContext_copy,
#context-copy,
#context-copyimage,
#context-copyvideourl,
#context-copyaudiourl,
#context-copylink,
#context-copyemail {
list-style-image: url("moz-icon://stock/gtk-copy?size=menu");
}
#menu_copy[disabled],
#placesContext_copy[disabled],
#context-copy[disabled] {
list-style-image: url("moz-icon://stock/gtk-copy?size=menu&state=disabled");
}
#menu_paste,
#placesContext_paste,
#context-paste {
list-style-image: url("moz-icon://stock/gtk-paste?size=menu");
}
#menu_paste[disabled],
#placesContext_paste[disabled],
#context-paste[disabled] {
list-style-image: url("moz-icon://stock/gtk-paste?size=menu&state=disabled");
}
#menu_delete,
#placesContext_delete,
#placesContext_delete_history,
#context-delete {
list-style-image: url("moz-icon://stock/gtk-delete?size=menu");
}
#menu_delete[disabled],
#placesContext_delete[disabled],
#placesContext_delete_history[disabled],
#context-delete[disabled] {
list-style-image: url("moz-icon://stock/gtk-delete?size=menu&state=disabled");
}
#menu_selectAll,
#context-selectall {
list-style-image: url("moz-icon://stock/gtk-select-all?size=menu");
}
#menu_find {
list-style-image: url("moz-icon://stock/gtk-find?size=menu");
}
#menu_find[disabled] {
list-style-image: url("moz-icon://stock/gtk-find?size=menu&state=disabled");
}
#menu_preferences {
list-style-image: url("moz-icon://stock/gtk-preferences?size=menu");
}
#placesContext_reload,
#context-reloadframe {
list-style-image: url("moz-icon://stock/gtk-refresh?size=menu");
}
#menu_zoomEnlarge {
list-style-image: url("moz-icon://stock/gtk-zoom-in?size=menu");
}
#menu_zoomReduce {
list-style-image: url("moz-icon://stock/gtk-zoom-out?size=menu");
}
#menu_zoomReset {
list-style-image: url("moz-icon://stock/gtk-zoom-100?size=menu");
}
#menu_showAllHistory {
list-style-image: url("chrome://browser/skin/Toolbar-small.png");
-moz-image-region: rect(0px 32px 16px 16px);
}
#bookmarksShowAll {
list-style-image: url("chrome://browser/skin/Toolbar-small.png");
-moz-image-region: rect(0px 48px 16px 32px);
}
#subscribeToPageMenuitem:not([disabled]),
#subscribeToPageMenupopup {
list-style-image: url("chrome://browser/skin/page-livemarks.png");
}
#bookmarksToolbarFolderMenu,
#BMB_bookmarksToolbar,
#panelMenu_bookmarksToolbar {
list-style-image: url("chrome://browser/skin/places/bookmarksToolbar.png");
}
#menu_unsortedBookmarks,
#BMB_unsortedBookmarks,
#panelMenu_unsortedBookmarks {
list-style-image: url("chrome://browser/skin/places/unsortedBookmarks.png");
}
#menu_openDownloads {
list-style-image: url("chrome://browser/skin/Toolbar-small.png");
-moz-image-region: rect(0px 16px 16px 0px);
}
#menu_openAddons {
list-style-image: url("chrome://mozapps/skin/extensions/extensionGeneric-16.png");
}
#menu_pageInfo,
#context-viewinfo,
#context-viewframeinfo {
list-style-image: url("moz-icon://stock/gtk-info?size=menu");
}
#placesContext_open\:newprivatewindow,
#privateBrowsingItem {
list-style-image: url("chrome://browser/skin/Privacy-16.png");
}
#placesContext_show\:info {
list-style-image: url("moz-icon://stock/gtk-properties?size=menu");
}
#sanitizeItem {
list-style-image: url("moz-icon://stock/gtk-clear?size=menu");
}
#menu_openHelp {
list-style-image: url("moz-icon://stock/gtk-help?size=menu");
}
#aboutName {
list-style-image: url("moz-icon://stock/gtk-about?size=menu");
}
/* Primary toolbar buttons */
:-moz-any(toolbar, .widget-overflow-list) .toolbarbutton-1 > .toolbarbutton-icon,
@ -1866,7 +1634,6 @@ notification.pluginVulnerable > .notification-inner > .messageCloseButton:not(:h
%include ../shared/contextmenu.inc.css
#context-navigation > .menuitem-iconic > .menu-iconic-left {
visibility: visible;
/* override toolkit/themes/linux/global/menu.css */
padding-inline-end: 0 !important;
margin-inline-end: 0 !important;
@ -1880,7 +1647,3 @@ notification.pluginVulnerable > .notification-inner > .messageCloseButton:not(:h
.webextension-popup-browser {
border-radius: inherit;
}
.menuitem-iconic[usercontextid] > .menu-iconic-left > .menu-iconic-icon {
visibility: visible;
}

View File

@ -265,16 +265,3 @@ treechildren::-moz-tree-cell-text(broken) {
#securityPanel row {
-moz-box-align: center;
}
/* Icons for context menus */
menuitem:not([type]) {
-moz-binding: url("chrome://global/content/bindings/menu.xml#menuitem-iconic");
}
#menu_selectall {
list-style-image: url("moz-icon://stock/gtk-select-all?size=menu");
}
#menu_copy {
list-style-image: url("moz-icon://stock/gtk-copy?size=menu");
}

View File

@ -90,19 +90,6 @@
padding-inline-start: 2px;
}
/**** menuitem stock icons ****/
#orgClose {
list-style-image: url("moz-icon://stock/gtk-close?size=menu");
}
#fileImport {
list-style-image: url("moz-icon://stock/gtk-revert-to-saved?size=menu");
}
#fileExport {
list-style-image: url("moz-icon://stock/gtk-save-as?size=menu");
}
/**
* Downloads pane
*/

View File

@ -120,102 +120,3 @@ treechildren::-moz-tree-image(cutting) {
treechildren::-moz-tree-cell-text(cutting) {
opacity: 0.7;
}
/**** menuitem stock icons ****/
menuitem:not([type]) {
-moz-binding: url("chrome://global/content/bindings/menu.xml#menuitem-iconic");
}
menuitem[command="cmd_cut"],
menuitem[cmd="cmd_cut"] {
list-style-image: url("moz-icon://stock/gtk-cut?size=menu");
}
menuitem[command="cmd_cut"][disabled],
menuitem[cmd="cmd_cut"][disabled] {
list-style-image: url("moz-icon://stock/gtk-cut?size=menu&state=disabled");
}
menuitem[command="cmd_copy"],
menuitem[cmd="cmd_copy"] {
list-style-image: url("moz-icon://stock/gtk-copy?size=menu");
}
menuitem[command="cmd_copy"][disabled],
menuitem[cmd="cmd_copy"][disabled] {
list-style-image: url("moz-icon://stock/gtk-copy?size=menu&state=disabled");
}
menuitem[command="cmd_paste"],
menuitem[cmd="cmd_paste"] {
list-style-image: url("moz-icon://stock/gtk-paste?size=menu");
}
menuitem[command="cmd_paste"][disabled],
menuitem[cmd="cmd_paste"][disabled] {
list-style-image: url("moz-icon://stock/gtk-paste?size=menu&state=disabled");
}
menuitem[command="cmd_delete"],
menuitem[cmd="cmd_delete"] {
list-style-image: url("moz-icon://stock/gtk-delete?size=menu");
}
menuitem[command="cmd_delete"][disabled],
menuitem[cmd="cmd_delete"][disabled] {
list-style-image: url("moz-icon://stock/gtk-delete?size=menu&state=disabled");
}
menuitem[command="cmd_undo"],
menuitem[cmd="cmd_undo"] {
list-style-image: url("moz-icon://stock/gtk-undo?size=menu");
}
menuitem[command="cmd_undo"][disabled],
menuitem[cmd="cmd_undo"][disabled] {
list-style-image: url("moz-icon://stock/gtk-undo?size=menu&state=disabled");
}
menuitem[command="cmd_redo"] {
list-style-image: url("moz-icon://stock/gtk-redo?size=menu");
}
menuitem[command="cmd_redo"][disabled] {
list-style-image: url("moz-icon://stock/gtk-redo?size=menu&state=disabled");
}
menuitem[command="cmd_selectAll"],
menuitem[cmd="cmd_selectAll"] {
list-style-image: url("moz-icon://stock/gtk-select-all?size=menu");
}
menuitem[command="cmd_selectAll"][disabled],
menuitem[cmd="cmd_selectAll"][disabled] {
list-style-image: url("moz-icon://stock/gtk-select-all?size=menu&state=disabled");
}
#placesContext_open\:newwindow,
menuitem[command="placesCmd_open:window"] {
list-style-image: url("chrome://browser/skin/Toolbar-small.png");
-moz-image-region: rect(0px 80px 16px 64px);
}
#placesContext_open\:newprivatewindow,
menuitem[command="placesCmd_open:privatewindow"] {
list-style-image: url("chrome://browser/skin/Privacy-16.png");
}
#placesContext_open\:newtab,
menuitem[command="placesCmd_open:tab"] {
list-style-image: url("chrome://browser/skin/Toolbar-small.png");
-moz-image-region: rect(0px 64px 16px 48px);
}
#placesContext_show\:info,
menuitem[command="placesCmd_show:info"] {
list-style-image: url("moz-icon://stock/gtk-properties?size=menu");
}
#placesContext_reload {
list-style-image: url("moz-icon://stock/gtk-refresh?size=menu");
}

View File

@ -7,7 +7,7 @@
@depends(target)
def force_system_ffi(target):
# Pre-emptively move to system ffi for non-tier one platforms.
if target.cpu not in ('x86', 'x86_64', 'arm'):
if target.cpu not in ('x86', 'x86_64', 'arm', 'aarch64'):
return True
imply_option('--with-system-ffi', force_system_ffi, "target")
@ -28,7 +28,7 @@ add_old_configure_assignment('MOZ_SYSTEM_FFI', system_ffi)
# Target selection, based on ffi/configure.ac.
@depends_when(target, when=building_ffi)
def ffi_target(target):
if target.cpu not in ('x86', 'x86_64', 'arm'):
if target.cpu not in ('x86', 'x86_64', 'arm', 'aarch64'):
die('Building libffi from the tree is not supported on this platform. '
'Use --with-system-ffi instead.')
@ -44,6 +44,9 @@ def ffi_target(target):
elif target.cpu == 'arm':
target_dir = 'arm'
target_name = 'ARM'
elif target.cpu == 'aarch64':
target_dir = 'aarch64'
target_name = 'AARCH64'
else:
target_dir = 'x86'
target_name = target.cpu.upper()

View File

@ -65,6 +65,13 @@ PrincipalOriginAttributes::InheritFromNecko(const NeckoOriginAttributes& aAttrs)
mFirstPartyDomain = aAttrs.mFirstPartyDomain;
}
void
PrincipalOriginAttributes::StripUserContextIdAndFirstPartyDomain()
{
mUserContextId = nsIScriptSecurityManager::DEFAULT_USER_CONTEXT_ID;
mFirstPartyDomain.Truncate();
}
void
DocShellOriginAttributes::InheritFromDocToChildDocShell(const PrincipalOriginAttributes& aAttrs)
{
@ -717,6 +724,23 @@ BasePrincipal::CreateCodebasePrincipal(const nsACString& aOrigin)
return BasePrincipal::CreateCodebasePrincipal(uri, attrs);
}
already_AddRefed<BasePrincipal>
BasePrincipal::CloneStrippingUserContextIdAndFirstPartyDomain()
{
PrincipalOriginAttributes attrs = OriginAttributesRef();
attrs.StripUserContextIdAndFirstPartyDomain();
nsAutoCString originNoSuffix;
nsresult rv = GetOriginNoSuffix(originNoSuffix);
NS_ENSURE_SUCCESS(rv, nullptr);
nsCOMPtr<nsIURI> uri;
rv = NS_NewURI(getter_AddRefs(uri), originNoSuffix);
NS_ENSURE_SUCCESS(rv, nullptr);
return BasePrincipal::CreateCodebasePrincipal(uri, attrs);
}
bool
BasePrincipal::AddonAllowsLoad(nsIURI* aURI)
{

View File

@ -104,6 +104,8 @@ public:
// Inherit OriginAttributes from Necko.
void InheritFromNecko(const NeckoOriginAttributes& aAttrs);
void StripUserContextIdAndFirstPartyDomain();
};
// For OriginAttributes stored on docshells / loadcontexts / browsing contexts.
@ -314,6 +316,8 @@ public:
virtual PrincipalKind Kind() = 0;
already_AddRefed<BasePrincipal> CloneStrippingUserContextIdAndFirstPartyDomain();
protected:
virtual ~BasePrincipal();

View File

@ -147,14 +147,15 @@ GetPrincipalDomainOrigin(nsIPrincipal* aPrincipal,
return GetOriginFromURI(uri, aOrigin);
}
inline void SetPendingException(JSContext *cx, const char *aMsg)
inline void SetPendingExceptionASCII(JSContext *cx, const char *aMsg)
{
JS_ReportError(cx, "%s", aMsg);
JS_ReportErrorASCII(cx, "%s", aMsg);
}
inline void SetPendingException(JSContext *cx, const char16_t *aMsg)
{
JS_ReportError(cx, "%hs", aMsg);
// FIXME: Need to convert to UTF-8 (bug XXX).
JS_ReportErrorLatin1(cx, "%hs", aMsg);
}
// Helper class to get stuff from the ClassInfo and not waste extra time with
@ -596,7 +597,7 @@ nsScriptSecurityManager::CheckLoadURIFromScript(JSContext *cx, nsIURI *aURI)
nsAutoCString msg("Access to '");
msg.Append(spec);
msg.AppendLiteral("' from script denied");
SetPendingException(cx, msg.get());
SetPendingExceptionASCII(cx, msg.get());
return NS_ERROR_DOM_BAD_URI;
}
@ -1305,7 +1306,7 @@ nsScriptSecurityManager::CanCreateInstance(JSContext *cx,
char cidStr[NSID_LENGTH];
aCID.ToProvidedString(cidStr);
errorMsg.Append(cidStr);
SetPendingException(cx, errorMsg.get());
SetPendingExceptionASCII(cx, errorMsg.get());
return NS_ERROR_DOM_XPCONNECT_ACCESS_DENIED;
}
@ -1322,7 +1323,7 @@ nsScriptSecurityManager::CanGetService(JSContext *cx,
char cidStr[NSID_LENGTH];
aCID.ToProvidedString(cidStr);
errorMsg.Append(cidStr);
SetPendingException(cx, errorMsg.get());
SetPendingExceptionASCII(cx, errorMsg.get());
return NS_ERROR_DOM_XPCONNECT_ACCESS_DENIED;
}

View File

@ -4,10 +4,11 @@
# 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/.
FINAL_LIBRARY = 'js'
if CONFIG['MOZ_SYSTEM_FFI']:
OS_LIBS += CONFIG['MOZ_FFI_LIBS']
else:
FINAL_LIBRARY = 'js'
ALLOW_COMPILER_WARNINGS = True
NO_VISIBILITY_FLAGS = True
@ -77,6 +78,8 @@ else:
ffi_srcs = ('sysv.S', 'ffi.c')
if CONFIG['CLANG_CXX']:
ASFLAGS += ['-no-integrated-as']
elif CONFIG['FFI_TARGET'] == 'AARCH64':
ffi_srcs = ('sysv.S', 'ffi.c')
elif CONFIG['FFI_TARGET'] == 'X86':
ffi_srcs = ('ffi.c', 'sysv.S', 'win32.S')
elif CONFIG['FFI_TARGET'] == 'X86_64':

View File

@ -1,5 +0,0 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
LIB_IS_C_ONLY = 1

View File

@ -6,6 +6,12 @@
const TEST_URI = "data:text/html;charset=utf-8,gcli-commands";
const HUDService = require("devtools/client/webconsole/hudservice");
// Use the old webconsole since pprint isn't working on new one (Bug 1304794)
Services.prefs.setBoolPref("devtools.webconsole.new-frontend-enabled", false);
registerCleanupFunction(function* () {
Services.prefs.clearUserPref("devtools.webconsole.new-frontend-enabled");
});
function test() {
return Task.spawn(spawnTest).then(finish, helpers.handleError);
}

View File

@ -7,6 +7,8 @@
const PAGE_URL = "data:text/html;charset=utf-8,test select events";
requestLongerTimeout(2);
add_task(function* () {
let tab = yield addTab(PAGE_URL);

View File

@ -138,7 +138,7 @@ function CssComputedView(inspector, document, pageStyle) {
this.propertyViews = [];
let cssProperties = getCssProperties(inspector.toolbox);
this._outputParser = new OutputParser(document, cssProperties.supportsType);
this._outputParser = new OutputParser(document, cssProperties);
// Create bound methods.
this.focusWindow = this.focusWindow.bind(this);

View File

@ -52,6 +52,7 @@ function TextProperty(rule, name, value, priority, enabled = true,
this.priority = priority;
this.enabled = !!enabled;
this.invisible = invisible;
this.panelDoc = this.rule.elementStyle.ruleView.inspector.panelDoc;
const toolbox = this.rule.elementStyle.ruleView.inspector.toolbox;
this.cssProperties = getCssProperties(toolbox);
@ -204,7 +205,7 @@ TextProperty.prototype = {
// compute validity locally (which might not be correct, but better than
// nothing).
if (!this.rule.domRule.declarations) {
return domUtils.cssPropertyIsValid(this.name, this.value);
return this.cssProperties.isValidOnClient(this.name, this.value, this.panelDoc);
}
let selfIndex = this.rule.textProps.indexOf(this);

View File

@ -105,7 +105,7 @@ function CssRuleView(inspector, document, store, pageStyle) {
this.cssProperties = getCssProperties(inspector.toolbox);
this._outputParser = new OutputParser(document, this.cssProperties.supportsType);
this._outputParser = new OutputParser(document, this.cssProperties);
this._onAddRule = this._onAddRule.bind(this);
this._onContextMenu = this._onContextMenu.bind(this);

View File

@ -31,6 +31,7 @@ const EventEmitter = require("devtools/shared/event-emitter");
const promise = require("promise");
const {Task} = require("devtools/shared/task");
const Services = require("Services");
const {getCssProperties} = require("devtools/shared/fronts/css-properties");
const PREF_IMAGE_TOOLTIP_SIZE = "devtools.inspector.imagePreviewTooltipSize";
@ -262,6 +263,7 @@ function TooltipsOverlay(view) {
let {CssRuleView} = require("devtools/client/inspector/rules/rules");
this.isRuleView = view instanceof CssRuleView;
this._cssProperties = getCssProperties(this.view.inspector.toolbox);
this._onNewSelection = this._onNewSelection.bind(this);
this.view.inspector.selection.on("new-node-front", this._onNewSelection);
@ -305,7 +307,8 @@ TooltipsOverlay.prototype = {
// Cubic bezier tooltip
this.cubicBezier = new SwatchCubicBezierTooltip(toolbox);
// Filter editor tooltip
this.filterEditor = new SwatchFilterTooltip(toolbox);
this.filterEditor = new SwatchFilterTooltip(toolbox,
this._cssProperties.getValidityChecker(this.view.inspector.panelDoc));
}
this._isStarted = true;

View File

@ -302,7 +302,7 @@ add_task(function* () {
yield initCssProperties(toolbox);
let cssProperties = getCssProperties(toolbox);
let parser = new OutputParser(document, cssProperties.supportsType);
let parser = new OutputParser(document, cssProperties);
for (let i = 0; i < TEST_DATA.length; i++) {
let data = TEST_DATA[i];
info("Output-parser test data " + i + ". {" + data.name + " : " +

View File

@ -11,6 +11,13 @@ registerCleanupFunction(() => {
Services.prefs.clearUserPref("devtools.toolbox.splitconsoleEnabled");
});
// Use the old webconsole since the node isn't being rendered as an HTML tag
// in the new one (Bug 1304794)
Services.prefs.setBoolPref("devtools.webconsole.new-frontend-enabled", false);
registerCleanupFunction(function* () {
Services.prefs.clearUserPref("devtools.webconsole.new-frontend-enabled");
});
add_task(function* () {
let { inspector, toolbox } = yield openInspectorForURL(TEST_URL);

View File

@ -3,6 +3,11 @@
http://creativecommons.org/publicdomain/zero/1.0/ */
/* Bug 661762 */
// Use the old webconsole since scratchpad focus isn't working on new one (Bug 1304794)
Services.prefs.setBoolPref("devtools.webconsole.new-frontend-enabled", false);
registerCleanupFunction(function* () {
Services.prefs.clearUserPref("devtools.webconsole.new-frontend-enabled");
});
function test()
{

View File

@ -4,7 +4,6 @@
"use strict";
const {Cc, Ci} = require("chrome");
const {angleUtils} = require("devtools/client/shared/css-angle");
const {colorUtils} = require("devtools/shared/css/color");
const {getCSSLexer} = require("devtools/shared/css/lexer");
@ -18,10 +17,6 @@ const {
const HTML_NS = "http://www.w3.org/1999/xhtml";
loader.lazyGetter(this, "DOMUtils", function () {
return Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils);
});
/**
* This module is used to process text for output by developer tools. This means
* linking JS files with the debugger, CSS files with the style editor, JS
@ -37,15 +32,18 @@ loader.lazyGetter(this, "DOMUtils", function () {
* parser.parseCssProperty("color", "red"); // Returns document fragment.
*
* @param {Document} document Used to create DOM nodes.
* @param {Function} supportsTypes A function that returns a boolean when asked if a css
* property name supports a given css type.
* The function is executed like supportsType("color", CSS_TYPES.COLOR) where CSS_TYPES is
* defined in devtools/shared/css/properties-db.js
* @param {Function} supportsTypes - A function that returns a boolean when asked if a css
* property name supports a given css type.
* The function is executed like supportsType("color", CSS_TYPES.COLOR)
* where CSS_TYPES is defined in devtools/shared/css/properties-db.js
* @param {Function} isValidOnClient - A function that checks if a css property
* name/value combo is valid.
*/
function OutputParser(document, supportsType) {
function OutputParser(document, {supportsType, isValidOnClient}) {
this.parsed = [];
this.doc = document;
this.supportsType = supportsType;
this.isValidOnClient = isValidOnClient;
this.colorSwatches = new WeakMap();
this.angleSwatches = new WeakMap();
this._onColorSwatchMouseDown = this._onColorSwatchMouseDown.bind(this);
@ -341,7 +339,7 @@ OutputParser.prototype = {
* CSS Property value to check
*/
_cssPropertySupportsValue: function (name, value) {
return DOMUtils.cssPropertyIsValid(name, value);
return this.isValidOnClient(name, value, this.doc);
},
/**

View File

@ -10,6 +10,7 @@ const DOMUtils =
Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils);
const TEST_URI = `data:text/html,<div id="filter-container" />`;
const {getClientCssProperties} = require("devtools/shared/fronts/css-properties");
// Verify that the given string consists of a valid CSS URL token.
// Return true on success, false on error.
@ -26,9 +27,10 @@ function verifyURL(string) {
add_task(function* () {
let [host, win, doc] = yield createHost("bottom", TEST_URI);
const cssIsValid = getClientCssProperties().getValidityChecker(doc);
const container = doc.querySelector("#filter-container");
let widget = new CSSFilterEditorWidget(container, "none");
let widget = new CSSFilterEditorWidget(container, "none", cssIsValid);
info("Test parsing of a valid CSS Filter value");
widget.setCssValue("blur(2px) contrast(200%)");

View File

@ -6,6 +6,7 @@
// Tests that the Filter Editor Widget renders filters correctly
const {CSSFilterEditorWidget} = require("devtools/client/shared/widgets/FilterWidget");
const {getClientCssProperties} = require("devtools/shared/fronts/css-properties");
const { LocalizationHelper } = require("devtools/shared/l10n");
const STRINGS_URI = "devtools/locale/filterwidget.properties";
@ -15,6 +16,7 @@ const TEST_URI = `data:text/html,<div id="filter-container" />`;
add_task(function* () {
let [host, win, doc] = yield createHost("bottom", TEST_URI);
const cssIsValid = getClientCssProperties().getValidityChecker(doc);
const TEST_DATA = [
{
@ -69,7 +71,7 @@ add_task(function* () {
];
const container = doc.querySelector("#filter-container");
let widget = new CSSFilterEditorWidget(container, "none");
let widget = new CSSFilterEditorWidget(container, "none", cssIsValid);
info("Test rendering of different types");

View File

@ -6,6 +6,7 @@
// Tests the Filter Editor Widget add, removeAt, updateAt, getValueAt methods
const {CSSFilterEditorWidget} = require("devtools/client/shared/widgets/FilterWidget");
const {getClientCssProperties} = require("devtools/shared/fronts/css-properties");
const GRAYSCALE_MAX = 100;
const INVERT_MIN = 0;
@ -13,9 +14,10 @@ const TEST_URI = `data:text/html,<div id="filter-container" />`;
add_task(function* () {
let [host, win, doc] = yield createHost("bottom", TEST_URI);
const cssIsValid = getClientCssProperties().getValidityChecker(doc);
const container = doc.querySelector("#filter-container");
let widget = new CSSFilterEditorWidget(container, "none");
let widget = new CSSFilterEditorWidget(container, "none", cssIsValid);
info("Test add method");
const blur = widget.add("blur", "10.2px");

View File

@ -6,16 +6,18 @@
// Tests the Filter Editor Widget's drag-drop re-ordering
const {CSSFilterEditorWidget} = require("devtools/client/shared/widgets/FilterWidget");
const {getClientCssProperties} = require("devtools/shared/fronts/css-properties");
const LIST_ITEM_HEIGHT = 32;
const TEST_URI = `data:text/html,<div id="filter-container" />`;
add_task(function* () {
let [host, win, doc] = yield createHost("bottom", TEST_URI);
const cssIsValid = getClientCssProperties().getValidityChecker(doc);
const container = doc.querySelector("#filter-container");
const initialValue = "blur(2px) contrast(200%) brightness(200%)";
let widget = new CSSFilterEditorWidget(container, initialValue);
let widget = new CSSFilterEditorWidget(container, initialValue, cssIsValid);
const filters = widget.el.querySelector("#filters");
function first() {

View File

@ -8,6 +8,7 @@ requestLongerTimeout(2);
// Tests the Filter Editor Widget's label-dragging
const {CSSFilterEditorWidget} = require("devtools/client/shared/widgets/FilterWidget");
const {getClientCssProperties} = require("devtools/shared/fronts/css-properties");
const FAST_VALUE_MULTIPLIER = 10;
const SLOW_VALUE_MULTIPLIER = 0.1;
@ -20,9 +21,10 @@ const TEST_URI = `data:text/html,<div id="filter-container" />`;
add_task(function* () {
let [host, win, doc] = yield createHost("bottom", TEST_URI);
const cssIsValid = getClientCssProperties().getValidityChecker(doc);
const container = doc.querySelector("#filter-container");
let widget = new CSSFilterEditorWidget(container, "grayscale(0%) url(test.svg)");
let widget = new CSSFilterEditorWidget(container, "grayscale(0%) url(test.svg)", cssIsValid);
const filters = widget.el.querySelector("#filters");
const grayscale = filters.children[0];

View File

@ -6,6 +6,7 @@
// Tests the Filter Editor Widget's add button
const {CSSFilterEditorWidget} = require("devtools/client/shared/widgets/FilterWidget");
const {getClientCssProperties} = require("devtools/shared/fronts/css-properties");
const { LocalizationHelper } = require("devtools/shared/l10n");
const STRINGS_URI = "devtools/locale/filterwidget.properties";
@ -15,9 +16,10 @@ const TEST_URI = `data:text/html,<div id="filter-container" />`;
add_task(function* () {
let [host, win, doc] = yield createHost("bottom", TEST_URI);
const cssIsValid = getClientCssProperties().getValidityChecker(doc);
const container = doc.querySelector("#filter-container");
let widget = new CSSFilterEditorWidget(container, "none");
let widget = new CSSFilterEditorWidget(container, "none", cssIsValid);
const select = widget.el.querySelector("select"),
add = widget.el.querySelector("#add-filter");

View File

@ -6,6 +6,7 @@
// Tests the Filter Editor Widget's remove button
const {CSSFilterEditorWidget} = require("devtools/client/shared/widgets/FilterWidget");
const {getClientCssProperties} = require("devtools/shared/fronts/css-properties");
const { LocalizationHelper } = require("devtools/shared/l10n");
const STRINGS_URI = "devtools/locale/filterwidget.properties";
@ -15,9 +16,10 @@ const TEST_URI = `data:text/html,<div id="filter-container" />`;
add_task(function* () {
let [host, win, doc] = yield createHost("bottom", TEST_URI);
const cssIsValid = getClientCssProperties().getValidityChecker(doc);
const container = doc.querySelector("#filter-container");
let widget = new CSSFilterEditorWidget(container, "blur(2px) contrast(200%)");
let widget = new CSSFilterEditorWidget(container, "blur(2px) contrast(200%)", cssIsValid);
info("Test removing filters with remove button");
widget.el.querySelector(".filter button").click();

View File

@ -7,6 +7,7 @@
// arrow keys, applying multiplier using alt/shift on number-type filters
const {CSSFilterEditorWidget} = require("devtools/client/shared/widgets/FilterWidget");
const {getClientCssProperties} = require("devtools/shared/fronts/css-properties");
const FAST_VALUE_MULTIPLIER = 10;
const SLOW_VALUE_MULTIPLIER = 0.1;
@ -16,10 +17,11 @@ const TEST_URI = `data:text/html,<div id="filter-container" />`;
add_task(function* () {
let [host, win, doc] = yield createHost("bottom", TEST_URI);
const cssIsValid = getClientCssProperties().getValidityChecker(doc);
const container = doc.querySelector("#filter-container");
const initialValue = "blur(2px)";
let widget = new CSSFilterEditorWidget(container, initialValue);
let widget = new CSSFilterEditorWidget(container, initialValue, cssIsValid);
let value = 2;

View File

@ -7,6 +7,7 @@
// on a number using arrow keys, applying multiplier using alt/shift on strings
const {CSSFilterEditorWidget} = require("devtools/client/shared/widgets/FilterWidget");
const {getClientCssProperties} = require("devtools/shared/fronts/css-properties");
const FAST_VALUE_MULTIPLIER = 10;
const SLOW_VALUE_MULTIPLIER = 0.1;
@ -16,10 +17,11 @@ const TEST_URI = `data:text/html,<div id="filter-container" />`;
add_task(function* () {
let [host, win, doc] = yield createHost("bottom", TEST_URI);
const cssIsValid = getClientCssProperties().getValidityChecker(doc);
const container = doc.querySelector("#filter-container");
const initialValue = "drop-shadow(rgb(0, 0, 0) 1px 1px 0px)";
let widget = new CSSFilterEditorWidget(container, initialValue);
let widget = new CSSFilterEditorWidget(container, initialValue, cssIsValid);
widget.el.querySelector("#filters input").setSelectionRange(13, 13);
let value = 1;

View File

@ -7,6 +7,7 @@
// on a number using arrow keys if cursor is behind/mid/after the number strings
const {CSSFilterEditorWidget} = require("devtools/client/shared/widgets/FilterWidget");
const {getClientCssProperties} = require("devtools/shared/fronts/css-properties");
const FAST_VALUE_MULTIPLIER = 10;
const SLOW_VALUE_MULTIPLIER = 0.1;
@ -16,10 +17,11 @@ const TEST_URI = `data:text/html,<div id="filter-container" />`;
add_task(function* () {
let [host, win, doc] = yield createHost("bottom", TEST_URI);
const cssIsValid = getClientCssProperties().getValidityChecker(doc);
const container = doc.querySelector("#filter-container");
const initialValue = "drop-shadow(rgb(0, 0, 0) 10px 1px 0px)";
let widget = new CSSFilterEditorWidget(container, initialValue);
let widget = new CSSFilterEditorWidget(container, initialValue, cssIsValid);
const input = widget.el.querySelector("#filters input");
let value = 10;

View File

@ -6,14 +6,16 @@
// Tests saving presets
const {CSSFilterEditorWidget} = require("devtools/client/shared/widgets/FilterWidget");
const {getClientCssProperties} = require("devtools/shared/fronts/css-properties");
const TEST_URI = `data:text/html,<div id="filter-container" />`;
add_task(function* () {
let [host, win, doc] = yield createHost("bottom", TEST_URI);
const cssIsValid = getClientCssProperties().getValidityChecker(doc);
const container = doc.querySelector("#filter-container");
let widget = new CSSFilterEditorWidget(container, "none");
let widget = new CSSFilterEditorWidget(container, "none", cssIsValid);
// First render
yield widget.once("render");

View File

@ -6,14 +6,16 @@
// Tests loading presets
const {CSSFilterEditorWidget} = require("devtools/client/shared/widgets/FilterWidget");
const {getClientCssProperties} = require("devtools/shared/fronts/css-properties");
const TEST_URI = `data:text/html,<div id="filter-container" />`;
add_task(function* () {
let [host, win, doc] = yield createHost("bottom", TEST_URI);
const cssIsValid = getClientCssProperties().getValidityChecker(doc);
const container = doc.querySelector("#filter-container");
let widget = new CSSFilterEditorWidget(container, "none");
let widget = new CSSFilterEditorWidget(container, "none", cssIsValid);
// First render
yield widget.once("render");

View File

@ -6,14 +6,16 @@
// Tests deleting presets
const {CSSFilterEditorWidget} = require("devtools/client/shared/widgets/FilterWidget");
const {getClientCssProperties} = require("devtools/shared/fronts/css-properties");
const TEST_URI = `data:text/html,<div id="filter-container" />`;
add_task(function* () {
let [host, win, doc] = yield createHost("bottom", TEST_URI);
const cssIsValid = getClientCssProperties().getValidityChecker(doc);
const container = doc.querySelector("#filter-container");
let widget = new CSSFilterEditorWidget(container, "none");
let widget = new CSSFilterEditorWidget(container, "none", cssIsValid);
// First render
yield widget.once("render");

View File

@ -21,7 +21,7 @@ function* performTest() {
yield initCssProperties(toolbox);
let cssProperties = getCssProperties(toolbox);
let parser = new OutputParser(doc, cssProperties.supportsType);
let parser = new OutputParser(doc, cssProperties);
testParseCssProperty(doc, parser);
testParseCssVar(doc, parser);
testParseURL(doc, parser);
@ -288,4 +288,3 @@ function testParseAngle(doc, parser) {
swatchCount = frag.querySelectorAll(".test-angleswatch").length;
is(swatchCount, 1, "angle swatch was created");
}

View File

@ -3,6 +3,14 @@
// Tests that the developer toolbar errors count works properly.
// Use the old webconsole since this is directly accessing old DOM, and
// the error count isn't reset when pressing the clear button in new one
// See Bug 1304794.
Services.prefs.setBoolPref("devtools.webconsole.new-frontend-enabled", false);
registerCleanupFunction(function* () {
Services.prefs.clearUserPref("devtools.webconsole.new-frontend-enabled");
});
function test() {
const TEST_URI = TEST_URI_ROOT + "browser_toolbar_webconsole_errors_count.html";

View File

@ -115,11 +115,14 @@ const SPECIAL_VALUES = new Set(["none", "unset", "initial", "inherit"]);
* The widget container.
* @param {String} value
* CSS filter value
* @param {Function} cssIsValid
* Test whether css name / value is valid.
*/
function CSSFilterEditorWidget(el, value = "") {
function CSSFilterEditorWidget(el, value = "", cssIsValid) {
this.doc = el.ownerDocument;
this.win = this.doc.defaultView;
this.el = el;
this._cssIsValid = cssIsValid;
this._addButtonClick = this._addButtonClick.bind(this);
this._removeButtonClick = this._removeButtonClick.bind(this);
@ -768,7 +771,7 @@ CSSFilterEditorWidget.prototype = {
// If the specified value is invalid, replace it with the
// default.
if (name !== "url") {
if (!DOMUtils.cssPropertyIsValid("filter", name + "(" + value + ")")) {
if (!this._cssIsValid("filter", name + "(" + value + ")")) {
value = null;
}
}

View File

@ -918,10 +918,14 @@ Heritage.extend(SwatchBasedEditorTooltip.prototype, {
*
* @param {Toolbox} toolbox
* The devtools toolbox, needed to get the devtools main window.
* @param {function} cssIsValid
* A function to check that css declaration's name and values are valid together.
* This can be obtained from "shared/fronts/css-properties.js".
*/
function SwatchFilterTooltip(toolbox) {
function SwatchFilterTooltip(toolbox, cssIsValid) {
let stylesheet = "chrome://devtools/content/shared/widgets/filter-widget.css";
SwatchBasedEditorTooltip.call(this, toolbox, stylesheet);
this._cssIsValid = cssIsValid;
// Creating a filter editor instance.
this.widget = this.setFilterContent("none");
@ -945,7 +949,7 @@ Heritage.extend(SwatchBasedEditorTooltip.prototype, {
this.tooltip.setContent(container, { width: 510, height: 200 });
return new CSSFilterEditorWidget(container, filter);
return new CSSFilterEditorWidget(container, filter, this._cssIsValid);
},
show: Task.async(function* () {

View File

@ -377,8 +377,7 @@ JSTerm.prototype = {
if (this.hud.NEW_CONSOLE_OUTPUT_ENABLED) {
this.hud.newConsoleOutput.dispatchMessageAdd(response);
// @TODO figure out what to do about the callback.
callback && callback();
callback && callback(this.hud.newConsoleOutput.getLastMessage());
return;
}
let msg = new Messages.JavaScriptEvalOutput(response,
@ -426,7 +425,7 @@ JSTerm.prototype = {
let deferred = promise.defer();
let resultCallback;
if (this.hud.NEW_CONSOLE_OUTPUT_ENABLED) {
resultCallback = () => deferred.resolve();
resultCallback = (msg) => deferred.resolve(msg);
} else {
resultCallback = (msg) => {
deferred.resolve(msg);
@ -453,7 +452,7 @@ JSTerm.prototype = {
let message = new ConsoleCommand({
messageText: executeString,
});
this.hud.newConsoleOutput.dispatchMessageAdd(message);
this.hud.proxy.dispatchMessageAdd(message);
} else {
let message = new Messages.Simple(executeString, {
category: "input",

View File

@ -25,6 +25,13 @@ registerCleanupFunction(() => {
Services.prefs.clearUserPref(NET_XHR_PREF, true);
});
// Use the old webconsole since the new one doesn't yet support
// XHR spy. See Bug 1304794.
Services.prefs.setBoolPref("devtools.webconsole.new-frontend-enabled", false);
registerCleanupFunction(function* () {
Services.prefs.clearUserPref("devtools.webconsole.new-frontend-enabled");
});
/**
* Add a new test tab in the browser and load the given url.
* @param {String} url The url to be loaded in the new tab

View File

@ -17,6 +17,7 @@ const FilterBar = React.createFactory(require("devtools/client/webconsole/new-co
const store = configureStore();
function NewConsoleOutputWrapper(parentNode, jsterm, toolbox, owner) {
this.parentNode = parentNode;
this.parentNode = parentNode;
this.jsterm = jsterm;
this.toolbox = toolbox;
@ -68,6 +69,12 @@ NewConsoleOutputWrapper.prototype = {
dispatchMessagesClear: () => {
store.dispatch(actions.messagesClear());
},
getLastMessage: function() {
// Return the last message in the DOM as the message that was just dispatched. This may not
// always be correct in the case of filtered messages, but it's close enough for our tests.
let messageNodes = this.parentNode.querySelectorAll(".message");
return messageNodes[messageNodes.length - 1]
},
};
// Exports from this module

View File

@ -52,16 +52,19 @@ var openNewTabAndConsole = Task.async(function* (url) {
function waitForMessages({ hud, messages }) {
return new Promise(resolve => {
let numMatched = 0;
let receivedLog = hud.ui.on("new-messages", function messagesReceieved(e, newMessage) {
let receivedLog = hud.ui.on("new-messages", function messagesReceieved(e, newMessages) {
for (let message of messages) {
if (message.matched) {
continue;
}
if (newMessage.node.querySelector(".message-body").textContent == message.text) {
numMatched++;
message.matched = true;
info("Matched a message with text: " + message.text + ", still waiting for " + (messages.length - numMatched) + " messages");
for (let newMessage of newMessages) {
if (newMessage.node.querySelector(".message-body").textContent == message.text) {
numMatched++;
message.matched = true;
info("Matched a message with text: " + message.text + ", still waiting for " + (messages.length - numMatched) + " messages");
break;
}
}
if (numMatched === messages.length) {

View File

@ -21,7 +21,7 @@ const TEST_CASES = [
},
{
input: '(new DOMParser()).parseFromString("<svg></svg>", "image/svg+xml")',
output: "SVGDocument",
output: "XMLDocument",
inspectable: true,
},
];

View File

@ -321,6 +321,12 @@ var finishTest = Task.async(function* () {
finish();
});
// Always use the 'old' frontend for tests that rely on it
Services.prefs.setBoolPref("devtools.webconsole.new-frontend-enabled", false);
registerCleanupFunction(function* () {
Services.prefs.clearUserPref("devtools.webconsole.new-frontend-enabled");
});
registerCleanupFunction(function* () {
flags.testing = false;

View File

@ -3266,14 +3266,10 @@ WebConsoleConnectionProxy.prototype = {
*/
dispatchMessageAdd: function(packet) {
this.webConsoleFrame.newConsoleOutput.dispatchMessageAdd(packet);
// Return the last message in the DOM as the message that was just dispatched. This may not
// always be true in the case of filtered messages, but it's close enough for our tests.
let messageNodes = this.webConsoleFrame.experimentalOutputNode.querySelectorAll(".message");
this.webConsoleFrame.emit("new-messages", {
this.webConsoleFrame.emit("new-messages", new Set([{
response: packet,
node: messageNodes[messageNodes.length - 1],
});
node: this.webConsoleFrame.newConsoleOutput.getLastMessage(),
}]));
},
/**

View File

@ -94,6 +94,11 @@ window.onload = function() {
"A property with color values includes papayawhip.");
ok(bgColorValues.includes("rgb"),
"A property with color values includes non-colors.");
ok(cssProperties.isValidOnClient("margin", "0px", window.document),
"Margin and 0px are valid CSS values");
ok(!cssProperties.isValidOnClient("margin", "foo", window.document),
"Margin and foo are not valid CSS values");
});
addAsyncTest(function* setup() {

View File

@ -65,6 +65,10 @@ function CssProperties(db) {
this.isKnown = this.isKnown.bind(this);
this.isInherited = this.isInherited.bind(this);
this.supportsType = this.supportsType.bind(this);
this.isValidOnClient = this.isValidOnClient.bind(this);
// A weakly held dummy HTMLDivElement to test CSS properties on the client.
this._dummyElements = new WeakMap();
}
CssProperties.prototype = {
@ -79,6 +83,45 @@ CssProperties.prototype = {
return !!this.properties[property] || isCssVariable(property);
},
/**
* Quickly check if a CSS name/value combo is valid on the client.
*
* @param {String} Property name.
* @param {String} Property value.
* @param {Document} The client's document object.
* @return {Boolean}
*/
isValidOnClient(name, value, doc) {
let dummyElement = this._dummyElements.get(doc);
if (!dummyElement) {
dummyElement = doc.createElement("div");
this._dummyElements.set(doc, dummyElement);
}
// `!important` is not a valid value when setting a style declaration in the
// CSS Object Model.
const sanitizedValue = ("" + value).replace(/!\s*important\s*$/, "");
// Test the style on the element.
dummyElement.style[name] = sanitizedValue;
const isValid = !!dummyElement.style[name];
// Reset the state of the dummy element;
dummyElement.style[name] = "";
return isValid;
},
/**
* Get a function that will check the validity of css name/values for a given document.
* Useful for injecting isValidOnClient into components when needed.
*
* @param {Document} The client's document object.
* @return {Function} this.isValidOnClient with the document pre-set.
*/
getValidityChecker(doc) {
return (name, value) => this.isValidOnClient(name, value, doc);
},
/**
* Checks to see if the property is an inherited one.
*

View File

@ -46,7 +46,7 @@ DocumentTimeline::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
/* static */ already_AddRefed<DocumentTimeline>
DocumentTimeline::Constructor(const GlobalObject& aGlobal,
const DOMHighResTimeStamp& aOriginTime,
const DocumentTimelineOptions& aOptions,
ErrorResult& aRv)
{
nsIDocument* doc = AnimationUtils::GetCurrentRealmDocument(aGlobal.Context());
@ -54,12 +54,11 @@ DocumentTimeline::Constructor(const GlobalObject& aGlobal,
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
TimeDuration originTime =
TimeDuration::FromMilliseconds(aOptions.mOriginTime);
TimeDuration originTime = TimeDuration::FromMilliseconds(aOriginTime);
if (originTime == TimeDuration::Forever() ||
originTime == -TimeDuration::Forever()) {
nsAutoString inputOriginTime;
inputOriginTime.AppendFloat(aOriginTime);
aRv.ThrowTypeError<dom::MSG_TIME_VALUE_OUT_OF_RANGE>(
NS_LITERAL_STRING("Origin time"));
return nullptr;

View File

@ -7,6 +7,7 @@
#ifndef mozilla_dom_DocumentTimeline_h
#define mozilla_dom_DocumentTimeline_h
#include "mozilla/dom/DocumentTimelineBinding.h"
#include "mozilla/TimeStamp.h"
#include "AnimationTimeline.h"
#include "nsIDocument.h"
@ -54,7 +55,7 @@ public:
static already_AddRefed<DocumentTimeline>
Constructor(const GlobalObject& aGlobal,
const DOMHighResTimeStamp& aOriginTime,
const DocumentTimelineOptions& aOptions,
ErrorResult& aRv);
// AnimationTimeline methods

View File

@ -118,7 +118,7 @@ test(function(t) {
}, 'After cancelling a transition, updating transition properties doesn\'t make'
+ ' it live again');
test(function(t) {
promise_test(function(t) {
var div = addDiv(t, { style: 'margin-left: 0px' });
flushComputedStyle(div);
@ -127,11 +127,39 @@ test(function(t) {
flushComputedStyle(div);
var animation = div.getAnimations()[0];
div.style.display = 'none';
assert_equals(animation.playState, 'idle');
assert_equals(getComputedStyle(div).marginLeft, '1000px');
return animation.ready.then(function() {
assert_equals(animation.playState, 'running');
div.style.display = 'none';
return waitForFrame();
}).then(function() {
assert_equals(animation.playState, 'idle');
assert_equals(getComputedStyle(div).marginLeft, '1000px');
});
}, 'Setting display:none on an element cancels its transitions');
promise_test(function(t) {
var parentDiv = addDiv(t);
var childDiv = document.createElement('div');
parentDiv.appendChild(childDiv);
childDiv.setAttribute('style', 'margin-left: 0px');
flushComputedStyle(childDiv);
childDiv.style.transition = 'margin-left 100s';
childDiv.style.marginLeft = '1000px';
flushComputedStyle(childDiv);
var animation = childDiv.getAnimations()[0];
return animation.ready.then(function() {
assert_equals(animation.playState, 'running');
parentDiv.style.display = 'none';
return waitForFrame();
}).then(function() {
assert_equals(animation.playState, 'idle');
assert_equals(getComputedStyle(childDiv).marginLeft, '1000px');
});
}, 'Setting display:none cancels transitions on a child element');
done();
</script>
</body>

View File

@ -12,13 +12,17 @@
// inside the allowed range will just mean we overflow elsewhere.
test(function(t) {
assert_throws({name: 'TypeError'},
function() { new DocumentTimeline(Number.MAX_SAFE_INTEGER); });
assert_throws({ name: 'TypeError'},
function() {
new DocumentTimeline({ originTime: Number.MAX_SAFE_INTEGER });
});
}, 'Calculated current time is positive infinity');
test(function(t) {
assert_throws({name: 'TypeError'},
function() { new DocumentTimeline(-1 * Number.MAX_SAFE_INTEGER); });
assert_throws({ name: 'TypeError'},
function() {
new DocumentTimeline({ originTime: -1 * Number.MAX_SAFE_INTEGER });
});
}, 'Calculated current time is negative infinity');
done();

View File

@ -12,24 +12,6 @@
namespace mozilla {
namespace dom {
already_AddRefed<Blob>
BlobSet::GetBlobInternal(nsISupports* aParent,
const nsACString& aContentType,
ErrorResult& aRv)
{
nsTArray<RefPtr<BlobImpl>> subImpls(GetBlobImpls());
RefPtr<BlobImpl> blobImpl =
MultipartBlobImpl::Create(Move(subImpls),
NS_ConvertASCIItoUTF16(aContentType),
aRv);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
RefPtr<Blob> blob = Blob::Create(aParent, blobImpl);
return blob.forget();
}
nsresult
BlobSet::AppendVoidPtr(const void* aData, uint32_t aLength)
{
@ -38,13 +20,16 @@ BlobSet::AppendVoidPtr(const void* aData, uint32_t aLength)
return NS_OK;
}
uint64_t offset = mDataLen;
if (!ExpandBufferSize(aLength)) {
void* data = malloc(aLength);
if (!data) {
return NS_ERROR_OUT_OF_MEMORY;
}
memcpy((char*)mData + offset, aData, aLength);
memcpy((char*)data, aData, aLength);
RefPtr<BlobImpl> blobImpl = new BlobImplMemory(data, aLength, EmptyString());
mBlobImpls.AppendElement(blobImpl);
return NS_OK;
}
@ -71,69 +56,9 @@ nsresult
BlobSet::AppendBlobImpl(BlobImpl* aBlobImpl)
{
NS_ENSURE_ARG_POINTER(aBlobImpl);
Flush();
mBlobImpls.AppendElement(aBlobImpl);
return NS_OK;
}
nsresult
BlobSet::AppendBlobImpls(const nsTArray<RefPtr<BlobImpl>>& aBlobImpls)
{
Flush();
mBlobImpls.AppendElements(aBlobImpls);
return NS_OK;
}
bool
BlobSet::ExpandBufferSize(uint64_t aSize)
{
if (mDataBufferLen >= mDataLen + aSize) {
mDataLen += aSize;
return true;
}
// Start at 1 or we'll loop forever.
CheckedUint32 bufferLen =
std::max<uint32_t>(static_cast<uint32_t>(mDataBufferLen), 1);
while (bufferLen.isValid() && bufferLen.value() < mDataLen + aSize) {
bufferLen *= 2;
}
if (!bufferLen.isValid()) {
return false;
}
void* data = realloc(mData, bufferLen.value());
if (!data) {
return false;
}
mData = data;
mDataBufferLen = bufferLen.value();
mDataLen += aSize;
return true;
}
void
BlobSet::Flush()
{
if (mData) {
// If we have some data, create a blob for it
// and put it on the stack
RefPtr<BlobImpl> blobImpl =
new BlobImplMemory(mData, mDataLen, EmptyString());
mBlobImpls.AppendElement(blobImpl);
mData = nullptr; // The nsDOMMemoryFile takes ownership of the buffer
mDataLen = 0;
mDataBufferLen = 0;
return;
}
}
} // dom namespace
} // mozilla namespace

View File

@ -12,23 +12,11 @@
namespace mozilla {
namespace dom {
class Blob;
class BlobImpl;
class BlobSet final
{
public:
BlobSet()
: mData(nullptr)
, mDataLen(0)
, mDataBufferLen(0)
{}
~BlobSet()
{
free(mData);
}
nsresult AppendVoidPtr(const void* aData, uint32_t aLength);
nsresult AppendString(const nsAString& aString, bool nativeEOL,
@ -36,23 +24,10 @@ public:
nsresult AppendBlobImpl(BlobImpl* aBlobImpl);
nsresult AppendBlobImpls(const nsTArray<RefPtr<BlobImpl>>& aBlobImpls);
nsTArray<RefPtr<BlobImpl>>& GetBlobImpls() { Flush(); return mBlobImpls; }
already_AddRefed<Blob> GetBlobInternal(nsISupports* aParent,
const nsACString& aContentType,
ErrorResult& aRv);
nsTArray<RefPtr<BlobImpl>>& GetBlobImpls() { return mBlobImpls; }
private:
bool ExpandBufferSize(uint64_t aSize);
void Flush();
nsTArray<RefPtr<BlobImpl>> mBlobImpls;
void* mData;
uint64_t mDataLen;
uint64_t mDataBufferLen;
};
} // namespace dom

View File

@ -910,8 +910,10 @@ Location::GetSourceBaseURL(JSContext* cx, nsIURI** sourceURL)
}
bool
Location::CallerSubsumes()
Location::CallerSubsumes(nsIPrincipal* aSubjectPrincipal)
{
MOZ_ASSERT(aSubjectPrincipal);
// Get the principal associated with the location object. Note that this is
// the principal of the page which will actually be navigated, not the
// principal of the Location object itself. This is why we need this check
@ -923,7 +925,8 @@ Location::CallerSubsumes()
nsCOMPtr<nsIScriptObjectPrincipal> sop = do_QueryInterface(outer);
bool subsumes = false;
nsresult rv =
nsContentUtils::SubjectPrincipal()->SubsumesConsideringDomain(sop->GetPrincipal(), &subsumes);
aSubjectPrincipal->SubsumesConsideringDomain(sop->GetPrincipal(),
&subsumes);
NS_ENSURE_SUCCESS(rv, false);
return subsumes;
}

View File

@ -44,119 +44,180 @@ public:
NS_DECL_NSIDOMLOCATION
#define THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME() { \
if (!CallerSubsumes()) { \
MOZ_ASSERT(aSubjectPrincipal.isSome()); \
if (!CallerSubsumes(aSubjectPrincipal.value())) { \
aError.Throw(NS_ERROR_DOM_SECURITY_ERR); \
return; \
} \
}
// WebIDL API:
void Assign(const nsAString& aUrl, ErrorResult& aError)
void Assign(const nsAString& aUrl,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
ErrorResult& aError)
{
THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME();
aError = Assign(aUrl);
}
void Replace(const nsAString& aUrl, ErrorResult& aError)
void Replace(const nsAString& aUrl,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
ErrorResult& aError)
{
aError = Replace(aUrl);
}
void Reload(bool aForceget, ErrorResult& aError)
void Reload(bool aForceget,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
ErrorResult& aError)
{
THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME();
aError = Reload(aForceget);
}
void GetHref(nsAString& aHref, ErrorResult& aError)
void GetHref(nsAString& aHref,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
ErrorResult& aError)
{
THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME();
aError = GetHref(aHref);
}
void SetHref(const nsAString& aHref, ErrorResult& aError)
void SetHref(const nsAString& aHref,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
ErrorResult& aError)
{
aError = SetHref(aHref);
}
void GetOrigin(nsAString& aOrigin, ErrorResult& aError)
void GetOrigin(nsAString& aOrigin,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
ErrorResult& aError)
{
THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME();
aError = GetOrigin(aOrigin);
}
void GetProtocol(nsAString& aProtocol, ErrorResult& aError)
void GetProtocol(nsAString& aProtocol,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
ErrorResult& aError)
{
THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME();
aError = GetProtocol(aProtocol);
}
void SetProtocol(const nsAString& aProtocol, ErrorResult& aError)
void SetProtocol(const nsAString& aProtocol,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
ErrorResult& aError)
{
THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME();
aError = SetProtocol(aProtocol);
}
void GetHost(nsAString& aHost, ErrorResult& aError)
void GetHost(nsAString& aHost,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
ErrorResult& aError)
{
THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME();
aError = GetHost(aHost);
}
void SetHost(const nsAString& aHost, ErrorResult& aError)
void SetHost(const nsAString& aHost,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
ErrorResult& aError)
{
THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME();
aError = SetHost(aHost);
}
void GetHostname(nsAString& aHostname, ErrorResult& aError)
void GetHostname(nsAString& aHostname,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
ErrorResult& aError)
{
THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME();
aError = GetHostname(aHostname);
}
void SetHostname(const nsAString& aHostname, ErrorResult& aError)
void SetHostname(const nsAString& aHostname,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
ErrorResult& aError)
{
THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME();
aError = SetHostname(aHostname);
}
void GetPort(nsAString& aPort, ErrorResult& aError)
void GetPort(nsAString& aPort,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
ErrorResult& aError)
{
THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME();
aError = GetPort(aPort);
}
void SetPort(const nsAString& aPort, ErrorResult& aError)
void SetPort(const nsAString& aPort,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
ErrorResult& aError)
{
THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME();
aError = SetPort(aPort);
}
void GetPathname(nsAString& aPathname, ErrorResult& aError)
void GetPathname(nsAString& aPathname,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
ErrorResult& aError)
{
THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME();
aError = GetPathname(aPathname);
}
void SetPathname(const nsAString& aPathname, ErrorResult& aError)
void SetPathname(const nsAString& aPathname,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
ErrorResult& aError)
{
THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME();
aError = SetPathname(aPathname);
}
void GetSearch(nsAString& aSeach, ErrorResult& aError)
void GetSearch(nsAString& aSeach,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
ErrorResult& aError)
{
THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME();
aError = GetSearch(aSeach);
}
void SetSearch(const nsAString& aSeach, ErrorResult& aError)
void SetSearch(const nsAString& aSeach,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
ErrorResult& aError)
{
THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME();
aError = SetSearch(aSeach);
}
void GetHash(nsAString& aHash, ErrorResult& aError)
void GetHash(nsAString& aHash,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
ErrorResult& aError)
{
THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME();
aError = GetHash(aHash);
}
void SetHash(const nsAString& aHash, ErrorResult& aError)
void SetHash(const nsAString& aHash,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
ErrorResult& aError)
{
THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME();
aError = SetHash(aHash);
}
void Stringify(nsAString& aRetval, ErrorResult& aError)
void Stringify(nsAString& aRetval,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
ErrorResult& aError)
{
// GetHref checks CallerSubsumes.
GetHref(aRetval, aError);
GetHref(aRetval, aSubjectPrincipal, aError);
}
nsPIDOMWindowInner* GetParentObject() const
{
return mInnerWindow;
@ -185,7 +246,7 @@ protected:
nsresult GetSourceBaseURL(JSContext* cx, nsIURI** sourceURL);
nsresult CheckURL(nsIURI *url, nsIDocShellLoadInfo** aLoadInfo);
bool CallerSubsumes();
bool CallerSubsumes(nsIPrincipal* aSubjectPrincipal);
nsString mCachedHash;
nsCOMPtr<nsPIDOMWindowInner> mInnerWindow;

View File

@ -0,0 +1,617 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/MutableBlobStorage.h"
#include "mozilla/CheckedInt.h"
#include "mozilla/dom/File.h"
#include "nsAnonymousTemporaryFile.h"
#include "nsNetCID.h"
#include "WorkerPrivate.h"
#define BLOB_MEMORY_TEMPORARY_FILE 1048576
namespace mozilla {
namespace dom {
namespace {
// This class uses the callback to inform when the Blob is created or when the
// error must be propagated.
class BlobCreationDoneRunnable final : public Runnable
{
public:
BlobCreationDoneRunnable(MutableBlobStorage* aBlobStorage,
MutableBlobStorageCallback* aCallback,
Blob* aBlob,
nsresult aRv)
: mBlobStorage(aBlobStorage)
, mCallback(aCallback)
, mBlob(aBlob)
, mRv(aRv)
{
MOZ_ASSERT(aBlobStorage);
MOZ_ASSERT(aCallback);
MOZ_ASSERT((NS_FAILED(aRv) && !aBlob) ||
(NS_SUCCEEDED(aRv) && aBlob));
}
NS_IMETHOD
Run() override
{
MOZ_ASSERT(NS_IsMainThread());
mCallback->BlobStoreCompleted(mBlobStorage, mBlob, mRv);
mCallback = nullptr;
mBlob = nullptr;
return NS_OK;
}
private:
~BlobCreationDoneRunnable()
{
// If something when wrong, we still have to release these objects in the
// correct thread.
NS_ReleaseOnMainThread(mCallback.forget());
NS_ReleaseOnMainThread(mBlob.forget());
}
RefPtr<MutableBlobStorage> mBlobStorage;
RefPtr<MutableBlobStorageCallback> mCallback;
RefPtr<Blob> mBlob;
nsresult mRv;
};
// This runnable goes back to the main-thread and informs the BlobStorage about
// the temporary file.
class FileCreatedRunnable final : public Runnable
{
public:
FileCreatedRunnable(MutableBlobStorage* aBlobStorage, PRFileDesc* aFD)
: mBlobStorage(aBlobStorage)
, mFD(aFD)
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(aBlobStorage);
MOZ_ASSERT(aFD);
}
NS_IMETHOD
Run() override
{
MOZ_ASSERT(NS_IsMainThread());
mBlobStorage->TemporaryFileCreated(mFD);
mFD = nullptr;
return NS_OK;
}
private:
~FileCreatedRunnable()
{
// If something when wrong, we still have to close the FileDescriptor.
if (mFD) {
PR_Close(mFD);
}
}
RefPtr<MutableBlobStorage> mBlobStorage;
PRFileDesc* mFD;
};
// This runnable creates the temporary file. When done, FileCreatedRunnable is
// dispatched back to the main-thread.
class CreateTemporaryFileRunnable final : public Runnable
{
public:
explicit CreateTemporaryFileRunnable(MutableBlobStorage* aBlobStorage)
: mBlobStorage(aBlobStorage)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aBlobStorage);
}
NS_IMETHOD
Run() override
{
MOZ_ASSERT(!NS_IsMainThread());
PRFileDesc* tempFD = nullptr;
nsresult rv = NS_OpenAnonymousTemporaryFile(&tempFD);
if (NS_WARN_IF(NS_FAILED(rv))) {
// In sandboxed context we are not allowed to create temporary files, but
// this doesn't mean that BlobStorage should fail. We can continue to
// store data in memory. We don't change the storageType so that we don't
// try to create a temporary file again.
return NS_OK;
}
// The ownership of the tempFD is moved to the FileCreatedRunnable.
return NS_DispatchToMainThread(new FileCreatedRunnable(mBlobStorage, tempFD));
}
private:
RefPtr<MutableBlobStorage> mBlobStorage;
};
// Simple runnable to propagate the error to the BlobStorage.
class ErrorPropagationRunnable final : public Runnable
{
public:
ErrorPropagationRunnable(MutableBlobStorage* aBlobStorage, nsresult aRv)
: mBlobStorage(aBlobStorage)
, mRv(aRv)
{}
NS_IMETHOD
Run() override
{
mBlobStorage->ErrorPropagated(mRv);
return NS_OK;
}
private:
RefPtr<MutableBlobStorage> mBlobStorage;
nsresult mRv;
};
// This runnable moves a buffer to the IO thread and there, it writes it into
// the temporary file.
class WriteRunnable final : public Runnable
{
public:
static WriteRunnable*
CopyBuffer(MutableBlobStorage* aBlobStorage, PRFileDesc* aFD,
const void* aData, uint32_t aLength)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aBlobStorage);
MOZ_ASSERT(aFD);
MOZ_ASSERT(aData);
// We have to take a copy of this buffer.
void* data = malloc(aLength);
if (!data) {
return nullptr;
}
memcpy((char*)data, aData, aLength);
return new WriteRunnable(aBlobStorage, aFD, data, aLength);
}
static WriteRunnable*
AdoptBuffer(MutableBlobStorage* aBlobStorage, PRFileDesc* aFD,
void* aData, uint32_t aLength)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aBlobStorage);
MOZ_ASSERT(aFD);
MOZ_ASSERT(aData);
return new WriteRunnable(aBlobStorage, aFD, aData, aLength);
}
NS_IMETHOD
Run() override
{
MOZ_ASSERT(!NS_IsMainThread());
int32_t written = PR_Write(mFD, mData, mLength);
if (NS_WARN_IF(written < 0 || uint32_t(written) != mLength)) {
return NS_DispatchToMainThread(
new ErrorPropagationRunnable(mBlobStorage, NS_ERROR_FAILURE));
}
return NS_OK;
}
private:
WriteRunnable(MutableBlobStorage* aBlobStorage, PRFileDesc* aFD,
void* aData, uint32_t aLength)
: mBlobStorage(aBlobStorage)
, mFD(aFD)
, mData(aData)
, mLength(aLength)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mBlobStorage);
MOZ_ASSERT(aFD);
MOZ_ASSERT(aData);
}
~WriteRunnable()
{
free(mData);
}
RefPtr<MutableBlobStorage> mBlobStorage;
PRFileDesc* mFD;
void* mData;
uint32_t mLength;
};
// This runnable closes the FD in case something goes wrong or the temporary
// file is not needed anymore.
class CloseFileRunnable final : public Runnable
{
public:
explicit CloseFileRunnable(PRFileDesc* aFD)
: mFD(aFD)
{}
NS_IMETHOD
Run() override
{
MOZ_ASSERT(!NS_IsMainThread());
PR_Close(mFD);
mFD = nullptr;
return NS_OK;
}
private:
~CloseFileRunnable()
{
if (mFD) {
PR_Close(mFD);
}
}
PRFileDesc* mFD;
};
// This runnable is dispatched to the main-thread from the IO thread and its
// task is to create the blob and inform the callback.
class CreateBlobRunnable final : public Runnable
{
public:
CreateBlobRunnable(MutableBlobStorage* aBlobStorage,
already_AddRefed<nsISupports> aParent,
const nsACString& aContentType,
already_AddRefed<MutableBlobStorageCallback> aCallback)
: mBlobStorage(aBlobStorage)
, mParent(aParent)
, mContentType(aContentType)
, mCallback(aCallback)
{
MOZ_ASSERT(!NS_IsMainThread());
}
NS_IMETHOD
Run() override
{
MOZ_ASSERT(NS_IsMainThread());
mBlobStorage->CreateBlobAndRespond(mParent.forget(), mContentType,
mCallback.forget());
return NS_OK;
}
private:
~CreateBlobRunnable()
{
// If something when wrong, we still have to release data in the correct
// thread.
NS_ReleaseOnMainThread(mParent.forget());
NS_ReleaseOnMainThread(mCallback.forget());
}
RefPtr<MutableBlobStorage> mBlobStorage;
nsCOMPtr<nsISupports> mParent;
nsCString mContentType;
RefPtr<MutableBlobStorageCallback> mCallback;
};
// This task is used to know when the writing is completed. From the IO thread
// it dispatches a CreateBlobRunnable to the main-thread.
class LastRunnable final : public Runnable
{
public:
LastRunnable(MutableBlobStorage* aBlobStorage,
nsISupports* aParent,
const nsACString& aContentType,
MutableBlobStorageCallback* aCallback)
: mBlobStorage(aBlobStorage)
, mParent(aParent)
, mContentType(aContentType)
, mCallback(aCallback)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mBlobStorage);
MOZ_ASSERT(aParent);
MOZ_ASSERT(aCallback);
}
NS_IMETHOD
Run() override
{
MOZ_ASSERT(!NS_IsMainThread());
RefPtr<Runnable> runnable =
new CreateBlobRunnable(mBlobStorage, mParent.forget(),
mContentType, mCallback.forget());
return NS_DispatchToMainThread(runnable);
}
private:
~LastRunnable()
{
// If something when wrong, we still have to release data in the correct
// thread.
NS_ReleaseOnMainThread(mParent.forget());
NS_ReleaseOnMainThread(mCallback.forget());
}
RefPtr<MutableBlobStorage> mBlobStorage;
nsCOMPtr<nsISupports> mParent;
nsCString mContentType;
RefPtr<MutableBlobStorageCallback> mCallback;
};
} // anonymous namespace
MutableBlobStorage::MutableBlobStorage(MutableBlobStorageType aType)
: mData(nullptr)
, mDataLen(0)
, mDataBufferLen(0)
, mStorageState(aType == eOnlyInMemory ? eKeepInMemory : eInMemory)
, mFD(nullptr)
, mErrorResult(NS_OK)
{
MOZ_ASSERT(NS_IsMainThread());
}
MutableBlobStorage::~MutableBlobStorage()
{
free(mData);
if (mFD) {
DispatchToIOThread(new CloseFileRunnable(mFD));
}
}
uint64_t
MutableBlobStorage::GetBlobWhenReady(nsISupports* aParent,
const nsACString& aContentType,
MutableBlobStorageCallback* aCallback)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aParent);
MOZ_ASSERT(aCallback);
// GetBlob can be called just once.
MOZ_ASSERT(mStorageState != eClosed);
StorageState previousState = mStorageState;
mStorageState = eClosed;
if (previousState == eInTemporaryFile) {
MOZ_ASSERT(mFD);
if (NS_FAILED(mErrorResult)) {
NS_DispatchToMainThread(
new BlobCreationDoneRunnable(this, aCallback, nullptr, mErrorResult));
return 0;
}
// We want to wait until all the WriteRunnable are completed. The way we do
// this is to go to the I/O thread and then we come back: the runnables are
// executed in order and this LastRunnable will be... the last one.
nsresult rv = DispatchToIOThread(new LastRunnable(this, aParent,
aContentType, aCallback));
if (NS_WARN_IF(NS_FAILED(rv))) {
NS_DispatchToMainThread(
new BlobCreationDoneRunnable(this, aCallback, nullptr, rv));
return 0;
}
return mDataLen;
}
RefPtr<BlobImpl> blobImpl;
if (mData) {
blobImpl = new BlobImplMemory(mData, mDataLen,
NS_ConvertUTF8toUTF16(aContentType));
mData = nullptr; // The BlobImplMemory takes ownership of the buffer
mDataLen = 0;
mDataBufferLen = 0;
} else {
blobImpl = new EmptyBlobImpl(NS_ConvertUTF8toUTF16(aContentType));
}
RefPtr<Blob> blob = Blob::Create(aParent, blobImpl);
RefPtr<BlobCreationDoneRunnable> runnable =
new BlobCreationDoneRunnable(this, aCallback, blob, NS_OK);
nsresult error = NS_DispatchToMainThread(runnable);
if (NS_WARN_IF(NS_FAILED(error))) {
return 0;
}
return mDataLen;
}
nsresult
MutableBlobStorage::Append(const void* aData, uint32_t aLength)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mStorageState != eClosed);
NS_ENSURE_ARG_POINTER(aData);
if (!aLength) {
return NS_OK;
}
// If eInMemory is the current Storage state, we could maybe migrate to
// a temporary file.
if (mStorageState == eInMemory && ShouldBeTemporaryStorage(aLength)) {
nsresult rv = MaybeCreateTemporaryFile();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
// If we are already in the temporaryFile mode, we have to dispatch a
// runnable.
if (mStorageState == eInTemporaryFile) {
MOZ_ASSERT(mFD);
RefPtr<WriteRunnable> runnable =
WriteRunnable::CopyBuffer(this, mFD, aData, aLength);
if (NS_WARN_IF(!runnable)) {
return NS_ERROR_OUT_OF_MEMORY;
}
nsresult rv = DispatchToIOThread(runnable);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
mDataLen += aLength;
return NS_OK;
}
// By default, we store in memory.
uint64_t offset = mDataLen;
if (!ExpandBufferSize(aLength)) {
return NS_ERROR_OUT_OF_MEMORY;
}
memcpy((char*)mData + offset, aData, aLength);
return NS_OK;
}
bool
MutableBlobStorage::ExpandBufferSize(uint64_t aSize)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mStorageState < eInTemporaryFile);
if (mDataBufferLen >= mDataLen + aSize) {
mDataLen += aSize;
return true;
}
// Start at 1 or we'll loop forever.
CheckedUint32 bufferLen =
std::max<uint32_t>(static_cast<uint32_t>(mDataBufferLen), 1);
while (bufferLen.isValid() && bufferLen.value() < mDataLen + aSize) {
bufferLen *= 2;
}
if (!bufferLen.isValid()) {
return false;
}
void* data = realloc(mData, bufferLen.value());
if (!data) {
return false;
}
mData = data;
mDataBufferLen = bufferLen.value();
mDataLen += aSize;
return true;
}
bool
MutableBlobStorage::ShouldBeTemporaryStorage(uint64_t aSize) const
{
MOZ_ASSERT(mStorageState == eInMemory);
CheckedUint32 bufferSize = mDataLen;
bufferSize += aSize;
if (!bufferSize.isValid()) {
return false;
}
return bufferSize.value() >= Preferences::GetUint("dom.blob.memoryToTemporaryFile",
BLOB_MEMORY_TEMPORARY_FILE);
}
nsresult
MutableBlobStorage::MaybeCreateTemporaryFile()
{
nsresult rv = DispatchToIOThread(new CreateTemporaryFileRunnable(this));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
mStorageState = eWaitingForTemporaryFile;
return NS_OK;
}
void
MutableBlobStorage::TemporaryFileCreated(PRFileDesc* aFD)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mStorageState == eWaitingForTemporaryFile ||
mStorageState == eClosed);
if (mStorageState == eClosed) {
DispatchToIOThread(new CloseFileRunnable(aFD));
return;
}
mStorageState = eInTemporaryFile;
mFD = aFD;
RefPtr<WriteRunnable> runnable =
WriteRunnable::AdoptBuffer(this, mFD, mData, mDataLen);
MOZ_ASSERT(runnable);
mData = nullptr;
nsresult rv = DispatchToIOThread(runnable);
if (NS_WARN_IF(NS_FAILED(rv))) {
mErrorResult = rv;
return;
}
}
void
MutableBlobStorage::CreateBlobAndRespond(already_AddRefed<nsISupports> aParent,
const nsACString& aContentType,
already_AddRefed<MutableBlobStorageCallback> aCallback)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mStorageState == eClosed);
MOZ_ASSERT(mFD);
nsCOMPtr<nsISupports> parent(aParent);
RefPtr<MutableBlobStorageCallback> callback(aCallback);
RefPtr<Blob> blob =
File::CreateTemporaryBlob(parent, mFD, 0, mDataLen,
NS_ConvertUTF8toUTF16(aContentType));
callback->BlobStoreCompleted(this, blob, NS_OK);
// ownership of this FD is moved to the BlobImpl.
mFD = nullptr;
}
void
MutableBlobStorage::ErrorPropagated(nsresult aRv)
{
MOZ_ASSERT(NS_IsMainThread());
mErrorResult = aRv;
}
/* static */ nsresult
MutableBlobStorage::DispatchToIOThread(Runnable* aRunnable)
{
nsCOMPtr<nsIEventTarget> target
= do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
MOZ_ASSERT(target);
nsresult rv = target->Dispatch(aRunnable, NS_DISPATCH_NORMAL);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
} // dom namespace
} // mozilla namespace

View File

@ -0,0 +1,98 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_MutableBlobStorage_h
#define mozilla_dom_MutableBlobStorage_h
#include "mozilla/RefPtr.h"
#include "prio.h"
namespace mozilla {
namespace dom {
class Blob;
class BlobImpl;
class MutableBlobStorage;
class MutableBlobStorageCallback
{
public:
NS_IMETHOD_(MozExternalRefCountType) AddRef(void) = 0;
NS_IMETHOD_(MozExternalRefCountType) Release(void) = 0;
virtual void BlobStoreCompleted(MutableBlobStorage* aBlobStorage,
Blob* aBlob,
nsresult aRv) = 0;
};
// This class is main-thread only.
class MutableBlobStorage final
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MutableBlobStorage);
enum MutableBlobStorageType
{
eOnlyInMemory,
eCouldBeInTemporaryFile,
};
explicit MutableBlobStorage(MutableBlobStorageType aType);
nsresult Append(const void* aData, uint32_t aLength);
// This method can be called just once.
// The callback will be called when the Blob is ready.
// The return value is the total size of the blob, when created.
uint64_t GetBlobWhenReady(nsISupports* aParent,
const nsACString& aContentType,
MutableBlobStorageCallback* aCallback);
void TemporaryFileCreated(PRFileDesc* aFD);
void CreateBlobAndRespond(already_AddRefed<nsISupports> aParent,
const nsACString& aContentType,
already_AddRefed<MutableBlobStorageCallback> aCallback);
void ErrorPropagated(nsresult aRv);
private:
~MutableBlobStorage();
bool ExpandBufferSize(uint64_t aSize);
bool ShouldBeTemporaryStorage(uint64_t aSize) const;
nsresult MaybeCreateTemporaryFile();
static nsresult DispatchToIOThread(Runnable* aRunnable);
// All these variables are touched on the main thread only.
void* mData;
uint64_t mDataLen;
uint64_t mDataBufferLen;
enum StorageState {
eKeepInMemory,
eInMemory,
eWaitingForTemporaryFile,
eInTemporaryFile,
eClosed
};
StorageState mStorageState;
PRFileDesc* mFD;
nsresult mErrorResult;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_MutableBlobStorage_h

View File

@ -116,10 +116,8 @@
#endif
#include "mozilla/dom/ContentChild.h"
#ifdef MOZ_EME
#include "mozilla/EMEUtils.h"
#include "mozilla/DetailedPromise.h"
#endif
namespace mozilla {
namespace dom {
@ -249,9 +247,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Navigator)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mServiceWorkerContainer)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow)
#ifdef MOZ_EME
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaKeySystemAccessManager)
#endif
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDeviceStorageAreaListener)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPresentation)
#ifdef MOZ_GAMEPAD
@ -386,12 +382,10 @@ Navigator::Invalidate()
mServiceWorkerContainer = nullptr;
#ifdef MOZ_EME
if (mMediaKeySystemAccessManager) {
mMediaKeySystemAccessManager->Shutdown();
mMediaKeySystemAccessManager = nullptr;
}
#endif
if (mDeviceStorageAreaListener) {
mDeviceStorageAreaListener = nullptr;
@ -2324,7 +2318,6 @@ Navigator::GetUserAgent(nsPIDOMWindowInner* aWindow, nsIURI* aURI,
return siteSpecificUA->GetUserAgentForURIAndWindow(aURI, aWindow, aUserAgent);
}
#ifdef MOZ_EME
static nsCString
ToCString(const nsString& aString)
{
@ -2450,7 +2443,6 @@ Navigator::RequestMediaKeySystemAccess(const nsAString& aKeySystem,
mMediaKeySystemAccessManager->Request(promise, aKeySystem, aConfigs);
return promise.forget();
}
#endif
Presentation*
Navigator::GetPresentation(ErrorResult& aRv)

View File

@ -18,9 +18,7 @@
#include "nsString.h"
#include "nsTArray.h"
#include "nsWeakPtr.h"
#ifdef MOZ_EME
#include "mozilla/dom/MediaKeySystemAccessManager.h"
#endif
class nsPluginArray;
class nsMimeTypeArray;
@ -317,14 +315,12 @@ public:
// any, else null.
static already_AddRefed<nsPIDOMWindowInner> GetWindowFromGlobal(JSObject* aGlobal);
#ifdef MOZ_EME
already_AddRefed<Promise>
RequestMediaKeySystemAccess(const nsAString& aKeySystem,
const Sequence<MediaKeySystemConfiguration>& aConfig,
ErrorResult& aRv);
private:
RefPtr<MediaKeySystemAccessManager> mMediaKeySystemAccessManager;
#endif
public:
void NotifyVRDisplaysUpdated();

View File

@ -166,3 +166,16 @@ DOM_MSG_DEF(NS_ERROR_DOM_DOMEXCEPTION, "A DOMException was thrown")
DOM4_MSG_DEF(AbortError, "The fetching process for the media resource was aborted by the user agent at the user's request.", NS_ERROR_DOM_MEDIA_ABORT_ERR)
DOM4_MSG_DEF(NotAllowedError, "The play method is not allowed by the user agent or the platform in the current context, possibly because the user denied permission.", NS_ERROR_DOM_MEDIA_NOT_ALLOWED_ERR)
DOM4_MSG_DEF(NotSupportedError, "The media resource indicated by the src attribute or assigned media provider object was not suitable.", NS_ERROR_DOM_MEDIA_NOT_SUPPORTED_ERR)
DOM4_MSG_DEF(SyntaxError, "The URI is malformed.", NS_ERROR_DOM_MALFORMED_URI)
DOM4_MSG_DEF(SyntaxError, "Invalid header name.", NS_ERROR_DOM_INVALID_HEADER_NAME)
/* XMLHttpRequest errors. */
DOM4_MSG_DEF(InvalidStateError, "XMLHttpRequest has an invalid context.", NS_ERROR_DOM_INVALID_STATE_XHR_HAS_INVALID_CONTEXT)
DOM4_MSG_DEF(InvalidStateError, "XMLHttpRequest state must be OPENED.", NS_ERROR_DOM_INVALID_STATE_XHR_MUST_BE_OPENED)
DOM4_MSG_DEF(InvalidStateError, "XMLHttpRequest must not be sending.", NS_ERROR_DOM_INVALID_STATE_XHR_MUST_NOT_BE_SENDING)
DOM4_MSG_DEF(InvalidStateError, "XMLHttpRequest state must not be LOADING or DONE.", NS_ERROR_DOM_INVALID_STATE_XHR_MUST_NOT_BE_LOADING_OR_DONE)
DOM4_MSG_DEF(InvalidStateError, "responseXML is only available if responseType is '' or 'document'.", NS_ERROR_DOM_INVALID_STATE_XHR_HAS_WRONG_RESPONSETYPE_FOR_RESPONSEXML)
DOM4_MSG_DEF(InvalidStateError, "responseText is only available if responseType is '', 'document', or 'moz-chunked-text'.", NS_ERROR_DOM_INVALID_STATE_XHR_HAS_WRONG_RESPONSETYPE_FOR_RESPONSETEXT)
DOM4_MSG_DEF(InvalidStateError, "synchronous XMLHttpRequests do not support 'moz-chunked-text' or 'moz-chunked-arraybuffer' responseType.", NS_ERROR_DOM_INVALID_STATE_XHR_CHUNKED_RESPONSETYPES_UNSUPPORTED_FOR_SYNC)
DOM4_MSG_DEF(InvalidAccessError, "synchronous XMLHttpRequests do not support timeout and responseType.", NS_ERROR_DOM_INVALID_ACCESS_XHR_TIMEOUT_AND_RESPONSETYPE_UNSUPPORTED_FOR_SYNC)

View File

@ -186,6 +186,7 @@ EXPORTS.mozilla.dom += [
'ImportManager.h',
'Link.h',
'Location.h',
'MutableBlobStorage.h',
'NameSpaceConstants.h',
'Navigator.h',
'NodeInfo.h',
@ -247,6 +248,7 @@ UNIFIED_SOURCES += [
'Link.cpp',
'Location.cpp',
'MultipartBlobImpl.cpp',
'MutableBlobStorage.cpp',
'Navigator.cpp',
'NodeInfo.cpp',
'NodeIterator.cpp',

View File

@ -28,6 +28,7 @@
#include "nsJSEnvironment.h"
#include "nsInProcessTabChildGlobal.h"
#include "nsFrameLoader.h"
#include "mozilla/CycleCollectedJSContext.h"
#include "mozilla/EventListenerManager.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/ProcessGlobal.h"
@ -313,6 +314,8 @@ MarkWindowList(nsISimpleEnumerator* aWindowList, bool aCleanupJS,
nsCOMPtr<nsIContentFrameMessageManager> mm;
tabChild->GetMessageManager(getter_AddRefs(mm));
if (mm) {
// MarkForCC ends up calling UnmarkGray on message listeners, which
// TraceBlackJS can't do yet.
mm->MarkForCC();
}
}
@ -489,6 +492,13 @@ mozilla::dom::TraceBlackJS(JSTracer* aTrc, uint32_t aGCNumber, bool aIsShutdownG
return;
}
if (nsFrameMessageManager::GetChildProcessManager()) {
nsIContentProcessMessageManager* pg = ProcessGlobal::Get();
if (pg) {
mozilla::TraceScriptHolder(pg, aTrc);
}
}
// Mark globals of active windows black.
nsGlobalWindow::WindowByIdTable* windowsById =
nsGlobalWindow::GetWindowsTable();
@ -502,6 +512,31 @@ mozilla::dom::TraceBlackJS(JSTracer* aTrc, uint32_t aGCNumber, bool aIsShutdownG
elm->TraceListeners(aTrc);
}
if (window->IsRootOuterWindow()) {
// In child process trace all the TabChildGlobals.
// Since there is one root outer window per TabChildGlobal, we need
// to look for only those windows, not all.
nsIDocShell* ds = window->GetDocShell();
if (ds) {
nsCOMPtr<nsITabChild> tabChild = ds->GetTabChild();
if (tabChild) {
nsCOMPtr<nsIContentFrameMessageManager> mm;
tabChild->GetMessageManager(getter_AddRefs(mm));
nsCOMPtr<EventTarget> et = do_QueryInterface(mm);
if (et) {
nsCOMPtr<nsISupports> tabChildAsSupports =
do_QueryInterface(tabChild);
mozilla::TraceScriptHolder(tabChildAsSupports, aTrc);
EventListenerManager* elm = et->GetExistingListenerManager();
if (elm) {
elm->TraceListeners(aTrc);
}
// As of now there isn't an easy way to trace message listeners.
}
}
}
}
#ifdef MOZ_XUL
nsIDocument* doc = window->GetExtantDoc();
if (doc && doc->IsXULDocument()) {

View File

@ -33,6 +33,7 @@ DEPRECATED_OPERATION(MozGetAsFile)
DEPRECATED_OPERATION(UseOfCaptureEvents)
DEPRECATED_OPERATION(UseOfReleaseEvents)
DEPRECATED_OPERATION(UseOfDOM3LoadMethod)
DEPRECATED_OPERATION(ChromeUseOfDOM3LoadMethod)
DEPRECATED_OPERATION(ShowModalDialog)
DEPRECATED_OPERATION(Window_Content)
DEPRECATED_OPERATION(SyncXMLHttpRequest)

View File

@ -252,7 +252,7 @@
#include "mozilla/StyleSetHandleInlines.h"
#include "mozilla/StyleSheet.h"
#include "mozilla/StyleSheetInlines.h"
#include "mozilla/dom/SVGSVGElement.h"
#include "mozilla/DocLoadingTimelineMarker.h"
#include "nsISpeculativeConnect.h"
@ -3038,6 +3038,16 @@ nsDocument::GetAnimations(nsTArray<RefPtr<Animation>>& aAnimations)
root->GetAnimations(filter, aAnimations);
}
SVGSVGElement*
nsIDocument::GetSVGRootElement() const
{
Element* root = GetRootElement();
if (!root || !root->IsSVGElement(nsGkAtoms::svg)) {
return nullptr;
}
return static_cast<SVGSVGElement*>(root);
}
/* Return true if the document is in the focused top-level window, and is an
* ancestor of the focused DOMWindow. */
NS_IMETHODIMP
@ -4346,7 +4356,6 @@ nsDocument::SetScopeObject(nsIGlobalObject* aGlobal)
}
}
#ifdef MOZ_EME
static void
CheckIfContainsEMEContent(nsISupports* aSupports, void* aContainsEME)
{
@ -4370,7 +4379,6 @@ nsDocument::ContainsEMEContent()
static_cast<void*>(&containsEME));
return containsEME;
}
#endif // MOZ_EME
static void
CheckIfContainsMSEContent(nsISupports* aSupports, void* aContainsMSE)
@ -5973,30 +5981,6 @@ nsDocument::GetElementsByTagNameNS(const nsAString& aNamespaceURI,
return NS_OK;
}
NS_IMETHODIMP
nsDocument::GetAsync(bool *aAsync)
{
NS_ERROR("nsDocument::GetAsync() should be overriden by subclass!");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsDocument::SetAsync(bool aAsync)
{
NS_ERROR("nsDocument::SetAsync() should be overriden by subclass!");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsDocument::Load(const nsAString& aUrl, bool *aReturn)
{
NS_ERROR("nsDocument::Load() should be overriden by subclass!");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsDocument::GetStyleSheets(nsIDOMStyleSheetList** aStyleSheets)
{
@ -8375,13 +8359,11 @@ nsDocument::CanSavePresentation(nsIRequest *aNewRequest)
}
#endif // MOZ_WEBRTC
#ifdef MOZ_EME
// Don't save presentations for documents containing EME content, so that
// CDMs reliably shutdown upon user navigation.
if (ContainsEMEContent()) {
return false;
}
#endif
// Don't save presentations for documents containing MSE content, to
// reduce memory usage.

View File

@ -19,7 +19,7 @@
#include "nsWeakReference.h"
#include "nsWeakPtr.h"
#include "nsTArray.h"
#include "nsIDOMXMLDocument.h"
#include "nsIDOMDocument.h"
#include "nsIDOMDocumentXBL.h"
#include "nsStubDocumentObserver.h"
#include "nsIScriptGlobalObject.h"
@ -485,16 +485,8 @@ protected:
};
// Base class for our document implementations.
//
// Note that this class *implements* nsIDOMXMLDocument, but it's not
// really an nsIDOMXMLDocument. The reason for implementing
// nsIDOMXMLDocument on this class is to avoid having to duplicate all
// its inherited methods on document classes that *are*
// nsIDOMXMLDocument's. nsDocument's QI should *not* claim to support
// nsIDOMXMLDocument unless someone writes a real implementation of
// the interface.
class nsDocument : public nsIDocument,
public nsIDOMXMLDocument, // inherits nsIDOMDocument
public nsIDOMDocument,
public nsIDOMDocumentXBL,
public nsSupportsWeakReference,
public nsIScriptObjectPrincipal,
@ -798,9 +790,6 @@ public:
// nsIDOMDocument
NS_DECL_NSIDOMDOCUMENT
// nsIDOMXMLDocument
NS_DECL_NSIDOMXMLDOCUMENT
// nsIDOMDocumentXBL
NS_DECL_NSIDOMDOCUMENTXBL
@ -1275,9 +1264,7 @@ public:
js::ExpandoAndGeneration mExpandoAndGeneration;
#ifdef MOZ_EME
bool ContainsEMEContent();
#endif
bool ContainsMSEContent();

View File

@ -2228,8 +2228,6 @@ GK_ATOM(scrollbar_start_forward, "scrollbar-start-forward")
GK_ATOM(scrollbar_end_backward, "scrollbar-end-backward")
GK_ATOM(scrollbar_end_forward, "scrollbar-end-forward")
GK_ATOM(scrollbar_thumb_proportional, "scrollbar-thumb-proportional")
GK_ATOM(images_in_menus, "images-in-menus")
GK_ATOM(images_in_buttons, "images-in-buttons")
GK_ATOM(overlay_scrollbars, "overlay-scrollbars")
GK_ATOM(windows_default_theme, "windows-default-theme")
GK_ATOM(mac_graphite_theme, "mac-graphite-theme")
@ -2259,8 +2257,6 @@ GK_ATOM(_moz_scrollbar_start_forward, "-moz-scrollbar-start-forward")
GK_ATOM(_moz_scrollbar_end_backward, "-moz-scrollbar-end-backward")
GK_ATOM(_moz_scrollbar_end_forward, "-moz-scrollbar-end-forward")
GK_ATOM(_moz_scrollbar_thumb_proportional, "-moz-scrollbar-thumb-proportional")
GK_ATOM(_moz_images_in_menus, "-moz-images-in-menus")
GK_ATOM(_moz_images_in_buttons, "-moz-images-in-buttons")
GK_ATOM(_moz_overlay_scrollbars, "-moz-overlay-scrollbars")
GK_ATOM(_moz_windows_default_theme, "-moz-windows-default-theme")
GK_ATOM(_moz_mac_graphite_theme, "-moz-mac-graphite-theme")

View File

@ -622,7 +622,7 @@ nsPIDOMWindow<T>::nsPIDOMWindow(nsPIDOMWindowOuter *aOuterWindow)
mMediaSuspend(Preferences::GetBool("media.block-autoplay-until-in-foreground", true) ?
nsISuspendedTypes::SUSPENDED_BLOCK : nsISuspendedTypes::NONE_SUSPENDED),
mAudioMuted(false), mAudioVolume(1.0), mAudioCaptured(false),
mDesktopModeViewport(false), mInnerWindow(nullptr),
mDesktopModeViewport(false), mIsRootOuterWindow(false), mInnerWindow(nullptr),
mOuterWindow(aOuterWindow),
// Make sure no actual window ends up with mWindowID == 0
mWindowID(NextWindowID()), mHasNotifiedGlobalCreated(false),
@ -3067,6 +3067,7 @@ nsGlobalWindow::SetDocShell(nsIDocShell* aDocShell)
}
else {
mChromeEventHandler = NS_NewWindowRoot(AsOuter());
mIsRootOuterWindow = true;
}
}

View File

@ -148,6 +148,7 @@ class ProcessingInstruction;
class Promise;
class StyleSheetList;
class SVGDocument;
class SVGSVGElement;
class Touch;
class TouchList;
class TreeWalker;
@ -2328,6 +2329,8 @@ public:
virtual void GetAnimations(
nsTArray<RefPtr<mozilla::dom::Animation>>& aAnimations) = 0;
mozilla::dom::SVGSVGElement* GetSVGRootElement() const;
nsresult ScheduleFrameRequestCallback(mozilla::dom::FrameRequestCallback& aCallback,
int32_t *aHandle);
void CancelFrameRequestCallback(int32_t aHandle);

View File

@ -118,6 +118,12 @@ public:
virtual nsPIDOMWindowOuter* GetScriptableParent() = 0;
virtual already_AddRefed<nsPIWindowRoot> GetTopWindowRoot() = 0;
bool IsRootOuterWindow()
{
MOZ_ASSERT(IsOuterWindow());
return mIsRootOuterWindow;
}
/**
* Behavies identically to GetScriptableParent extept that it returns null
* if GetScriptableParent would return this window.
@ -666,6 +672,8 @@ protected:
// current desktop mode flag.
bool mDesktopModeViewport;
bool mIsRootOuterWindow;
// And these are the references between inner and outer windows.
nsPIDOMWindowInner* MOZ_NON_OWNING_REF mInnerWindow;
nsCOMPtr<nsPIDOMWindowOuter> mOuterWindow;

View File

@ -217,7 +217,7 @@ var tests =
{target: XHR, type: "loadend", optional: false}]},
{ method: "GET", withUpload: none, testAbort: true, testRedirectError: false, testNetworkError: false,
expectedEvents: [{target: XHR, type: "loadstart", optional: false},
{target: XHR, type: "progress", optional: false},
{target: XHR, type: "progress", optional: true},
{target: XHR, type: "abort", optional: false},
{target: XHR, type: "loadend", optional: false}]},
{ method: "GET", withUpload: none, testAbort: false, testRedirectError: true, testNetworkError: false,
@ -236,7 +236,7 @@ var tests =
{target: XHR, type: "loadend", optional: false}]},
{ method: "GET", withUpload: small, testAbort: true, testRedirectError: false, testNetworkError: false,
expectedEvents: [{target: XHR, type: "loadstart", optional: false},
{target: XHR, type: "progress", optional: false},
{target: XHR, type: "progress", optional: true},
{target: XHR, type: "abort", optional: false},
{target: XHR, type: "loadend", optional: false}]},
{ method: "GET", withUpload: small, testAbort: false, testRedirectError: true, testNetworkError: false,
@ -255,7 +255,7 @@ var tests =
{target: XHR, type: "loadend", optional: false}]},
{ method: "GET", withUpload: mid, testAbort: true, testRedirectError: false, testNetworkError: false,
expectedEvents: [{target: XHR, type: "loadstart", optional: false},
{target: XHR, type: "progress", optional: false},
{target: XHR, type: "progress", optional: true},
{target: XHR, type: "abort", optional: false},
{target: XHR, type: "loadend", optional: false}]},
{ method: "GET", withUpload: mid, testAbort: false, testRedirectError: true, testNetworkError: false,
@ -274,7 +274,7 @@ var tests =
{target: XHR, type: "loadend", optional: false}]},
{ method: "GET", withUpload: large, testAbort: true, testRedirectError: false, testNetworkError: false,
expectedEvents: [{target: XHR, type: "loadstart", optional: false},
{target: XHR, type: "progress", optional: false},
{target: XHR, type: "progress", optional: true},
{target: XHR, type: "abort", optional: false},
{target: XHR, type: "loadend", optional: false}]},
{ method: "GET", withUpload: large, testAbort: false, testRedirectError: true, testNetworkError: false,
@ -293,7 +293,7 @@ var tests =
{target: XHR, type: "loadend", optional: false}]},
{ method: "POST", withUpload: none, testAbort: true, testRedirectError: false, testNetworkError: false,
expectedEvents: [{target: XHR, type: "loadstart", optional: false},
{target: XHR, type: "progress", optional: false},
{target: XHR, type: "progress", optional: true},
{target: XHR, type: "abort", optional: false},
{target: XHR, type: "loadend", optional: false}]},
{ method: "POST", withUpload: none, testAbort: false, testRedirectError: true, testNetworkError: false,
@ -317,10 +317,10 @@ var tests =
{ method: "POST", withUpload: small, testAbort: true, testRedirectError: false, testNetworkError: false,
expectedEvents: [{target: XHR, type: "loadstart", optional: false},
{target: UPLOAD, type: "loadstart", optional: false},
{target: UPLOAD, type: "progress", optional: false},
{target: UPLOAD, type: "progress", optional: true},
{target: UPLOAD, type: "abort", optional: false},
{target: UPLOAD, type: "loadend", optional: false},
{target: XHR, type: "progress", optional: false},
{target: XHR, type: "progress", optional: true},
{target: XHR, type: "abort", optional: false},
{target: XHR, type: "loadend", optional: false}]},
{ method: "POST", withUpload: small, testAbort: false, testRedirectError: true, testNetworkError: false,
@ -351,10 +351,10 @@ var tests =
{ method: "POST", withUpload: mid, testAbort: true, testRedirectError: false, testNetworkError: false,
expectedEvents: [{target: XHR, type: "loadstart", optional: false},
{target: UPLOAD, type: "loadstart", optional: false},
{target: UPLOAD, type: "progress", optional: false},
{target: UPLOAD, type: "progress", optional: true},
{target: UPLOAD, type: "abort", optional: false},
{target: UPLOAD, type: "loadend", optional: false},
{target: XHR, type: "progress", optional: false},
{target: XHR, type: "progress", optional: true},
{target: XHR, type: "abort", optional: false},
{target: XHR, type: "loadend", optional: false}]},
{ method: "POST", withUpload: mid, testAbort: false, testRedirectError: true, testNetworkError: false,
@ -385,10 +385,10 @@ var tests =
{ method: "POST", withUpload: large, testAbort: true, testRedirectError: false, testNetworkError: false,
expectedEvents: [{target: XHR, type: "loadstart", optional: false},
{target: UPLOAD, type: "loadstart", optional: false},
{target: UPLOAD, type: "progress", optional: false},
{target: UPLOAD, type: "progress", optional: true},
{target: UPLOAD, type: "abort", optional: false},
{target: UPLOAD, type: "loadend", optional: false},
{target: XHR, type: "progress", optional: false},
{target: XHR, type: "progress", optional: true},
{target: XHR, type: "abort", optional: false},
{target: XHR, type: "loadend", optional: false}]},
{ method: "POST", withUpload: large, testAbort: false, testRedirectError: true, testNetworkError: false,

View File

@ -34,8 +34,6 @@ function testHTMLDocuments(ids, isXHTML) {
is(doc1.body, null, "Shouldn't have .body!");
ok(doc1 instanceof HTMLDocument,
"Document should be an HTML document!");
ok(!(doc1 instanceof SVGDocument),
"Document shouldn't be an SVG document!");
var docType2 =
document.implementation.createDocumentType(isXHTML ? "html" : "HTML",
@ -70,11 +68,11 @@ function testSVGDocument() {
ok(!doc1.documentElement, "Document shouldn't have document element!");
ok(!(doc1 instanceof HTMLDocument),
"Document shouldn't be an HTML document!");
ok(doc1 instanceof SVGDocument,
"Document should be an SVG document!");
ok(doc1 instanceof XMLDocument,
"Document should be an XML document!");
// SVG documents have .rootElement.
ok("rootElement" in doc1, "No .rootElement in document");
// SVG documents have .documentElement.
ok("documentElement" in doc1, "No .documentElement in document");
var docType2 =
document.implementation.createDocumentType("svg",
@ -83,8 +81,7 @@ function testSVGDocument() {
var doc2 = document.implementation.createDocument("http://www.w3.org/2000/svg",
"svg", docType2);
ok(doc2.documentElement, "Document should have document element!");
ok(doc2.rootElement, "Should have .rootElement in document");
is(doc2.rootElement.localName, "svg", "Wrong .rootElement!");
is(doc2.documentElement.localName, "svg", "Wrong .documentElement!");
}
function testFooBarDocument() {
@ -97,8 +94,6 @@ function testFooBarDocument() {
ok(!doc1.documentElement, "Document shouldn't have document element!");
ok(!(doc1 instanceof HTMLDocument),
"Document shouldn't be an HTML document!");
ok(!(doc1 instanceof SVGDocument),
"Document shouldn't be an SVG document!");
var docType2 =
document.implementation.createDocumentType("FooBar", "FooBar", null);
@ -114,8 +109,6 @@ function testNullDocTypeDocument() {
ok(!doc1.documentElement, "Document shouldn't have document element!");
ok(!(doc1 instanceof HTMLDocument),
"Document shouldn't be an HTML document!");
ok(!(doc1 instanceof SVGDocument),
"Document shouldn't be an SVG document!");
var doc2 = document.implementation.createDocument("FooBarNS",
"FooBar", null);

View File

@ -23,16 +23,11 @@ var dp = new DOMParser();
var d = dp.parseFromString("<?xml version='1.0'?><svg xmlns='http://www.w3.org/2000/svg'></svg>",
"image/svg+xml");
ok(d instanceof SVGDocument, "Should have created an SVG document.");
ok("rootElement" in d, "Should have created an SVG document, which has .rootElement.");
ok(d instanceof XMLDocument, "Should have created an XML document.");
ok("documentElement" in d, "Should have created an XML document, which has .documentElement.");
is(d.documentElement.localName, "svg", "Root element should be svg.");
is(d.documentElement.namespaceURI, "http://www.w3.org/2000/svg",
"Root element should be in svg namespace.");
dp = new DOMParser();
d = dp.parseFromString("<?xml version='1.0'?><svg xmlns='http://www.w3.org/2000/svg'></svg>",
"text/xml");
ok(!(d instanceof SVGDocument), "Should not have created an SVG document!");
</script>
</pre>
</body>

View File

@ -1117,7 +1117,7 @@ QueryInterface(JSContext* cx, unsigned argc, JS::Value* vp)
JS::Rooted<JSObject*> obj(cx, js::CheckedUnwrap(origObj,
/* stopAtWindowProxy = */ false));
if (!obj) {
JS_ReportError(cx, "Permission denied to access object");
JS_ReportErrorASCII(cx, "Permission denied to access object");
return false;
}

View File

@ -1855,8 +1855,6 @@ addExternalIface('nsIBrowserDOMWindow', nativeType='nsIBrowserDOMWindow',
addExternalIface('nsIControllers', nativeType='nsIControllers')
addExternalIface('nsIDOMCrypto', nativeType='nsIDOMCrypto',
headerFile='Crypto.h')
addExternalIface('nsIInputStreamCallback', nativeType='nsIInputStreamCallback',
headerFile='nsIAsyncInputStream.h')
addExternalIface('nsIFile', nativeType='nsIFile', notflattened=True)
addExternalIface('nsILoadGroup', nativeType='nsILoadGroup',
headerFile='nsILoadGroup.h', notflattened=True)

View File

@ -6836,6 +6836,9 @@ class CGCallGenerator(CGThing):
A class to generate an actual call to a C++ object. Assumes that the C++
object is stored in a variable whose name is given by the |object| argument.
needsSubjectPrincipal is a boolean indicating whether the call should
receive the subject nsIPrincipal as argument.
isFallible is a boolean indicating whether the call should be fallible.
resultVar: If the returnType is not void, then the result of the call is
@ -6843,9 +6846,10 @@ class CGCallGenerator(CGThing):
declaring the result variable. If the caller doesn't care about the result
value, resultVar can be omitted.
"""
def __init__(self, isFallible, arguments, argsPre, returnType,
extendedAttributes, descriptorProvider, nativeMethodName,
static, object="self", argsPost=[], resultVar=None):
def __init__(self, isFallible, needsSubjectPrincipal, arguments, argsPre,
returnType, extendedAttributes, descriptorProvider,
nativeMethodName, static, object="self", argsPost=[],
resultVar=None):
CGThing.__init__(self)
result, resultOutParam, resultRooter, resultArgs, resultConversion = \
@ -6902,6 +6906,9 @@ class CGCallGenerator(CGThing):
assert resultOutParam == "ptr"
args.append(CGGeneric("&" + resultVar))
if needsSubjectPrincipal:
args.append(CGGeneric("subjectPrincipal"))
if isFallible:
args.append(CGGeneric("rv"))
args.extend(CGGeneric(arg) for arg in argsPost)
@ -6940,6 +6947,18 @@ class CGCallGenerator(CGThing):
call = CGWrapper(call, post=";\n")
self.cgRoot.append(call)
if needsSubjectPrincipal:
self.cgRoot.prepend(CGGeneric(dedent(
"""
Maybe<nsIPrincipal*> subjectPrincipal;
if (NS_IsMainThread()) {
JSCompartment* compartment = js::GetContextCompartment(cx);
MOZ_ASSERT(compartment);
JSPrincipals* principals = JS_GetCompartmentPrincipals(compartment);
subjectPrincipal.emplace(nsJSPrincipals::get(principals));
}
""")))
if isFallible:
self.cgRoot.prepend(CGGeneric("binding_detail::FastErrorResult rv;\n"))
self.cgRoot.append(CGGeneric(dedent(
@ -7406,6 +7425,7 @@ class CGPerSignatureCall(CGThing):
else:
cgThings.append(CGCallGenerator(
self.isFallible(),
idlNode.getExtendedAttribute('NeedsSubjectPrincipal'),
self.getArguments(), argsPre, returnType,
self.extendedAttributes, descriptor,
nativeMethodName,
@ -13812,6 +13832,9 @@ class CGNativeMember(ClassMethod):
elif returnType.isObject() or returnType.isSpiderMonkeyInterface():
args.append(Argument("JS::MutableHandle<JSObject*>", "aRetVal"))
# And the nsIPrincipal
if self.member.getExtendedAttribute('NeedsSubjectPrincipal'):
args.append(Argument("const Maybe<nsIPrincipal*>&", "aPrincipal"))
# And the ErrorResult
if 'infallible' not in self.extendedAttrs:
# Use aRv so it won't conflict with local vars named "rv"
@ -15757,7 +15780,7 @@ class CGMaplikeOrSetlikeMethodGenerator(CGThing):
// TODO (Bug 1173651): Xrays currently cannot wrap iterators. Change
// after bug 1023984 is fixed.
if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
JS_ReportError(cx, "Xray wrapping of iterators not supported.");
JS_ReportErrorASCII(cx, "Xray wrapping of iterators not supported.");
return false;
}
JS::Rooted<JSObject*> result(cx);

View File

@ -4204,6 +4204,7 @@ class IDLAttribute(IDLInterfaceMember):
identifier == "Frozen" or
identifier == "NewObject" or
identifier == "UnsafeInPrerendering" or
identifier == "NeedsSubjectPrincipal" or
identifier == "BinaryName"):
# Known attributes that we don't need to do anything with here
pass
@ -4920,6 +4921,7 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
identifier == "Func" or
identifier == "SecureContext" or
identifier == "BinaryName" or
identifier == "NeedsSubjectPrincipal" or
identifier == "StaticClassOverride"):
# Known attributes that we don't need to do anything with here
pass

View File

@ -773,6 +773,8 @@ interface TestExampleInterface {
[Throws] attribute boolean throwingAttr;
[GetterThrows] attribute boolean throwingGetterAttr;
[SetterThrows] attribute boolean throwingSetterAttr;
[NeedsSubjectPrincipal] void needsSubjectPrincipalMethod();
[NeedsSubjectPrincipal] attribute boolean needsSubjectPrincipalAttr;
legacycaller short(unsigned long arg1, TestInterface arg2);
void passArgsWithDefaults(optional long arg1,
optional TestInterface? arg2 = null,

View File

@ -4785,12 +4785,10 @@ CanvasRenderingContext2D::DrawImage(const CanvasImageSource& aImage,
return;
}
#ifdef MOZ_EME
if (video->ContainsRestrictedContent()) {
aError.Throw(NS_ERROR_NOT_AVAILABLE);
return;
}
#endif
uint16_t readyState;
if (NS_SUCCEEDED(video->GetReadyState(&readyState)) &&

View File

@ -395,15 +395,16 @@ TexUnpackBytes::TexOrSubImage(bool isSubImage, bool needsRespec, const char* fun
if (!isSubImage) {
// Alloc first to catch OOMs.
gl->fBindBuffer(LOCAL_GL_PIXEL_UNPACK_BUFFER, 0);
AssertUintParamCorrect(gl, LOCAL_GL_PIXEL_UNPACK_BUFFER, 0);
*out_error = DoTexOrSubImage(false, gl, target, level, dui, xOffset, yOffset,
zOffset, mWidth, mHeight, mDepth, nullptr);
gl->fBindBuffer(LOCAL_GL_PIXEL_UNPACK_BUFFER,
webgl->mBoundPixelUnpackBuffer->mGLName);
if (*out_error)
return false;
}
const ScopedLazyBind bindPBO(gl, LOCAL_GL_PIXEL_UNPACK_BUFFER,
webgl->mBoundPixelUnpackBuffer);
//////
// Make our sometimes-implicit values explicit. Also this keeps them constant when we

View File

@ -85,6 +85,8 @@ WebGL2Context::CopyBufferSubData(GLenum readTarget, GLenum writeTarget,
}
gl->MakeCurrent();
const ScopedLazyBind readBind(gl, readTarget, readBuffer);
const ScopedLazyBind writeBind(gl, writeTarget, writeBuffer);
gl->fCopyBufferSubData(readTarget, writeTarget, readOffset, writeOffset, size);
}
@ -143,6 +145,7 @@ WebGL2Context::GetBufferSubData(GLenum target, GLintptr offset,
////
gl->MakeCurrent();
const ScopedLazyBind readBind(gl, target, buffer);
const auto ptr = gl->fMapBufferRange(target, offset, data.LengthAllowShared(),
LOCAL_GL_MAP_READ_BIT);

View File

@ -16,6 +16,7 @@ WebGLBuffer::WebGLBuffer(WebGLContext* webgl, GLuint buf)
: WebGLContextBoundObject(webgl)
, mGLName(buf)
, mContent(Kind::Undefined)
, mUsage(LOCAL_GL_STATIC_DRAW)
, mByteLength(0)
, mNumActiveTFOs(0)
, mBoundForTF(false)
@ -114,6 +115,7 @@ WebGLBuffer::BufferData(GLenum target, size_t size, const void* data, GLenum usa
const auto& gl = mContext->gl;
gl->MakeCurrent();
const ScopedLazyBind lazyBind(gl, target, this);
mContext->InvalidateBufferFetching();
#ifdef XP_MACOSX
@ -141,6 +143,7 @@ WebGLBuffer::BufferData(GLenum target, size_t size, const void* data, GLenum usa
gl->fBufferData(target, size, data, usage);
}
mUsage = usage;
mByteLength = size;
// Warning: Possibly shared memory. See bug 1225033.

View File

@ -45,6 +45,7 @@ public:
size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
GLenum Usage() const { return mUsage; }
size_t ByteLength() const { return mByteLength; }
bool ElementArrayCacheBufferData(const void* ptr, size_t bufferSizeInBytes);
@ -74,6 +75,7 @@ protected:
~WebGLBuffer();
Kind mContent;
GLenum mUsage;
size_t mByteLength;
UniquePtr<WebGLElementArrayCache> mCache;
size_t mNumActiveTFOs;

View File

@ -2159,6 +2159,39 @@ ScopedFBRebinder::UnwrapImpl()
}
}
////////////////////
static GLenum
TargetIfLazy(GLenum target)
{
switch (target) {
case LOCAL_GL_PIXEL_PACK_BUFFER:
case LOCAL_GL_PIXEL_UNPACK_BUFFER:
return target;
default:
return 0;
}
}
ScopedLazyBind::ScopedLazyBind(gl::GLContext* gl, GLenum target, const WebGLBuffer* buf)
: ScopedGLWrapper<ScopedLazyBind>(gl)
, mTarget(buf ? TargetIfLazy(target) : 0)
, mBuf(buf)
{
if (mTarget) {
mGL->fBindBuffer(mTarget, mBuf->mGLName);
}
}
void
ScopedLazyBind::UnwrapImpl()
{
if (mTarget) {
mGL->fBindBuffer(mTarget, 0);
}
}
////////////////////////////////////////
void

View File

@ -1834,6 +1834,21 @@ private:
void UnwrapImpl();
};
class ScopedLazyBind final
: public gl::ScopedGLWrapper<ScopedLazyBind>
{
friend struct gl::ScopedGLWrapper<ScopedLazyBind>;
const GLenum mTarget;
const WebGLBuffer* const mBuf;
public:
ScopedLazyBind(gl::GLContext* gl, GLenum target, const WebGLBuffer* buf);
private:
void UnwrapImpl();
};
void
ComputeLengthAndData(const dom::ArrayBufferViewOrSharedArrayBufferView& view,
void** const out_data, size_t* const out_length,

View File

@ -137,6 +137,13 @@ WebGLContext::BindBuffer(GLenum target, WebGLBuffer* buffer)
if (buffer) {
buffer->SetContentAfterBind(target);
}
switch (target) {
case LOCAL_GL_PIXEL_PACK_BUFFER:
case LOCAL_GL_PIXEL_UNPACK_BUFFER:
gl->fBindBuffer(target, 0);
break;
}
}
////////////////////////////////////////
@ -429,6 +436,8 @@ WebGLContext::BufferSubDataT(GLenum target,
}
MakeContextCurrent();
const ScopedLazyBind lazyBind(gl, target, buffer);
// Warning: Possibly shared memory. See bug 1225033.
gl->fBufferSubData(target, byteOffset, data.LengthAllowShared(),
data.DataAllowShared());

View File

@ -630,28 +630,17 @@ WebGLContext::GetBufferParameter(GLenum target, GLenum pname)
if (!buffer)
return JS::NullValue();
MakeContextCurrent();
switch (pname) {
case LOCAL_GL_BUFFER_SIZE:
case LOCAL_GL_BUFFER_USAGE:
{
GLint i = 0;
gl->fGetBufferParameteriv(target, pname, &i);
if (pname == LOCAL_GL_BUFFER_SIZE) {
return JS::Int32Value(i);
}
case LOCAL_GL_BUFFER_SIZE:
return JS::NumberValue(buffer->ByteLength());
MOZ_ASSERT(pname == LOCAL_GL_BUFFER_USAGE);
return JS::NumberValue(uint32_t(i));
}
break;
case LOCAL_GL_BUFFER_USAGE:
return JS::NumberValue(buffer->Usage());
default:
ErrorInvalidEnumInfo("getBufferParameter: parameter", pname);
default:
ErrorInvalidEnumInfo("getBufferParameter: parameter", pname);
return JS::NullValue();
}
return JS::NullValue();
}
JS::Value
@ -1528,6 +1517,9 @@ WebGL2Context::ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenu
bytesAfterOffset = checkedBytesAfterOffset.value();
}
gl->MakeCurrent();
const ScopedLazyBind lazyBind(gl, LOCAL_GL_PIXEL_PACK_BUFFER, mBoundPixelPackBuffer);
ReadPixelsImpl(x, y, width, height, format, type, (void*)offset, bytesAfterOffset);
}

View File

@ -33,9 +33,9 @@ private:
bool mIsActive;
// Not in state tables:
WebGLRefPtr<WebGLProgram> mActive_Program;
GLenum mActive_PrimMode;
size_t mActive_VertPosition;
size_t mActive_VertCapacity;
MOZ_INIT_OUTSIDE_CTOR GLenum mActive_PrimMode;
MOZ_INIT_OUTSIDE_CTOR size_t mActive_VertPosition;
MOZ_INIT_OUTSIDE_CTOR size_t mActive_VertCapacity;
public:
WebGLTransformFeedback(WebGLContext* webgl, GLuint tf);

View File

@ -53,6 +53,7 @@ fail-if = (os == 'android') || (os == 'win' && os_version == '5.1')
[test_backbuffer_channels.html]
fail-if = (os == 'b2g')
[test_depth_readpixels.html]
[test_canvas_size.html]
[test_capture.html]
support-files = ../captureStream_common.js
# Even though we use ../ here, in the test HTML, we need to omit this. Sub-CWD relative

View File

@ -0,0 +1,54 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset='UTF-8'>
<script src='/tests/SimpleTest/SimpleTest.js'></script>
<link rel='stylesheet' href='/tests/SimpleTest/test.css'>
</head>
<title>WebGL test: Framebuffer maximum size test. (Bug 1290333)</title>
<body>
<script>
function TestSize(contextName, testSize) {
var attributes = {
antialias: false,
};
var canvas = document.createElement('canvas');
var gl = canvas.getContext(contextName, attributes);
if (!gl) {
todo(false, contextName + 'is unavailable.');
return;
}
gl.canvas.width = testSize;
gl.canvas.height = testSize;
ok(true, contextName + 'test complete.');
}
function run() {
TestSize('webgl', 16384);
TestSize('webgl2', 16384);
ok(true, 'Test complete.');
SimpleTest.finish();
}
////////////////////////////////////////
SimpleTest.waitForExplicitFinish();
try {
var prefPairList = [
['webgl.force-enabled', true],
];
var prefEnv = {'set': prefPairList};
SpecialPowers.pushPrefEnv(prefEnv, run);
} catch (e) {
warning('No SpecialPowers, but trying WebGL2 anyway...');
run();
}
</script>
</body>
</html>

View File

@ -449,8 +449,12 @@ DataTransfer::SetData(const nsAString& aFormat, const nsAString& aData,
}
void
DataTransfer::ClearData(const Optional<nsAString>& aFormat, ErrorResult& aRv)
DataTransfer::ClearData(const Optional<nsAString>& aFormat,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
ErrorResult& aRv)
{
MOZ_ASSERT(aSubjectPrincipal.isSome());
if (mReadOnly) {
aRv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
return;
@ -461,9 +465,9 @@ DataTransfer::ClearData(const Optional<nsAString>& aFormat, ErrorResult& aRv)
}
if (aFormat.WasPassed()) {
MozClearDataAtHelper(aFormat.Value(), 0, aRv);
MozClearDataAtHelper(aFormat.Value(), 0, aSubjectPrincipal, aRv);
} else {
MozClearDataAtHelper(EmptyString(), 0, aRv);
MozClearDataAtHelper(EmptyString(), 0, aSubjectPrincipal, aRv);
}
}
@ -473,7 +477,7 @@ DataTransfer::ClearData(const nsAString& aFormat)
Optional<nsAString> format;
format = &aFormat;
ErrorResult rv;
ClearData(format, rv);
ClearData(format, Some(nsContentUtils::SubjectPrincipal()), rv);
return rv.StealNSResult();
}
@ -743,8 +747,11 @@ DataTransfer::MozSetDataAt(JSContext* aCx, const nsAString& aFormat,
void
DataTransfer::MozClearDataAt(const nsAString& aFormat, uint32_t aIndex,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
ErrorResult& aRv)
{
MOZ_ASSERT(aSubjectPrincipal.isSome());
if (mReadOnly) {
aRv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
return;
@ -763,7 +770,7 @@ DataTransfer::MozClearDataAt(const nsAString& aFormat, uint32_t aIndex,
return;
}
MozClearDataAtHelper(aFormat, aIndex, aRv);
MozClearDataAtHelper(aFormat, aIndex, aSubjectPrincipal, aRv);
// If we just cleared the 0-th index, and there are still more than 1 indexes
// remaining, MozClearDataAt should cause the 1st index to become the 0th
@ -779,6 +786,7 @@ DataTransfer::MozClearDataAt(const nsAString& aFormat, uint32_t aIndex,
void
DataTransfer::MozClearDataAtHelper(const nsAString& aFormat, uint32_t aIndex,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
ErrorResult& aRv)
{
MOZ_ASSERT(!mReadOnly);
@ -786,18 +794,19 @@ DataTransfer::MozClearDataAtHelper(const nsAString& aFormat, uint32_t aIndex,
MOZ_ASSERT(aIndex == 0 ||
(mEventMessage != eCut && mEventMessage != eCopy &&
mEventMessage != ePaste));
MOZ_ASSERT(aSubjectPrincipal.isSome());
nsAutoString format;
GetRealFormat(aFormat, format);
mItems->MozRemoveByTypeAt(format, aIndex, aRv);
mItems->MozRemoveByTypeAt(format, aIndex, aSubjectPrincipal, aRv);
}
NS_IMETHODIMP
DataTransfer::MozClearDataAt(const nsAString& aFormat, uint32_t aIndex)
{
ErrorResult rv;
MozClearDataAt(aFormat, aIndex, rv);
MozClearDataAt(aFormat, aIndex, Some(nsContentUtils::SubjectPrincipal()), rv);
return rv.StealNSResult();
}

View File

@ -144,6 +144,7 @@ public:
ErrorResult& aRv);
void ClearData(const mozilla::dom::Optional<nsAString>& aFormat,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
mozilla::ErrorResult& aRv);
already_AddRefed<FileList> GetFiles(mozilla::ErrorResult& aRv);
@ -170,6 +171,7 @@ public:
mozilla::ErrorResult& aRv) const;
void MozClearDataAt(const nsAString& aFormat, uint32_t aIndex,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
mozilla::ErrorResult& aRv);
void MozSetDataAt(JSContext* aCx, const nsAString& aFormat,
@ -307,6 +309,7 @@ protected:
nsIPrincipal* aPrincipal);
void MozClearDataAtHelper(const nsAString& aFormat, uint32_t aIndex,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
mozilla::ErrorResult& aRv);
nsCOMPtr<nsISupports> mParent;

Some files were not shown because too many files have changed in this diff Show More