mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-31 14:15:30 +00:00
Merge mozilla-central to fx-team
This commit is contained in:
commit
dc6ea2267a
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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@
|
||||
|
@ -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
|
||||
|
@ -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++) {
|
||||
|
@ -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
|
||||
|
@ -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() {
|
||||
|
@ -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,
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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()
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
5
config/external/ffi/moz.build
vendored
5
config/external/ffi/moz.build
vendored
@ -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':
|
||||
|
5
config/external/sqlite/Makefile.in
vendored
5
config/external/sqlite/Makefile.in
vendored
@ -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
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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 + " : " +
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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()
|
||||
{
|
||||
|
@ -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);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -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%)");
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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() {
|
||||
|
@ -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];
|
||||
|
@ -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");
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
|
@ -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";
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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* () {
|
||||
|
@ -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",
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -21,7 +21,7 @@ const TEST_CASES = [
|
||||
},
|
||||
{
|
||||
input: '(new DOMParser()).parseFromString("<svg></svg>", "image/svg+xml")',
|
||||
output: "SVGDocument",
|
||||
output: "XMLDocument",
|
||||
inspectable: true,
|
||||
},
|
||||
];
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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(),
|
||||
}]));
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -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() {
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
617
dom/base/MutableBlobStorage.cpp
Normal file
617
dom/base/MutableBlobStorage.cpp
Normal 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
|
98
dom/base/MutableBlobStorage.h
Normal file
98
dom/base/MutableBlobStorage.h
Normal 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
|
@ -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)
|
||||
|
@ -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();
|
||||
|
@ -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)
|
||||
|
@ -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',
|
||||
|
@ -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()) {
|
||||
|
@ -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)
|
||||
|
@ -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.
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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")
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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)) &&
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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());
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
54
dom/canvas/test/webgl-mochitest/test_canvas_size.html
Normal file
54
dom/canvas/test/webgl-mochitest/test_canvas_size.html
Normal 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>
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user