зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to b2g-inbound.
This commit is contained in:
Коммит
3dbc65929d
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include "AccessibleWrap.h"
|
||||
#include "IUnknownImpl.h"
|
||||
#include "nsIURI.h"
|
||||
|
||||
using namespace mozilla::a11y;
|
||||
|
||||
|
|
|
@ -196,7 +196,6 @@
|
|||
@BINPATH@/components/dom_offline.xpt
|
||||
@BINPATH@/components/dom_payment.xpt
|
||||
@BINPATH@/components/dom_json.xpt
|
||||
@BINPATH@/components/dom_browserelement.xpt
|
||||
@BINPATH@/components/dom_messages.xpt
|
||||
@BINPATH@/components/dom_power.xpt
|
||||
@BINPATH@/components/dom_quota.xpt
|
||||
|
|
|
@ -714,3 +714,18 @@ chatbox:-moz-full-screen-ancestor > .chat-titlebar {
|
|||
*:-moz-full-screen-ancestor #social-sidebar-box:not(:-moz-full-screen-ancestor) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Combobox dropdown renderer */
|
||||
#ContentSelectDropdown {
|
||||
max-height: 400px;
|
||||
}
|
||||
|
||||
.contentSelectDropdown-optgroup {
|
||||
font-weight: bold;
|
||||
/* color: menutext used to overwrite the disabled color */
|
||||
color: menutext;
|
||||
}
|
||||
|
||||
.contentSelectDropdown-ingroup {
|
||||
-moz-margin-start: 2em;
|
||||
}
|
||||
|
|
|
@ -125,6 +125,9 @@
|
|||
<!-- for url bar autocomplete -->
|
||||
<panel type="autocomplete-richlistbox" id="PopupAutoCompleteRichResult" noautofocus="true" hidden="true"/>
|
||||
|
||||
<!-- for select dropdowns -->
|
||||
<menupopup id="ContentSelectDropdown" rolluponmousewheel="true" hidden="true"/>
|
||||
|
||||
<!-- for invalid form error message -->
|
||||
<panel id="invalid-form-popup" type="arrow" orient="vertical" noautofocus="true" hidden="true" level="parent">
|
||||
<description/>
|
||||
|
@ -1025,7 +1028,8 @@
|
|||
flex="1" contenttooltip="aHTMLTooltip"
|
||||
tabcontainer="tabbrowser-tabs"
|
||||
contentcontextmenu="contentAreaContextMenu"
|
||||
autocompletepopup="PopupAutoComplete"/>
|
||||
autocompletepopup="PopupAutoComplete"
|
||||
selectpopup="ContentSelectDropdown"/>
|
||||
<chatbar id="pinnedchats" layer="true" mousethrough="always" hidden="true"/>
|
||||
<statuspanel id="statusbar-display" inactive="true"/>
|
||||
</vbox>
|
||||
|
|
|
@ -48,6 +48,7 @@ if (Services.prefs.getBoolPref("browser.tabs.remote")) {
|
|||
});
|
||||
addEventListener("DOMFormHasPassword", function(event) {
|
||||
InsecurePasswordUtils.checkForInsecurePasswords(event.target);
|
||||
LoginManagerContent.onFormPassword(event);
|
||||
});
|
||||
addEventListener("DOMAutoComplete", function(event) {
|
||||
LoginManagerContent.onUsernameInput(event);
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
<xul:vbox flex="1" class="browserContainer">
|
||||
<xul:stack flex="1" class="browserStack" anonid="browserStack">
|
||||
<xul:browser anonid="initialBrowser" type="content-primary" message="true" disablehistory="true"
|
||||
xbl:inherits="tooltip=contenttooltip,contextmenu=contentcontextmenu,autocompletepopup"/>
|
||||
xbl:inherits="tooltip=contenttooltip,contextmenu=contentcontextmenu,autocompletepopup,selectpopup"/>
|
||||
</xul:stack>
|
||||
</xul:vbox>
|
||||
</xul:hbox>
|
||||
|
@ -1473,6 +1473,10 @@
|
|||
|
||||
if (this.hasAttribute("autocompletepopup"))
|
||||
b.setAttribute("autocompletepopup", this.getAttribute("autocompletepopup"));
|
||||
|
||||
if (this.hasAttribute("selectpopup"))
|
||||
b.setAttribute("selectpopup", this.getAttribute("selectpopup"));
|
||||
|
||||
b.setAttribute("autoscrollpopup", this._autoScrollPopup.id);
|
||||
|
||||
// Create the browserStack container
|
||||
|
|
|
@ -543,7 +543,7 @@ BrowserGlue.prototype = {
|
|||
label: win.gNavigatorBundle.getString("slowStartup.helpButton.label"),
|
||||
accessKey: win.gNavigatorBundle.getString("slowStartup.helpButton.accesskey"),
|
||||
callback: function () {
|
||||
win.openUILinkIn("https://support.mozilla.org/kb/firefox-takes-long-time-start-up", "tab");
|
||||
win.openUILinkIn("https://support.mozilla.org/kb/reset-firefox-easily-fix-most-problems", "tab");
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -1733,16 +1733,21 @@ ContentPermissionPrompt.prototype = {
|
|||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentPermissionPrompt]),
|
||||
|
||||
_getChromeWindow: function CPP_getChromeWindow(aWindow) {
|
||||
var chromeWin = aWindow
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShellTreeItem)
|
||||
.rootTreeItem
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindow)
|
||||
.QueryInterface(Ci.nsIDOMChromeWindow);
|
||||
return chromeWin;
|
||||
_getBrowserForRequest: function (aRequest) {
|
||||
var browser;
|
||||
try {
|
||||
// "element" is only defined in e10s mode, otherwise it throws.
|
||||
browser = aRequest.element;
|
||||
} catch (e) {}
|
||||
if (!browser) {
|
||||
var requestingWindow = aRequest.window.top;
|
||||
// find the requesting browser or iframe
|
||||
browser = requestingWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShell)
|
||||
.chromeEventHandler;
|
||||
}
|
||||
return browser;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -1767,19 +1772,7 @@ ContentPermissionPrompt.prototype = {
|
|||
|
||||
var browserBundle = Services.strings.createBundle("chrome://browser/locale/browser.properties");
|
||||
|
||||
var browser;
|
||||
try {
|
||||
// "element" is only defined in e10s mode, otherwise it throws.
|
||||
browser = aRequest.element;
|
||||
} catch (e) {}
|
||||
if (!browser) {
|
||||
var requestingWindow = aRequest.window.top;
|
||||
// find the requesting browser or iframe
|
||||
browser = requestingWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShell)
|
||||
.chromeEventHandler;
|
||||
}
|
||||
var browser = this._getBrowserForRequest(aRequest);
|
||||
var chromeWin = browser.ownerDocument.defaultView;
|
||||
var requestPrincipal = aRequest.principal;
|
||||
|
||||
|
@ -1896,8 +1889,7 @@ ContentPermissionPrompt.prototype = {
|
|||
});
|
||||
}
|
||||
|
||||
var requestingWindow = aRequest.window.top;
|
||||
var chromeWin = this._getChromeWindow(requestingWindow).wrappedJSObject;
|
||||
var chromeWin = this._getBrowserForRequest(aRequest).ownerDocument.defaultView;
|
||||
var link = chromeWin.document.getElementById("geolocation-learnmore-link");
|
||||
link.value = browserBundle.GetStringFromName("geolocation.learnMore");
|
||||
link.href = Services.urlFormatter.formatURLPref("browser.geolocation.warning.infoURL");
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
. "$topsrcdir/browser/config/mozconfigs/win64/common-opt"
|
||||
|
||||
mk_add_options MOZ_PGO=1
|
||||
|
||||
ac_add_options --enable-official-branding
|
||||
|
||||
. "$topsrcdir/build/mozconfig.common.override"
|
|
@ -0,0 +1,20 @@
|
|||
# This file is sourced by the nightly, beta, and release mozconfigs.
|
||||
|
||||
. "$topsrcdir/browser/config/mozconfigs/common"
|
||||
|
||||
ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
|
||||
ac_add_options --enable-update-packaging
|
||||
ac_add_options --enable-jemalloc
|
||||
ac_add_options --with-google-api-keyfile=/e/builds/gapi.data
|
||||
|
||||
# Needed to enable breakpad in application.ini
|
||||
export MOZILLA_OFFICIAL=1
|
||||
|
||||
export MOZ_TELEMETRY_REPORTING=1
|
||||
|
||||
if test -z "${_PYMAKE}"; then
|
||||
mk_add_options MOZ_MAKE_FLAGS=-j1
|
||||
fi
|
||||
|
||||
# Package js shell.
|
||||
export MOZ_PACKAGE_JSSHELL=1
|
|
@ -0,0 +1,5 @@
|
|||
# This file is used by all Win64 builds
|
||||
|
||||
ac_add_options --target=x86_64-pc-mingw32
|
||||
ac_add_options --host=x86_64-pc-mingw32
|
||||
|
|
@ -1,11 +1,6 @@
|
|||
. "$topsrcdir/browser/config/mozconfigs/common"
|
||||
. "$topsrcdir/browser/config/mozconfigs/win64/common-win64"
|
||||
. "$topsrcdir/browser/config/mozconfigs/win64/common-opt"
|
||||
|
||||
ac_add_options --target=x86_64-pc-mingw32
|
||||
ac_add_options --host=x86_64-pc-mingw32
|
||||
|
||||
ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
|
||||
ac_add_options --enable-update-packaging
|
||||
ac_add_options --enable-jemalloc
|
||||
ac_add_options --enable-signmar
|
||||
ac_add_options --enable-profiling
|
||||
ac_add_options --enable-metro
|
||||
|
@ -13,18 +8,6 @@ ac_add_options --enable-metro
|
|||
# Nightlies only since this has a cost in performance
|
||||
ac_add_options --enable-js-diagnostics
|
||||
|
||||
# Needed to enable breakpad in application.ini
|
||||
export MOZILLA_OFFICIAL=1
|
||||
|
||||
export MOZ_TELEMETRY_REPORTING=1
|
||||
|
||||
if test -z "${_PYMAKE}"; then
|
||||
mk_add_options MOZ_MAKE_FLAGS=-j1
|
||||
fi
|
||||
|
||||
# Package js shell.
|
||||
export MOZ_PACKAGE_JSSHELL=1
|
||||
|
||||
. $topsrcdir/build/win64/mozconfig.vs2010
|
||||
|
||||
. "$topsrcdir/build/mozconfig.common.override"
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
# This make file should be identical to the beta mozconfig, apart from the
|
||||
# safeguard below
|
||||
. "$topsrcdir/browser/config/mozconfigs/win64/common-opt"
|
||||
|
||||
mk_add_options MOZ_PGO=1
|
||||
|
||||
ac_add_options --enable-official-branding
|
||||
|
||||
# safeguard against someone forgetting to re-set EARLY_BETA_OR_EARLIER in
|
||||
# defines.sh during the beta cycle
|
||||
export BUILDING_RELEASE=1
|
||||
|
||||
. "$topsrcdir/build/mozconfig.common.override"
|
|
@ -24,6 +24,7 @@ MOCHITEST_BROWSER_TESTS = \
|
|||
browser_dbg_cmd_blackbox.js \
|
||||
browser_dbg_cmd_break.js \
|
||||
browser_dbg_debuggerstatement.js \
|
||||
browser_dbg_listaddons.js \
|
||||
browser_dbg_listtabs-01.js \
|
||||
browser_dbg_listtabs-02.js \
|
||||
browser_dbg_tabactor-01.js \
|
||||
|
@ -130,6 +131,8 @@ MOCHITEST_BROWSER_PAGES = \
|
|||
testactors.js \
|
||||
browser_dbg_tab1.html \
|
||||
browser_dbg_tab2.html \
|
||||
browser_dbg_addon1.xpi \
|
||||
browser_dbg_addon2.xpi \
|
||||
browser_dbg_debuggerstatement.html \
|
||||
browser_dbg_stack.html \
|
||||
browser_dbg_script-switching.html \
|
||||
|
|
Двоичный файл не отображается.
Двоичный файл не отображается.
|
@ -0,0 +1,100 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Make sure the listAddons request works as specified.
|
||||
|
||||
var gAddon1 = null;
|
||||
var gAddon1Actor = null;
|
||||
|
||||
var gAddon2 = null;
|
||||
var gAddon2Actor = null;
|
||||
|
||||
var gClient = null;
|
||||
|
||||
function test()
|
||||
{
|
||||
let transport = DebuggerServer.connectPipe();
|
||||
gClient = new DebuggerClient(transport);
|
||||
gClient.connect(function (aType, aTraits) {
|
||||
is(aType, "browser", "Root actor should identify itself as a browser.");
|
||||
test_first_addon();
|
||||
})
|
||||
}
|
||||
|
||||
function test_first_addon()
|
||||
{
|
||||
let addonListChanged = false;
|
||||
gClient.addOneTimeListener("addonListChanged", function () {
|
||||
addonListChanged = true;
|
||||
});
|
||||
addAddon(ADDON1_URL, function(aAddon) {
|
||||
gAddon1 = aAddon;
|
||||
gClient.listAddons(function(aResponse) {
|
||||
for each (let addon in aResponse.addons) {
|
||||
if (addon.url == ADDON1_URL) {
|
||||
gAddon1Actor = addon.actor;
|
||||
}
|
||||
}
|
||||
ok(!addonListChanged, "Should not yet be notified that list of addons changed.");
|
||||
ok(gAddon1Actor, "Should find an addon actor for addon1.");
|
||||
test_second_addon();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function test_second_addon()
|
||||
{
|
||||
let addonListChanged = false;
|
||||
gClient.addOneTimeListener("addonListChanged", function () {
|
||||
addonListChanged = true;
|
||||
});
|
||||
addAddon(ADDON2_URL, function(aAddon) {
|
||||
gAddon2 = aAddon;
|
||||
gClient.listAddons(function(aResponse) {
|
||||
let foundAddon1 = false;
|
||||
for each (let addon in aResponse.addons) {
|
||||
if (addon.url == ADDON1_URL) {
|
||||
is(addon.actor, gAddon1Actor, "Addon1's actor shouldn't have changed.");
|
||||
foundAddon1 = true;
|
||||
}
|
||||
if (addon.url == ADDON2_URL) {
|
||||
gAddon2Actor = addon.actor;
|
||||
}
|
||||
}
|
||||
ok(addonListChanged, "Should be notified that list of addons changed.");
|
||||
ok(foundAddon1, "Should find an addon actor for addon1.");
|
||||
ok(gAddon2Actor, "Should find an actor for addon2.");
|
||||
test_remove_addon();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function test_remove_addon()
|
||||
{
|
||||
let addonListChanged = false;
|
||||
gClient.addOneTimeListener("addonListChanged", function () {
|
||||
addonListChanged = true;
|
||||
});
|
||||
removeAddon(gAddon1, function() {
|
||||
gClient.listAddons(function(aResponse) {
|
||||
let foundAddon1 = false;
|
||||
for each (let addon in aResponse.addons) {
|
||||
if (addon.url == ADDON1_URL) {
|
||||
foundAddon1 = true;
|
||||
}
|
||||
}
|
||||
ok(addonListChanged, "Should be notified that list of addons changed.");
|
||||
ok(!foundAddon1, "Addon1 should be gone");
|
||||
finish_test();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function finish_test()
|
||||
{
|
||||
removeAddon(gAddon2, function() {
|
||||
gClient.close(function() {
|
||||
finish();
|
||||
});
|
||||
});
|
||||
}
|
|
@ -12,17 +12,19 @@ let Services = tempScope.Services;
|
|||
// Disable logging for faster test runs. Set this pref to true if you want to
|
||||
// debug a test in your try runs.
|
||||
let gEnableLogging = Services.prefs.getBoolPref("devtools.debugger.log");
|
||||
Services.prefs.setBoolPref("devtools.debugger.log", true);
|
||||
Services.prefs.setBoolPref("devtools.debugger.log", false);
|
||||
|
||||
Cu.import("resource://gre/modules/devtools/dbg-server.jsm", tempScope);
|
||||
Cu.import("resource://gre/modules/devtools/dbg-client.jsm", tempScope);
|
||||
Cu.import("resource:///modules/source-editor.jsm", tempScope);
|
||||
Cu.import("resource:///modules/devtools/gDevTools.jsm", tempScope);
|
||||
Cu.import("resource://gre/modules/devtools/Loader.jsm", tempScope);
|
||||
Cu.import("resource://gre/modules/AddonManager.jsm", tempScope);
|
||||
let SourceEditor = tempScope.SourceEditor;
|
||||
let DebuggerServer = tempScope.DebuggerServer;
|
||||
let DebuggerTransport = tempScope.DebuggerTransport;
|
||||
let DebuggerClient = tempScope.DebuggerClient;
|
||||
let AddonManager = tempScope.AddonManager;
|
||||
let gDevTools = tempScope.gDevTools;
|
||||
let devtools = tempScope.devtools;
|
||||
let TargetFactory = devtools.TargetFactory;
|
||||
|
@ -34,6 +36,8 @@ Services.scriptloader.loadSubScript(testDir + "../../../commandline/test/helpers
|
|||
const EXAMPLE_URL = "http://example.com/browser/browser/devtools/debugger/test/";
|
||||
const TAB1_URL = EXAMPLE_URL + "browser_dbg_tab1.html";
|
||||
const TAB2_URL = EXAMPLE_URL + "browser_dbg_tab2.html";
|
||||
const ADDON1_URL = EXAMPLE_URL + "browser_dbg_addon1.xpi";
|
||||
const ADDON2_URL = EXAMPLE_URL + "browser_dbg_addon2.xpi";
|
||||
const STACK_URL = EXAMPLE_URL + "browser_dbg_stack.html";
|
||||
|
||||
// Enable remote debugging for the relevant tests.
|
||||
|
@ -106,6 +110,32 @@ function removeTab(aTab, aWindow) {
|
|||
targetBrowser.removeTab(aTab);
|
||||
}
|
||||
|
||||
function addAddon(aURL, aOnInstallEnded) {
|
||||
AddonManager.getInstallForURL(aURL, function(aInstall) {
|
||||
aInstall.install();
|
||||
var listener = {
|
||||
onInstallEnded: function(aAddon, aAddonInstall) {
|
||||
aInstall.removeListener(listener);
|
||||
aOnInstallEnded(aAddonInstall);
|
||||
}
|
||||
};
|
||||
aInstall.addListener(listener);
|
||||
}, "application/x-xpinstall");
|
||||
}
|
||||
|
||||
function removeAddon(aAddon, aOnUninstalled) {
|
||||
var listener = {
|
||||
onUninstalled: function(aUninstalledAddon) {
|
||||
if (aUninstalledAddon != aAddon)
|
||||
return;
|
||||
AddonManager.removeAddonListener(listener);
|
||||
aOnUninstalled();
|
||||
}
|
||||
};
|
||||
AddonManager.addAddonListener(listener);
|
||||
aAddon.uninstall();
|
||||
}
|
||||
|
||||
function closeDebuggerAndFinish(aRemoteFlag, aCallback, aWindow) {
|
||||
let debuggerClosed = false;
|
||||
let debuggerDisconnected = false;
|
||||
|
|
|
@ -203,7 +203,6 @@
|
|||
@BINPATH@/components/dom_indexeddb.xpt
|
||||
@BINPATH@/components/dom_offline.xpt
|
||||
@BINPATH@/components/dom_json.xpt
|
||||
@BINPATH@/components/dom_browserelement.xpt
|
||||
@BINPATH@/components/dom_power.xpt
|
||||
@BINPATH@/components/dom_quota.xpt
|
||||
@BINPATH@/components/dom_range.xpt
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
* 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/. */
|
||||
|
||||
Components.utils.import("resource:///modules/ContentUtil.jsm");
|
||||
|
||||
let Util = {
|
||||
/*
|
||||
* General purpose utilities
|
||||
|
@ -11,70 +13,12 @@ let Util = {
|
|||
return aWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
|
||||
},
|
||||
|
||||
// Recursively find all documents, including root document.
|
||||
getAllDocuments: function getAllDocuments(doc, resultSoFar) {
|
||||
resultSoFar = resultSoFar || [doc];
|
||||
if (!doc.defaultView)
|
||||
return resultSoFar;
|
||||
let frames = doc.defaultView.frames;
|
||||
if (!frames)
|
||||
return resultSoFar;
|
||||
|
||||
let i;
|
||||
let currentDoc;
|
||||
for (i = 0; i < frames.length; i++) {
|
||||
currentDoc = frames[i].document;
|
||||
resultSoFar.push(currentDoc);
|
||||
this.getAllDocuments(currentDoc, resultSoFar);
|
||||
}
|
||||
|
||||
return resultSoFar;
|
||||
},
|
||||
|
||||
// Put the Mozilla networking code into a state that will kick the
|
||||
// auto-connection process.
|
||||
forceOnline: function forceOnline() {
|
||||
Services.io.offline = false;
|
||||
},
|
||||
|
||||
// Pass several objects in and it will combine them all into the first object and return it.
|
||||
// NOTE: Deep copy is not supported
|
||||
extend: function extend() {
|
||||
// copy reference to target object
|
||||
let target = arguments[0] || {};
|
||||
let length = arguments.length;
|
||||
|
||||
if (length === 1) {
|
||||
return target;
|
||||
}
|
||||
|
||||
// Handle case when target is a string or something
|
||||
if (typeof target != "object" && typeof target != "function") {
|
||||
target = {};
|
||||
}
|
||||
|
||||
for (let i = 1; i < length; i++) {
|
||||
// Only deal with non-null/undefined values
|
||||
let options = arguments[i];
|
||||
if (options != null) {
|
||||
// Extend the base object
|
||||
for (let name in options) {
|
||||
let copy = options[name];
|
||||
|
||||
// Prevent never-ending loop
|
||||
if (target === copy)
|
||||
continue;
|
||||
|
||||
if (copy !== undefined)
|
||||
target[name] = copy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return the modified object
|
||||
return target;
|
||||
},
|
||||
|
||||
/*
|
||||
* Timing utilties
|
||||
*/
|
||||
|
@ -92,17 +36,6 @@ let Util = {
|
|||
* Console printing utilities
|
||||
*/
|
||||
|
||||
dumpf: function dumpf(str) {
|
||||
let args = arguments;
|
||||
let i = 1;
|
||||
dump(str.replace(/%s/g, function() {
|
||||
if (i >= args.length) {
|
||||
throw "dumps received too many placeholders and not enough arguments";
|
||||
}
|
||||
return args[i++].toString();
|
||||
}));
|
||||
},
|
||||
|
||||
// Like dump, but each arg is handled and there's an automatic newline
|
||||
dumpLn: function dumpLn() {
|
||||
for (let i = 0; i < arguments.length; i++)
|
||||
|
@ -110,30 +43,10 @@ let Util = {
|
|||
dump("\n");
|
||||
},
|
||||
|
||||
dumpElement: function dumpElement(aElement) {
|
||||
this.dumpLn(aElement.id);
|
||||
},
|
||||
|
||||
dumpElementTree: function dumpElementTree(aElement) {
|
||||
let node = aElement;
|
||||
while (node) {
|
||||
this.dumpLn("node:", node, "id:", node.id, "class:", node.classList);
|
||||
node = node.parentNode;
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
* Element utilities
|
||||
*/
|
||||
|
||||
highlightElement: function highlightElement(aElement) {
|
||||
if (aElement == null) {
|
||||
this.dumpLn("aElement is null");
|
||||
return;
|
||||
}
|
||||
aElement.style.border = "2px solid red";
|
||||
},
|
||||
|
||||
transitionElementVisibility: function(aNodes, aVisible) {
|
||||
// accept single node or a collection of nodes
|
||||
aNodes = aNodes.length ? aNodes : [aNodes];
|
||||
|
@ -161,24 +74,6 @@ let Util = {
|
|||
return defd.promise;
|
||||
},
|
||||
|
||||
getHrefForElement: function getHrefForElement(target) {
|
||||
let link = null;
|
||||
while (target) {
|
||||
if (target instanceof Ci.nsIDOMHTMLAnchorElement ||
|
||||
target instanceof Ci.nsIDOMHTMLAreaElement ||
|
||||
target instanceof Ci.nsIDOMHTMLLinkElement) {
|
||||
if (target.hasAttribute("href"))
|
||||
link = target;
|
||||
}
|
||||
target = target.parentNode;
|
||||
}
|
||||
|
||||
if (link && link.hasAttribute("href"))
|
||||
return link.href;
|
||||
else
|
||||
return null;
|
||||
},
|
||||
|
||||
isTextInput: function isTextInput(aElement) {
|
||||
return ((aElement instanceof Ci.nsIDOMHTMLInputElement &&
|
||||
aElement.mozIsTextField(false)) ||
|
||||
|
@ -308,16 +203,6 @@ let Util = {
|
|||
aURL.indexOf("chrome:") == 0);
|
||||
},
|
||||
|
||||
isOpenableScheme: function isShareableScheme(aProtocol) {
|
||||
let dontOpen = /^(mailto|javascript|news|snews)$/;
|
||||
return (aProtocol && !dontOpen.test(aProtocol));
|
||||
},
|
||||
|
||||
isShareableScheme: function isShareableScheme(aProtocol) {
|
||||
let dontShare = /^(chrome|about|file|javascript|resource)$/;
|
||||
return (aProtocol && !dontShare.test(aProtocol));
|
||||
},
|
||||
|
||||
// Don't display anything in the urlbar for these special URIs.
|
||||
isURLEmpty: function isURLEmpty(aURL) {
|
||||
return (!aURL ||
|
||||
|
@ -382,68 +267,6 @@ let Util = {
|
|||
return this.displayDPI = this.getWindowUtils(window).displayDPI;
|
||||
},
|
||||
|
||||
isPortrait: function isPortrait() {
|
||||
return (window.innerWidth <= window.innerHeight);
|
||||
},
|
||||
|
||||
LOCALE_DIR_RTL: -1,
|
||||
LOCALE_DIR_LTR: 1,
|
||||
get localeDir() {
|
||||
// determine browser dir first to know which direction to snap to
|
||||
let chromeReg = Cc["@mozilla.org/chrome/chrome-registry;1"].getService(Ci.nsIXULChromeRegistry);
|
||||
return chromeReg.isLocaleRTL("global") ? this.LOCALE_DIR_RTL : this.LOCALE_DIR_LTR;
|
||||
},
|
||||
|
||||
/*
|
||||
* Process utilities
|
||||
*/
|
||||
|
||||
isParentProcess: function isInParentProcess() {
|
||||
let appInfo = Cc["@mozilla.org/xre/app-info;1"];
|
||||
return (!appInfo || appInfo.getService(Ci.nsIXULRuntime).processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT);
|
||||
},
|
||||
|
||||
/*
|
||||
* Event utilities
|
||||
*/
|
||||
|
||||
modifierMaskFromEvent: function modifierMaskFromEvent(aEvent) {
|
||||
return (aEvent.altKey ? Ci.nsIDOMEvent.ALT_MASK : 0) |
|
||||
(aEvent.ctrlKey ? Ci.nsIDOMEvent.CONTROL_MASK : 0) |
|
||||
(aEvent.shiftKey ? Ci.nsIDOMEvent.SHIFT_MASK : 0) |
|
||||
(aEvent.metaKey ? Ci.nsIDOMEvent.META_MASK : 0);
|
||||
},
|
||||
|
||||
/*
|
||||
* Download utilities
|
||||
*/
|
||||
|
||||
insertDownload: function insertDownload(aSrcUri, aFile) {
|
||||
let dm = Cc["@mozilla.org/download-manager;1"].getService(Ci.nsIDownloadManager);
|
||||
let db = dm.DBConnection;
|
||||
|
||||
let stmt = db.createStatement(
|
||||
"INSERT INTO moz_downloads (name, source, target, startTime, endTime, state, referrer) " +
|
||||
"VALUES (:name, :source, :target, :startTime, :endTime, :state, :referrer)"
|
||||
);
|
||||
|
||||
stmt.params.name = aFile.leafName;
|
||||
stmt.params.source = aSrcUri.spec;
|
||||
stmt.params.target = aFile.path;
|
||||
stmt.params.startTime = Date.now() * 1000;
|
||||
stmt.params.endTime = Date.now() * 1000;
|
||||
stmt.params.state = Ci.nsIDownloadManager.DOWNLOAD_NOTSTARTED;
|
||||
stmt.params.referrer = aSrcUri.spec;
|
||||
|
||||
stmt.execute();
|
||||
stmt.finalize();
|
||||
|
||||
let newItemId = db.lastInsertRowID;
|
||||
let download = dm.getDownload(newItemId);
|
||||
//dm.resumeDownload(download);
|
||||
//Services.obs.notifyObservers(download, "dl-start", null);
|
||||
},
|
||||
|
||||
/*
|
||||
* Local system utilities
|
||||
*/
|
||||
|
@ -540,3 +363,11 @@ Util.Timeout.prototype = {
|
|||
}
|
||||
};
|
||||
|
||||
// Mixin the ContentUtil module exports
|
||||
{
|
||||
for (let name in ContentUtil) {
|
||||
let copy = ContentUtil[name];
|
||||
if (copy !== undefined)
|
||||
Util[name] = copy;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1096,14 +1096,6 @@ var BrowserUI = {
|
|||
case "cmd_panel":
|
||||
PanelUI.toggle();
|
||||
break;
|
||||
case "cmd_volumeLeft":
|
||||
// Zoom in (portrait) or out (landscape)
|
||||
Browser.zoom(Util.isPortrait() ? -1 : 1);
|
||||
break;
|
||||
case "cmd_volumeRight":
|
||||
// Zoom out (portrait) or in (landscape)
|
||||
Browser.zoom(Util.isPortrait() ? 1 : -1);
|
||||
break;
|
||||
case "cmd_openFile":
|
||||
this.openFile();
|
||||
break;
|
||||
|
|
|
@ -95,12 +95,6 @@
|
|||
<command id="cmd_sanitize" oncommand="CommandUpdater.doCommand(this.id);"/>
|
||||
<command id="cmd_contextUI" oncommand="CommandUpdater.doCommand(this.id);"/>
|
||||
|
||||
<!-- screen/display -->
|
||||
<command id="cmd_lockscreen" oncommand="CommandUpdater.doCommand(this.id);"/>
|
||||
|
||||
<command id="cmd_volumeLeft" observes="bcast_contentShowing" oncommand="CommandUpdater.doCommand(this.id);"/>
|
||||
<command id="cmd_volumeRight" observes="bcast_contentShowing" oncommand="CommandUpdater.doCommand(this.id);"/>
|
||||
|
||||
<!-- scrolling -->
|
||||
<command id="cmd_scrollPageUp" oncommand="CommandUpdater.doCommand(this.id);"/>
|
||||
<command id="cmd_scrollPageDown" oncommand="CommandUpdater.doCommand(this.id);"/>
|
||||
|
|
|
@ -140,6 +140,7 @@ let Content = {
|
|||
addEventListener("MozApplicationManifest", this, false);
|
||||
addEventListener("DOMContentLoaded", this, false);
|
||||
addEventListener("DOMAutoComplete", this, false);
|
||||
addEventListener("DOMFormHasPassword", this, false);
|
||||
addEventListener("blur", this, false);
|
||||
addEventListener("pagehide", this, false);
|
||||
// Attach a listener to watch for "click" events bubbling up from error
|
||||
|
@ -189,6 +190,10 @@ let Content = {
|
|||
this._onClickCapture(aEvent);
|
||||
break;
|
||||
|
||||
case "DOMFormHasPassword":
|
||||
LoginManagerContent.onFormPassword(aEvent);
|
||||
break;
|
||||
|
||||
case "DOMContentLoaded":
|
||||
LoginManagerContent.onContentLoaded(aEvent);
|
||||
this._maybeNotifyErrorPage();
|
||||
|
|
|
@ -140,13 +140,13 @@ var FindHelperUI = {
|
|||
this._container.removeEventListener("transitionend", onTransitionEnd, true);
|
||||
this._textbox.value = "";
|
||||
this.status = null;
|
||||
this._textbox.blur();
|
||||
this._open = false;
|
||||
|
||||
// Restore the scroll synchronisation
|
||||
Browser.selectedBrowser.scrollSync = true;
|
||||
};
|
||||
|
||||
this._textbox.blur();
|
||||
this._container.addEventListener("transitionend", onTransitionEnd, true);
|
||||
this._container.dismiss();
|
||||
Elements.browsers.removeAttribute("findbar");
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0"?>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" xml:lang="en">
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
|
@ -1,10 +1,10 @@
|
|||
"use strict";
|
||||
|
||||
load('Util.js');
|
||||
load("Util.js");
|
||||
|
||||
function run_test() {
|
||||
do_print("Testing Util.extend");
|
||||
|
||||
|
||||
do_print("Check if function is defined");
|
||||
do_check_true(!!Util.extend);
|
||||
|
||||
|
@ -14,7 +14,7 @@ function run_test() {
|
|||
|
||||
let nullRes = Util.extend(null);
|
||||
do_check_true(nullRes && typeof nullRes == "object");
|
||||
|
||||
|
||||
do_print("Simple extend");
|
||||
let simpleExtend = {a: 1, b: 2};
|
||||
let simpleExtendResult = Util.extend(simpleExtend, {b: 3, c: 4});
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
// -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; js2-basic-offset: 2; js2-skip-preprocessor-directives: t; -*-
|
||||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
let Cu = Components.utils;
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource:///modules/ContentUtil.jsm");
|
||||
load("Util.js");
|
||||
|
||||
function empty_node(node) {
|
||||
let cnode;
|
||||
while((cnode = node.firstChild))
|
||||
node.removeChild(cnode);
|
||||
return node;
|
||||
}
|
||||
|
||||
function DOMSerializer() {
|
||||
return Components.classes["@mozilla.org/xmlextras/xmlserializer;1"]
|
||||
.createInstance(Components.interfaces.nsIDOMSerializer);
|
||||
}
|
||||
|
||||
function serializeContents(node) {
|
||||
let str = DOMSerializer().serializeToString(node);
|
||||
return str.replace(/^<[^>]+>/, '')
|
||||
.replace(/<\/[^>]+>$/, '');
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
let doc, body, str, expectedResult, frag;
|
||||
|
||||
do_print("Testing Util.populateFragmentFromString");
|
||||
|
||||
do_check_true(!!Util.populateFragmentFromString);
|
||||
do_check_true(!!ContentUtil.populateFragmentFromString);
|
||||
do_check_eq(ContentUtil.populateFragmentFromString, Util.populateFragmentFromString);
|
||||
|
||||
do_print("Loading blank document");
|
||||
doc = do_parse_document("blank.xhtml", "application/xhtml+xml");
|
||||
|
||||
// sanity check
|
||||
do_check_eq(doc.nodeType, 9);
|
||||
do_check_true(doc.documentElement.localName != "parsererror");
|
||||
|
||||
body = doc.documentElement.getElementsByTagName("body")[0];
|
||||
do_check_eq(1, body.nodeType);
|
||||
|
||||
frag = doc.createDocumentFragment();
|
||||
|
||||
// test proper handling of leading and trailing text
|
||||
str = "Before, #2, #1. After";
|
||||
Util.populateFragmentFromString(
|
||||
frag, str,
|
||||
{ text: "One", className: "text-one"},
|
||||
{ text: "Two", className: "text-two"}
|
||||
);
|
||||
|
||||
empty_node(body);
|
||||
body.appendChild(frag);
|
||||
|
||||
expectedResult = 'Before, <span class="text-two">Two</span>, <span class="text-one">One</span>. After';
|
||||
do_check_eq(serializeContents(body), expectedResult);
|
||||
|
||||
// test proper handling of unspecified markers
|
||||
str = "#8080: #1. http://localhost/#bar";
|
||||
Util.populateFragmentFromString(
|
||||
frag, str,
|
||||
{ text: "One" }
|
||||
);
|
||||
|
||||
empty_node(body);
|
||||
body.appendChild(frag);
|
||||
|
||||
expectedResult = '#8080: <span>One</span>. http://localhost/#bar';
|
||||
do_check_eq(serializeContents(body), expectedResult);
|
||||
|
||||
// test proper handling of markup in strings
|
||||
str = "#1 <body> tag. © 2000 - Some Corp\u2122";
|
||||
Util.populateFragmentFromString(
|
||||
frag, str,
|
||||
{ text: "About the" }
|
||||
);
|
||||
|
||||
empty_node(body);
|
||||
body.appendChild(frag);
|
||||
expectedResult = "<span>About the</span> <body> tag. &copy; 2000 - Some Corp™"
|
||||
do_check_eq(serializeContents(body), expectedResult);
|
||||
}
|
|
@ -1,5 +1,8 @@
|
|||
[DEFAULT]
|
||||
head =
|
||||
head =
|
||||
tail =
|
||||
firefox-appdir = metro
|
||||
|
||||
[test_util_extend.js]
|
||||
[test_util_populateFragmentFromString.js]
|
||||
|
||||
|
|
|
@ -14,6 +14,11 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
|||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/DownloadUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "ContentUtil", function() {
|
||||
Cu.import("resource:///modules/ContentUtil.jsm");
|
||||
return ContentUtil;
|
||||
});
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// HelperApp Launcher Dialog
|
||||
// -----------------------------------------------------------------------
|
||||
|
@ -97,19 +102,35 @@ HelperAppLauncherDialog.prototype = {
|
|||
let window = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
let chromeWin = this._getChromeWindow(window).wrappedJSObject;
|
||||
let notificationBox = chromeWin.Browser.getNotificationBox();
|
||||
let document = notificationBox.ownerDocument;
|
||||
downloadSize = this._getDownloadSize(aLauncher.contentLength);
|
||||
|
||||
let msg = browserBundle.GetStringFromName("alertDownloadSave")
|
||||
.replace("#1", aLauncher.suggestedFileName)
|
||||
.replace("#2", downloadSize)
|
||||
.replace("#3", aLauncher.source.host);
|
||||
let msg = browserBundle.GetStringFromName("alertDownloadSave");
|
||||
|
||||
let fragment = ContentUtil.populateFragmentFromString(
|
||||
document.createDocumentFragment(),
|
||||
msg,
|
||||
{
|
||||
text: aLauncher.suggestedFileName,
|
||||
className: "download-filename-text"
|
||||
},
|
||||
{
|
||||
text: aLauncher.suggestedFileName,
|
||||
className: "download-size-text"
|
||||
},
|
||||
{
|
||||
text: aLauncher.source.host,
|
||||
className: "download-host-text"
|
||||
}
|
||||
);
|
||||
notificationBox.notificationsHidden = false;
|
||||
let newBar = notificationBox.appendNotification(msg,
|
||||
let newBar = notificationBox.appendNotification("",
|
||||
"save-download",
|
||||
URI_GENERIC_ICON_DOWNLOAD,
|
||||
notificationBox.PRIORITY_WARNING_HIGH,
|
||||
buttons);
|
||||
let messageContainer = document.getAnonymousElementByAttribute(newBar, "anonid", "messageText");
|
||||
messageContainer.appendChild(fragment);
|
||||
},
|
||||
|
||||
promptForSaveToFile: function hald_promptForSaveToFile(aLauncher, aContext, aDefaultFile, aSuggestedFileExt, aForcePrompt) {
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
/* 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/. */
|
||||
"use strict";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["ContentUtil"];
|
||||
|
||||
const XHTML_NS = "http://www.w3.org/1999/xhtml";
|
||||
|
||||
this.ContentUtil = {
|
||||
populateFragmentFromString: function populateFragmentFromString(fragment, str) {
|
||||
let re = /^([^#]*)#(\d+)\b([^#]*)/,
|
||||
document = fragment.ownerDocument,
|
||||
// the remaining arguments are our {text, className} values
|
||||
replacements = Array.slice(arguments, 2),
|
||||
match;
|
||||
|
||||
// walk over the string, building textNode/spans as nec. with replacement content
|
||||
// note that #1,#2 etc. may not appear in numerical order in the string
|
||||
while ((match = re.exec(str))) {
|
||||
let [mstring,pre,num,post] = match,
|
||||
replaceText = "",
|
||||
replaceClass,
|
||||
idx = num-1; // markers are 1-based, replacement indices 0 based
|
||||
|
||||
str = str.substring(re.lastIndex+mstring.length);
|
||||
|
||||
if (pre)
|
||||
fragment.appendChild(document.createTextNode(pre));
|
||||
|
||||
if (replacements[idx]) {
|
||||
replaceText = replacements[idx].text;
|
||||
let spanNode = document.createElementNS(XHTML_NS, "span");
|
||||
spanNode.appendChild(document.createTextNode(replaceText));
|
||||
// add class to the span when provided
|
||||
if(replacements[idx].className)
|
||||
spanNode.classList.add(replacements[idx].className);
|
||||
|
||||
fragment.appendChild(spanNode);
|
||||
} else {
|
||||
// put it back if no replacement was provided
|
||||
fragment.appendChild(document.createTextNode("#"+num));
|
||||
}
|
||||
|
||||
if(post)
|
||||
fragment.appendChild(document.createTextNode(post));
|
||||
}
|
||||
if(str)
|
||||
fragment.appendChild(document.createTextNode(str));
|
||||
|
||||
return fragment;
|
||||
},
|
||||
|
||||
// Pass several objects in and it will combine them all into the first object and return it.
|
||||
// NOTE: Deep copy is not supported
|
||||
extend: function extend() {
|
||||
// copy reference to target object
|
||||
let target = arguments[0] || {};
|
||||
let length = arguments.length;
|
||||
|
||||
if (length === 1) {
|
||||
return target;
|
||||
}
|
||||
|
||||
// Handle case when target is a string or something
|
||||
if (typeof target != "object" && typeof target != "function") {
|
||||
target = {};
|
||||
}
|
||||
|
||||
for (let i = 1; i < length; i++) {
|
||||
// Only deal with non-null/undefined values
|
||||
let options = arguments[i];
|
||||
if (options != null) {
|
||||
// Extend the base object
|
||||
for (let name in options) {
|
||||
let copy = options[name];
|
||||
|
||||
// Prevent never-ending loop
|
||||
if (target === copy)
|
||||
continue;
|
||||
|
||||
if (copy !== undefined)
|
||||
target[name] = copy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return the modified object
|
||||
return target;
|
||||
}
|
||||
|
||||
};
|
|
@ -5,6 +5,7 @@
|
|||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
'ContentUtil.jsm',
|
||||
'CrossSlide.jsm',
|
||||
'View.jsm',
|
||||
'colorUtils.jsm',
|
||||
|
|
|
@ -696,7 +696,7 @@ documenttab[selected] .documenttab-selection {
|
|||
}
|
||||
|
||||
/* navbar edit button: one button out of three - when editing: go, when !editing,
|
||||
loading: stop, when !editing, !loading: reload */
|
||||
loading: stop, when !editing, !loading: reload */
|
||||
|
||||
#go-button, #reload-button, #stop-button {
|
||||
visibility: collapse;
|
||||
|
@ -1006,6 +1006,15 @@ documenttab[selected] .documenttab-selection {
|
|||
-moz-image-region: rect(80px, 560px, 120px, 520px) !important;
|
||||
}
|
||||
|
||||
/* Download notifications ======================================================= */
|
||||
|
||||
.download-filename-text {
|
||||
font-weight: bold;
|
||||
}
|
||||
.download-host-text {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* Autoscroll popup ======================================================== */
|
||||
|
||||
.autoscroller {
|
||||
|
|
|
@ -37,7 +37,11 @@
|
|||
transition: opacity .15s ease 0s;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-checkbox > .checkbox-check {
|
||||
.side-menu-widget-item-checkbox > .checkbox-spacer-box {
|
||||
-moz-appearance: none;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-checkbox > .checkbox-spacer-box > .checkbox-check {
|
||||
-moz-appearance: none;
|
||||
background: none;
|
||||
background-image: url(itemToggle.png);
|
||||
|
@ -50,7 +54,7 @@
|
|||
border: 0;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-checkbox[checked] > .checkbox-check {
|
||||
.side-menu-widget-item-checkbox[checked] > .checkbox-spacer-box > .checkbox-check {
|
||||
background-position: 0 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ def InvokeClWithDependencyGeneration(cmdline):
|
|||
cl = subprocess.Popen(cmdline, stdout=subprocess.PIPE)
|
||||
|
||||
mk = Makefile()
|
||||
rule = mk.create_rule(target)
|
||||
rule = mk.create_rule([target])
|
||||
rule.add_dependencies([normcase(source)])
|
||||
for line in cl.stdout:
|
||||
# cl -showIncludes prefixes every header with "Note: including file:"
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "nsIContent.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsIURI.h"
|
||||
|
||||
//XXXtw sadly, this makes consumers of nsContentPolicyUtils depend on widget
|
||||
#include "nsIDocument.h"
|
||||
|
|
|
@ -96,7 +96,6 @@ struct JSContext;
|
|||
struct JSPropertyDescriptor;
|
||||
struct JSRuntime;
|
||||
struct nsIntMargin;
|
||||
struct nsNativeKeyEvent; // Don't include nsINativeKeyBindings.h here: it will force strange compilation error!
|
||||
|
||||
template<class E> class nsCOMArray;
|
||||
template<class E> class nsTArray;
|
||||
|
@ -1386,14 +1385,11 @@ public:
|
|||
static const nsDependentString GetLocalizedEllipsis();
|
||||
|
||||
/**
|
||||
* The routine GetNativeEvent is used to fill nsNativeKeyEvent.
|
||||
* It's also used in DOMEventToNativeKeyEvent.
|
||||
* See bug 406407 for details.
|
||||
* The routine GetNativeEvent returns the result of
|
||||
* aDOMEvent->GetInternalNSEvent().
|
||||
* XXX Is this necessary?
|
||||
*/
|
||||
static nsEvent* GetNativeEvent(nsIDOMEvent* aDOMEvent);
|
||||
static bool DOMEventToNativeKeyEvent(nsIDOMKeyEvent* aKeyEvent,
|
||||
nsNativeKeyEvent* aNativeEvent,
|
||||
bool aGetCharCode);
|
||||
|
||||
/**
|
||||
* Get the candidates for accelkeys for aDOMKeyEvent.
|
||||
|
|
|
@ -269,12 +269,7 @@ public:
|
|||
}
|
||||
return mDocumentBaseURI ? mDocumentBaseURI : mDocumentURI;
|
||||
}
|
||||
virtual already_AddRefed<nsIURI> GetBaseURI() const MOZ_OVERRIDE
|
||||
{
|
||||
nsCOMPtr<nsIURI> uri = GetDocBaseURI();
|
||||
|
||||
return uri.forget();
|
||||
}
|
||||
virtual already_AddRefed<nsIURI> GetBaseURI() const MOZ_OVERRIDE;
|
||||
|
||||
virtual nsresult SetBaseURI(nsIURI* aURI) = 0;
|
||||
|
||||
|
|
|
@ -111,27 +111,20 @@ Link::LinkState() const
|
|||
return nsEventStates();
|
||||
}
|
||||
|
||||
already_AddRefed<nsIURI>
|
||||
nsIURI*
|
||||
Link::GetURI() const
|
||||
{
|
||||
nsCOMPtr<nsIURI> uri(mCachedURI);
|
||||
|
||||
// If we have this URI cached, use it.
|
||||
if (uri) {
|
||||
return uri.forget();
|
||||
if (mCachedURI) {
|
||||
return mCachedURI;
|
||||
}
|
||||
|
||||
// Otherwise obtain it.
|
||||
Link *self = const_cast<Link *>(this);
|
||||
Element *element = self->mElement;
|
||||
uri = element->GetHrefURI();
|
||||
mCachedURI = element->GetHrefURI();
|
||||
|
||||
// We want to cache the URI if we have it
|
||||
if (uri) {
|
||||
mCachedURI = uri;
|
||||
}
|
||||
|
||||
return uri.forget();
|
||||
return mCachedURI;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -20,9 +20,9 @@ namespace dom {
|
|||
|
||||
class Element;
|
||||
|
||||
#define MOZILLA_DOM_LINK_IMPLEMENTATION_IID \
|
||||
{ 0x7EA57721, 0xE373, 0x458E, \
|
||||
{0x8F, 0x44, 0xF8, 0x96, 0x56, 0xB4, 0x14, 0xF5 } }
|
||||
#define MOZILLA_DOM_LINK_IMPLEMENTATION_IID \
|
||||
{ 0xb25edee6, 0xdd35, 0x4f8b, \
|
||||
{ 0xab, 0x90, 0x66, 0xd0, 0xbd, 0x3c, 0x22, 0xd5 } }
|
||||
|
||||
class Link : public nsISupports
|
||||
{
|
||||
|
@ -45,8 +45,8 @@ public:
|
|||
/**
|
||||
* @return the URI this link is for, if available.
|
||||
*/
|
||||
already_AddRefed<nsIURI> GetURI() const;
|
||||
virtual already_AddRefed<nsIURI> GetURIExternal() const {
|
||||
nsIURI* GetURI() const;
|
||||
virtual nsIURI* GetURIExternal() const {
|
||||
return GetURI();
|
||||
}
|
||||
|
||||
|
@ -111,11 +111,11 @@ protected:
|
|||
*/
|
||||
bool HasURI() const
|
||||
{
|
||||
if (mCachedURI)
|
||||
if (HasCachedURI()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> uri(GetURI());
|
||||
return !!uri;
|
||||
return !!GetURI();
|
||||
}
|
||||
|
||||
nsIURI* GetCachedURI() const { return mCachedURI; }
|
||||
|
|
|
@ -116,7 +116,6 @@
|
|||
#include "nsILoadGroup.h"
|
||||
#include "nsIMEStateManager.h"
|
||||
#include "nsIMIMEService.h"
|
||||
#include "nsINativeKeyBindings.h"
|
||||
#include "nsINode.h"
|
||||
#include "nsINodeInfo.h"
|
||||
#include "nsIObjectLoadingContent.h"
|
||||
|
@ -4551,39 +4550,6 @@ nsContentUtils::GetNativeEvent(nsIDOMEvent* aDOMEvent)
|
|||
return aDOMEvent ? aDOMEvent->GetInternalNSEvent() : nullptr;
|
||||
}
|
||||
|
||||
//static
|
||||
bool
|
||||
nsContentUtils::DOMEventToNativeKeyEvent(nsIDOMKeyEvent* aKeyEvent,
|
||||
nsNativeKeyEvent* aNativeEvent,
|
||||
bool aGetCharCode)
|
||||
{
|
||||
bool defaultPrevented;
|
||||
aKeyEvent->GetDefaultPrevented(&defaultPrevented);
|
||||
if (defaultPrevented)
|
||||
return false;
|
||||
|
||||
bool trusted = false;
|
||||
aKeyEvent->GetIsTrusted(&trusted);
|
||||
if (!trusted)
|
||||
return false;
|
||||
|
||||
if (aGetCharCode) {
|
||||
aKeyEvent->GetCharCode(&aNativeEvent->charCode);
|
||||
} else {
|
||||
aNativeEvent->charCode = 0;
|
||||
}
|
||||
aKeyEvent->GetKeyCode(&aNativeEvent->keyCode);
|
||||
aKeyEvent->GetAltKey(&aNativeEvent->altKey);
|
||||
aKeyEvent->GetCtrlKey(&aNativeEvent->ctrlKey);
|
||||
aKeyEvent->GetShiftKey(&aNativeEvent->shiftKey);
|
||||
aKeyEvent->GetMetaKey(&aNativeEvent->metaKey);
|
||||
|
||||
aNativeEvent->mGeckoEvent =
|
||||
static_cast<nsKeyEvent*>(GetNativeEvent(aKeyEvent));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
HasASCIIDigit(const nsTArray<nsShortcutCandidate>& aCandidates)
|
||||
{
|
||||
|
|
|
@ -3259,6 +3259,13 @@ nsIDocument::ReleaseCapture() const
|
|||
}
|
||||
}
|
||||
|
||||
already_AddRefed<nsIURI>
|
||||
nsIDocument::GetBaseURI() const
|
||||
{
|
||||
nsCOMPtr<nsIURI> uri = GetDocBaseURI();
|
||||
return uri.forget();
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDocument::SetBaseURI(nsIURI* aURI)
|
||||
{
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "imgIRequest.h"
|
||||
#include "nsEventStates.h"
|
||||
#include "nsEventDispatcher.h"
|
||||
#include "nsGUIEvent.h"
|
||||
|
||||
class nsGenConImageContent MOZ_FINAL : public nsXMLElement,
|
||||
public nsImageLoadingContent
|
||||
|
|
|
@ -5,7 +5,10 @@ content.document.title = "Hello, Kitty";
|
|||
(function start() {
|
||||
sync_test();
|
||||
async_test();
|
||||
sendAsyncMessage("cpows:done", {});
|
||||
// The sync-ness of this call is important, because otherwise
|
||||
// we tear down the child's document while we are
|
||||
// still in the async test in the parent.
|
||||
sendSyncMessage("cpows:done", {});
|
||||
}
|
||||
)();
|
||||
|
||||
|
|
|
@ -17,6 +17,11 @@
|
|||
return opener.wrappedJSObject.ok(condition, message);
|
||||
}
|
||||
|
||||
// Make sure that an error in this file actually causes the test to fail.
|
||||
window.onerror = function (msg, url, line) {
|
||||
ok(false, "Error while executing: \n" + msg + "\n" + url + ":" + line);
|
||||
};
|
||||
|
||||
function testCpowMessage(message) {
|
||||
ok(message.json.check == "ok", "correct json");
|
||||
|
||||
|
|
|
@ -21,7 +21,10 @@
|
|||
}
|
||||
|
||||
addLoadEvent(function() {
|
||||
window.open("cpows_parent.xul", "", "chrome");
|
||||
// We don't want to set browser.tabs.remote to true, but still have CPOWs enabled.
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.ipc.cpows.force-enabled", true]]}, function() {
|
||||
window.open("cpows_parent.xul", "", "chrome");
|
||||
});
|
||||
});
|
||||
]]></script>
|
||||
</window>
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#define _CANVASUTILS_H_
|
||||
|
||||
#include "mozilla/CheckedInt.h"
|
||||
#include "jsapi.h"
|
||||
|
||||
class nsIPrincipal;
|
||||
|
||||
|
|
|
@ -2596,7 +2596,7 @@ nsEventStateManager::ComputeScrollTarget(nsIFrame* aTargetFrame,
|
|||
return frameToScroll;
|
||||
}
|
||||
|
||||
nsPresContext::ScrollbarStyles ss = frameToScroll->GetScrollbarStyles();
|
||||
ScrollbarStyles ss = frameToScroll->GetScrollbarStyles();
|
||||
bool hiddenForV = (NS_STYLE_OVERFLOW_HIDDEN == ss.mVertical);
|
||||
bool hiddenForH = (NS_STYLE_OVERFLOW_HIDDEN == ss.mHorizontal);
|
||||
if ((hiddenForV && hiddenForH) ||
|
||||
|
@ -2705,8 +2705,7 @@ nsEventStateManager::DoScrollText(nsIScrollableFrame* aScrollableFrame,
|
|||
ComputeScrollAmountForDefaultAction(aEvent, scrollAmountInDevPixels);
|
||||
|
||||
// Don't scroll around the axis whose overflow style is hidden.
|
||||
nsPresContext::ScrollbarStyles overflowStyle =
|
||||
aScrollableFrame->GetScrollbarStyles();
|
||||
ScrollbarStyles overflowStyle = aScrollableFrame->GetScrollbarStyles();
|
||||
if (overflowStyle.mHorizontal == NS_STYLE_OVERFLOW_HIDDEN) {
|
||||
actualDevPixelScrollAmount.x = 0;
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "nsIDocument.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "nsIURI.h"
|
||||
|
||||
NS_IMPL_NS_NEW_HTML_ELEMENT(Anchor)
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "mozilla/dom/HTMLFieldSetElementBinding.h"
|
||||
#include "nsContentList.h"
|
||||
#include "nsEventDispatcher.h"
|
||||
#include "nsGUIEvent.h"
|
||||
|
||||
NS_IMPL_NS_NEW_HTML_ELEMENT(FieldSet)
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "nsRefPtrHashtable.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsAsyncDOMEvent.h"
|
||||
#include "jsfriendapi.h" // For js::ExpandoAndGeneration
|
||||
|
||||
class nsIMutableArray;
|
||||
class nsIURI;
|
||||
|
|
|
@ -1162,6 +1162,9 @@ HTMLInputElement::TabIndexDefault()
|
|||
uint32_t
|
||||
HTMLInputElement::Height()
|
||||
{
|
||||
if (mType != NS_FORM_INPUT_IMAGE) {
|
||||
return 0;
|
||||
}
|
||||
return GetWidthHeightForImage(mCurrentRequest).height;
|
||||
}
|
||||
|
||||
|
@ -1213,6 +1216,9 @@ HTMLInputElement::SetIndeterminate(bool aValue)
|
|||
uint32_t
|
||||
HTMLInputElement::Width()
|
||||
{
|
||||
if (mType != NS_FORM_INPUT_IMAGE) {
|
||||
return 0;
|
||||
}
|
||||
return GetWidthHeightForImage(mCurrentRequest).width;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
#include "mozilla/dom/HTMLLabelElementBinding.h"
|
||||
#include "nsEventDispatcher.h"
|
||||
#include "nsFocusManager.h"
|
||||
#include "nsGUIEvent.h"
|
||||
#include "nsIDOMMouseEvent.h"
|
||||
|
||||
// construction, destruction
|
||||
|
||||
|
|
|
@ -329,7 +329,8 @@ HTMLLinkElement::GetStyleSheetURL(bool* aIsInline)
|
|||
if (href.IsEmpty()) {
|
||||
return nullptr;
|
||||
}
|
||||
return Link::GetURI();
|
||||
nsCOMPtr<nsIURI> uri = Link::GetURI();
|
||||
return uri.forget();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -10,7 +10,9 @@
|
|||
#include "nsAttrValueInlines.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsEventDispatcher.h"
|
||||
#include "nsGUIEvent.h"
|
||||
#include "nsXULContextMenuBuilder.h"
|
||||
#include "nsIURI.h"
|
||||
|
||||
NS_IMPL_NS_NEW_HTML_ELEMENT(Menu)
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "nsAttrValueInlines.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsEventDispatcher.h"
|
||||
#include "nsGUIEvent.h"
|
||||
|
||||
|
||||
NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(MenuItem)
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "nsString.h"
|
||||
#include "nsWrapperCache.h"
|
||||
#include "nsGenericHTMLElement.h"
|
||||
#include "jsfriendapi.h" // For js::ExpandoAndGeneration
|
||||
|
||||
namespace mozilla {
|
||||
class ErrorResult;
|
||||
|
|
|
@ -809,29 +809,41 @@ DoCommandCallback(const char *aCommand, void *aData)
|
|||
NS_IMETHODIMP
|
||||
nsTextInputListener::HandleEvent(nsIDOMEvent* aEvent)
|
||||
{
|
||||
nsCOMPtr<nsIDOMKeyEvent> keyEvent(do_QueryInterface(aEvent));
|
||||
NS_ENSURE_TRUE(keyEvent, NS_ERROR_INVALID_ARG);
|
||||
bool defaultPrevented = false;
|
||||
nsresult rv = aEvent->GetDefaultPrevented(&defaultPrevented);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (defaultPrevented) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsAutoString eventType;
|
||||
aEvent->GetType(eventType);
|
||||
bool isTrusted = false;
|
||||
rv = aEvent->GetIsTrusted(&isTrusted);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!isTrusted) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsKeyEvent* keyEvent =
|
||||
static_cast<nsKeyEvent*>(aEvent->GetInternalNSEvent());
|
||||
if (keyEvent->eventStructType != NS_KEY_EVENT) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
nsNativeKeyEvent nativeEvent;
|
||||
nsINativeKeyBindings *bindings = GetKeyBindings();
|
||||
if (bindings &&
|
||||
nsContentUtils::DOMEventToNativeKeyEvent(keyEvent, &nativeEvent, false)) {
|
||||
|
||||
if (bindings) {
|
||||
bool handled = false;
|
||||
if (eventType.EqualsLiteral("keydown")) {
|
||||
handled = bindings->KeyDown(nativeEvent, DoCommandCallback, mFrame);
|
||||
}
|
||||
else if (eventType.EqualsLiteral("keyup")) {
|
||||
handled = bindings->KeyUp(nativeEvent, DoCommandCallback, mFrame);
|
||||
}
|
||||
else if (eventType.EqualsLiteral("keypress")) {
|
||||
handled = bindings->KeyPress(nativeEvent, DoCommandCallback, mFrame);
|
||||
}
|
||||
else {
|
||||
NS_ABORT();
|
||||
switch (keyEvent->message) {
|
||||
case NS_KEY_DOWN:
|
||||
handled = bindings->KeyDown(*keyEvent, DoCommandCallback, mFrame);
|
||||
break;
|
||||
case NS_KEY_UP:
|
||||
handled = bindings->KeyUp(*keyEvent, DoCommandCallback, mFrame);
|
||||
break;
|
||||
case NS_KEY_PRESS:
|
||||
handled = bindings->KeyPress(*keyEvent, DoCommandCallback, mFrame);
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH("Unknown key message");
|
||||
}
|
||||
if (handled) {
|
||||
aEvent->PreventDefault();
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
<div id="content">
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
@ -17,6 +17,38 @@
|
|||
|
||||
// TODO: maybe make those reflections be tested against all input types.
|
||||
|
||||
function testWidthHeight(attr) {
|
||||
var element = document.createElement('input');
|
||||
is(element[attr], 0, attr + ' always returns 0 if not type=image');
|
||||
element.setAttribute(attr, '42');
|
||||
is(element[attr], 0, attr + ' always returns 0 if not type=image');
|
||||
is(element.getAttribute(attr), '42');
|
||||
element[attr] = 0;
|
||||
is(element.getAttribute(attr), '0', 'setting ' + attr + ' changes the content attribute');
|
||||
element[attr] = 12;
|
||||
is(element.getAttribute(attr), '12', 'setting ' + attr + ' changes the content attribute');
|
||||
|
||||
element.removeAttribute(attr);
|
||||
ise(element.getAttribute(attr), null);
|
||||
|
||||
element = document.createElement('input');
|
||||
element.type = 'image';
|
||||
document.getElementById('content').appendChild(element);
|
||||
isnot(element[attr], 0, attr + ' represents the dimension of the element if type=image');
|
||||
|
||||
element.setAttribute(attr, '42');
|
||||
isnot(element[attr], 0, attr + ' represents the dimension of the element if type=image');
|
||||
isnot(element[attr], 42, attr + ' represents the dimension of the element if type=image');
|
||||
is(element.getAttribute(attr), '42');
|
||||
element[attr] = 0;
|
||||
is(element.getAttribute(attr), '0', 'setting ' + attr + ' changes the content attribute');
|
||||
element[attr] = 12;
|
||||
is(element.getAttribute(attr), '12', 'setting ' + attr + ' changes the content attribute');
|
||||
|
||||
element.removeAttribute(attr);
|
||||
ise(element.getAttribute(attr), null);
|
||||
}
|
||||
|
||||
// .accept
|
||||
reflectString({
|
||||
element: document.createElement("input"),
|
||||
|
@ -101,11 +133,7 @@ reflectString({
|
|||
});
|
||||
|
||||
// .height
|
||||
reflectUnsignedInt({
|
||||
element: document.createElement("input"),
|
||||
attribute: "height",
|
||||
nonZero: false
|
||||
});
|
||||
testWidthHeight('height');
|
||||
|
||||
// .indeterminate doesn't reflect a content attribute.
|
||||
|
||||
|
@ -234,11 +262,7 @@ todo("selectedOption" in document.createElement("input"),
|
|||
"selectedOption isn't implemented yet");
|
||||
|
||||
// .width
|
||||
reflectUnsignedInt({
|
||||
element: document.createElement("input"),
|
||||
attribute: "width",
|
||||
nonZero: false
|
||||
});
|
||||
testWidthHeight('width');
|
||||
|
||||
// .willValidate doesn't reflect a content attribute.
|
||||
// .validity doesn't reflect a content attribute.
|
||||
|
|
|
@ -39,6 +39,8 @@ class AudioStreamTrack;
|
|||
class VideoStreamTrack;
|
||||
}
|
||||
|
||||
class MediaStreamDirectListener;
|
||||
|
||||
/**
|
||||
* DOM wrapper for MediaStreams.
|
||||
*/
|
||||
|
@ -74,6 +76,14 @@ public:
|
|||
|
||||
MediaStream* GetStream() const { return mStream; }
|
||||
|
||||
/**
|
||||
* Overridden in DOMLocalMediaStreams to allow getUserMedia to pass
|
||||
* data directly to RTCPeerConnection without going through graph queuing.
|
||||
* Returns a bool to let us know if direct data will be delivered.
|
||||
*/
|
||||
virtual bool AddDirectListener(MediaStreamDirectListener *aListener) { return false; }
|
||||
virtual void RemoveDirectListener(MediaStreamDirectListener *aListener) {}
|
||||
|
||||
bool IsFinished();
|
||||
/**
|
||||
* Returns a principal indicating who may access this stream. The stream contents
|
||||
|
|
|
@ -190,6 +190,7 @@ destroying the MediaDecoder object.
|
|||
#include "gfxRect.h"
|
||||
#include "MediaResource.h"
|
||||
#include "mozilla/ReentrantMonitor.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "MediaStreamGraph.h"
|
||||
#include "MediaDecoderOwner.h"
|
||||
#include "AudioChannelCommon.h"
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "nsIInterfaceRequestor.h"
|
||||
#include "MediaCache.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
|
||||
// For HTTP seeking, if number of bytes needing to be
|
||||
// seeked forward is less than this value then a read is
|
||||
|
|
|
@ -1976,7 +1976,7 @@ SourceMediaStream::AddTrack(TrackID aID, TrackRate aRate, TrackTicks aStart,
|
|||
}
|
||||
|
||||
bool
|
||||
SourceMediaStream::AppendToTrack(TrackID aID, MediaSegment* aSegment)
|
||||
SourceMediaStream::AppendToTrack(TrackID aID, MediaSegment* aSegment, MediaSegment *aRawSegment)
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
// ::EndAllTrackAndFinished() can end these before the sources notice
|
||||
|
@ -1984,7 +1984,15 @@ SourceMediaStream::AppendToTrack(TrackID aID, MediaSegment* aSegment)
|
|||
if (!mFinished) {
|
||||
TrackData *track = FindDataForTrack(aID);
|
||||
if (track) {
|
||||
track->mData->AppendFrom(aSegment);
|
||||
// Data goes into mData, and on the next iteration of the MSG moves
|
||||
// into the track's segment after NotifyQueuedTrackChanges(). This adds
|
||||
// 0-10ms of delay before data gets to direct listeners.
|
||||
// Indirect listeners (via subsequent TrackUnion nodes) are synced to
|
||||
// playout time, and so can be delayed by buffering.
|
||||
|
||||
// Must notify first, since AppendFrom() will empty out aSegment
|
||||
NotifyDirectConsumers(track, aRawSegment ? aRawSegment : aSegment);
|
||||
track->mData->AppendFrom(aSegment); // note: aSegment is now dead
|
||||
appended = true;
|
||||
} else {
|
||||
aSegment->Clear();
|
||||
|
@ -1996,6 +2004,35 @@ SourceMediaStream::AppendToTrack(TrackID aID, MediaSegment* aSegment)
|
|||
return appended;
|
||||
}
|
||||
|
||||
void
|
||||
SourceMediaStream::NotifyDirectConsumers(TrackData *aTrack,
|
||||
MediaSegment *aSegment)
|
||||
{
|
||||
// Call with mMutex locked
|
||||
MOZ_ASSERT(aTrack);
|
||||
|
||||
for (uint32_t j = 0; j < mDirectListeners.Length(); ++j) {
|
||||
MediaStreamDirectListener* l = mDirectListeners[j];
|
||||
TrackTicks offset = 0; // FIX! need a separate TrackTicks.... or the end of the internal buffer
|
||||
l->NotifyRealtimeData(static_cast<MediaStreamGraph*>(GraphImpl()), aTrack->mID, aTrack->mRate,
|
||||
offset, aTrack->mCommands, *aSegment);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SourceMediaStream::AddDirectListener(MediaStreamDirectListener* aListener)
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
mDirectListeners.AppendElement(aListener);
|
||||
}
|
||||
|
||||
void
|
||||
SourceMediaStream::RemoveDirectListener(MediaStreamDirectListener* aListener)
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
mDirectListeners.RemoveElement(aListener);
|
||||
}
|
||||
|
||||
bool
|
||||
SourceMediaStream::HaveEnoughBuffered(TrackID aID)
|
||||
{
|
||||
|
@ -2073,6 +2110,21 @@ SourceMediaStream::EndAllTrackAndFinish()
|
|||
// we will call NotifyFinished() to let GetUserMedia know
|
||||
}
|
||||
|
||||
TrackTicks
|
||||
SourceMediaStream::GetBufferedTicks(TrackID aID)
|
||||
{
|
||||
StreamBuffer::Track* track = mBuffer.FindTrack(aID);
|
||||
if (track) {
|
||||
MediaSegment* segment = track->GetSegment();
|
||||
if (segment) {
|
||||
return segment->GetDuration() -
|
||||
track->TimeToTicksRoundDown(
|
||||
GraphTimeToStreamTime(GraphImpl()->mStateComputedTime));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
MediaInputPort::Init()
|
||||
{
|
||||
|
|
|
@ -169,6 +169,30 @@ public:
|
|||
const MediaSegment& aQueuedMedia) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* This is a base class for media graph thread listener direct callbacks
|
||||
* from within AppendToTrack(). Note that your regular listener will
|
||||
* still get NotifyQueuedTrackChanges() callbacks from the MSG thread, so
|
||||
* you must be careful to ignore them if AddDirectListener was successful.
|
||||
*/
|
||||
class MediaStreamDirectListener : public MediaStreamListener
|
||||
{
|
||||
public:
|
||||
virtual ~MediaStreamDirectListener() {}
|
||||
|
||||
/*
|
||||
* This will be called on any MediaStreamDirectListener added to a
|
||||
* a SourceMediaStream when AppendToTrack() is called. The MediaSegment
|
||||
* will be the RawSegment (unresampled) if available in AppendToTrack().
|
||||
* Note that NotifyQueuedTrackChanges() calls will also still occur.
|
||||
*/
|
||||
virtual void NotifyRealtimeData(MediaStreamGraph* aGraph, TrackID aID,
|
||||
TrackRate aTrackRate,
|
||||
TrackTicks aTrackOffset,
|
||||
uint32_t aTrackEvents,
|
||||
const MediaSegment& aMedia) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* This is a base class for main-thread listener callbacks.
|
||||
* This callback is invoked on the main thread when the main-thread-visible
|
||||
|
@ -599,6 +623,10 @@ public:
|
|||
* it is still possible for a NotifyPull to occur.
|
||||
*/
|
||||
void SetPullEnabled(bool aEnabled);
|
||||
|
||||
void AddDirectListener(MediaStreamDirectListener* aListener);
|
||||
void RemoveDirectListener(MediaStreamDirectListener* aListener);
|
||||
|
||||
/**
|
||||
* Add a new track to the stream starting at the given base time (which
|
||||
* must be greater than or equal to the last time passed to
|
||||
|
@ -613,7 +641,7 @@ public:
|
|||
* Returns false if the data was not appended because no such track exists
|
||||
* or the stream was already finished.
|
||||
*/
|
||||
bool AppendToTrack(TrackID aID, MediaSegment* aSegment);
|
||||
bool AppendToTrack(TrackID aID, MediaSegment* aSegment, MediaSegment *aRawSegment = nullptr);
|
||||
/**
|
||||
* Returns true if the buffer currently has enough data.
|
||||
* Returns false if there isn't enough data or if no such track exists.
|
||||
|
@ -658,6 +686,17 @@ public:
|
|||
*/
|
||||
void EndAllTrackAndFinish();
|
||||
|
||||
/**
|
||||
* Note: Only call from Media Graph thread (eg NotifyPull)
|
||||
*
|
||||
* Returns amount of time (data) that is currently buffered in the track,
|
||||
* assuming playout via PlayAudio or via a TrackUnion - note that
|
||||
* NotifyQueuedTrackChanges() on a SourceMediaStream will occur without
|
||||
* any "extra" buffering, but NotifyQueued TrackChanges() on a TrackUnion
|
||||
* will be buffered.
|
||||
*/
|
||||
TrackTicks GetBufferedTicks(TrackID aID);
|
||||
|
||||
// XXX need a Reset API
|
||||
|
||||
friend class MediaStreamGraphImpl;
|
||||
|
@ -704,6 +743,15 @@ protected:
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify direct consumers of new data to one of the stream tracks.
|
||||
* The data doesn't have to be resampled (though it may be). This is called
|
||||
* from AppendToTrack on the thread providing the data, and will call
|
||||
* the Listeners on this thread.
|
||||
*/
|
||||
void NotifyDirectConsumers(TrackData *aTrack,
|
||||
MediaSegment *aSegment);
|
||||
|
||||
// Media stream graph thread only
|
||||
MediaStreamListener::Consumption mLastConsumptionState;
|
||||
|
||||
|
@ -713,6 +761,7 @@ protected:
|
|||
// protected by mMutex
|
||||
StreamTime mUpdateKnownTracksTime;
|
||||
nsTArray<TrackData> mUpdateTracks;
|
||||
nsTArray<nsRefPtr<MediaStreamDirectListener> > mDirectListeners;
|
||||
bool mPullEnabled;
|
||||
bool mUpdateFinished;
|
||||
bool mDestroyed;
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "mozilla/dom/TimeRanges.h"
|
||||
#include "MediaResource.h"
|
||||
#include "mozilla/dom/HTMLMediaElement.h"
|
||||
|
|
|
@ -43,7 +43,7 @@ public:
|
|||
: AudioNodeEngine(aNode)
|
||||
, mSource(nullptr)
|
||||
, mDestination(static_cast<AudioNodeStream*> (aDestination->Stream()))
|
||||
, mStart(0)
|
||||
, mStart(-1)
|
||||
, mStop(TRACK_TICKS_MAX)
|
||||
// Keep the default values in sync with OscillatorNode::OscillatorNode.
|
||||
, mFrequency(440.f)
|
||||
|
@ -245,6 +245,11 @@ public:
|
|||
MOZ_ASSERT(mSource == aStream, "Invalid source stream");
|
||||
|
||||
TrackTicks ticks = aStream->GetCurrentPosition();
|
||||
if (mStart == -1) {
|
||||
ComputeSilence(aOutput);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ticks + WEBAUDIO_BLOCK_SIZE < mStart) {
|
||||
// We're not playing yet.
|
||||
ComputeSilence(aOutput);
|
||||
|
|
|
@ -78,6 +78,7 @@ MOCHITEST_FILES := \
|
|||
test_offlineDestinationChannelCountLess.html \
|
||||
test_offlineDestinationChannelCountMore.html \
|
||||
test_oscillatorNode.html \
|
||||
test_oscillatorNodeStart.html \
|
||||
test_pannerNode.html \
|
||||
test_pannerNode_equalPower.html \
|
||||
test_periodicWave.html \
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test the OscillatorNode interface</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="webaudio.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addLoadEvent(function() {
|
||||
|
||||
var context = new AudioContext();
|
||||
var osc = context.createOscillator();
|
||||
var sp = context.createScriptProcessor();
|
||||
|
||||
osc.connect(sp);
|
||||
|
||||
sp.onaudioprocess = function (e) {
|
||||
var input = e.inputBuffer.getChannelData(0);
|
||||
var isSilent = true;
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
if (input[i] != 0.0) {
|
||||
isSilent = false;
|
||||
}
|
||||
}
|
||||
sp.onaudioprocess = null;
|
||||
ok(isSilent, "OscillatorNode should be silent before calling start.");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -11,6 +11,7 @@
|
|||
#include "nsContentUtils.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsSVGString.h"
|
||||
#include "nsIURI.h"
|
||||
|
||||
NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(A)
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "nsSMILAnimationController.h"
|
||||
#include "nsSMILAnimationFunction.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIURI.h"
|
||||
#include "prtime.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "mozilla/dom/SVGPathElement.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "mozilla/dom/SVGMPathElementBinding.h"
|
||||
#include "nsIURI.h"
|
||||
|
||||
NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(MPath)
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "nsIPresShell.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIURI.h"
|
||||
|
||||
NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(Use)
|
||||
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
#include "nsIDOMNode.h"
|
||||
#include "nsXBLPrototypeBinding.h"
|
||||
#include "nsXBLProtoImplProperty.h"
|
||||
#include "nsIURI.h"
|
||||
#include "xpcpublic.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ class nsSupportsHashtable;
|
|||
class nsXBLPrototypeResources;
|
||||
class nsXBLPrototypeBinding;
|
||||
struct nsXBLResource;
|
||||
class nsIObjectOutputStream;
|
||||
|
||||
// *********************************************************************/
|
||||
// The XBLResourceLoader class
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "nsContentUtils.h"
|
||||
#include "nsCxPusher.h"
|
||||
#include "jsdbgapi.h"
|
||||
#include "jsfriendapi.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
|
|
|
@ -345,7 +345,6 @@ nsXBLWindowKeyHandler::WalkHandlers(nsIDOMKeyEvent* aKeyEvent, nsIAtom* aEventTy
|
|||
WalkHandlersInternal(aKeyEvent, aEventType, mHandler);
|
||||
|
||||
if (isEditor && GetEditorKeyBindings()) {
|
||||
nsNativeKeyEvent nativeEvent;
|
||||
// get the DOM window we're attached to
|
||||
nsCOMPtr<nsIControllers> controllers;
|
||||
nsCOMPtr<nsPIWindowRoot> root = do_QueryInterface(mTarget);
|
||||
|
@ -353,20 +352,30 @@ nsXBLWindowKeyHandler::WalkHandlers(nsIDOMKeyEvent* aKeyEvent, nsIAtom* aEventTy
|
|||
root->GetControllers(getter_AddRefs(controllers));
|
||||
}
|
||||
|
||||
nsKeyEvent* keyEvent =
|
||||
static_cast<nsKeyEvent*>(aKeyEvent->GetInternalNSEvent());
|
||||
MOZ_ASSERT(keyEvent->eventStructType == NS_KEY_EVENT,
|
||||
"DOM key event's internal event must be nsKeyEvent");
|
||||
|
||||
bool handled = false;
|
||||
if (aEventType == nsGkAtoms::keypress) {
|
||||
if (nsContentUtils::DOMEventToNativeKeyEvent(aKeyEvent, &nativeEvent, true))
|
||||
handled = sNativeEditorBindings->KeyPress(nativeEvent,
|
||||
DoCommandCallback, controllers);
|
||||
} else if (aEventType == nsGkAtoms::keyup) {
|
||||
if (nsContentUtils::DOMEventToNativeKeyEvent(aKeyEvent, &nativeEvent, false))
|
||||
handled = sNativeEditorBindings->KeyUp(nativeEvent,
|
||||
DoCommandCallback, controllers);
|
||||
} else {
|
||||
NS_ASSERTION(aEventType == nsGkAtoms::keydown, "unknown key event type");
|
||||
if (nsContentUtils::DOMEventToNativeKeyEvent(aKeyEvent, &nativeEvent, false))
|
||||
handled = sNativeEditorBindings->KeyDown(nativeEvent,
|
||||
DoCommandCallback, controllers);
|
||||
switch (keyEvent->message) {
|
||||
case NS_KEY_PRESS:
|
||||
handled = sNativeEditorBindings->KeyPress(*keyEvent,
|
||||
DoCommandCallback,
|
||||
controllers);
|
||||
break;
|
||||
case NS_KEY_UP:
|
||||
handled = sNativeEditorBindings->KeyUp(*keyEvent,
|
||||
DoCommandCallback,
|
||||
controllers);
|
||||
break;
|
||||
case NS_KEY_DOWN:
|
||||
handled = sNativeEditorBindings->KeyDown(*keyEvent,
|
||||
DoCommandCallback,
|
||||
controllers);
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH("Unknown key message");
|
||||
}
|
||||
|
||||
if (handled)
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "nsAttrName.h"
|
||||
#include "rdf.h"
|
||||
#include "nsArrayUtils.h"
|
||||
#include "nsIURI.h"
|
||||
|
||||
#include "nsContentTestNode.h"
|
||||
#include "nsRDFConInstanceTestNode.h"
|
||||
|
|
|
@ -185,8 +185,6 @@
|
|||
#endif
|
||||
|
||||
#include "nsIDOMCameraManager.h"
|
||||
#include "nsIOpenWindowEventDetail.h"
|
||||
#include "nsIAsyncScrollEventDetail.h"
|
||||
#include "nsIDOMGlobalObjectConstructor.h"
|
||||
#include "nsIDOMLockedFile.h"
|
||||
#include "nsDebug.h"
|
||||
|
@ -561,11 +559,6 @@ static nsDOMClassInfoData sClassInfoData[] = {
|
|||
NS_DEFINE_CLASSINFO_DATA(CameraCapabilities, nsDOMGenericSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
|
||||
NS_DEFINE_CLASSINFO_DATA(OpenWindowEventDetail, nsDOMGenericSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CLASSINFO_DATA(AsyncScrollEventDetail, nsDOMGenericSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
|
||||
NS_DEFINE_CLASSINFO_DATA(LockedFile, nsEventTargetSH,
|
||||
EVENTTARGET_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CLASSINFO_DATA(CSSFontFeatureValuesRule, nsDOMGenericSH,
|
||||
|
@ -1447,14 +1440,6 @@ nsDOMClassInfo::Init()
|
|||
DOM_CLASSINFO_MAP_ENTRY(nsICameraCapabilities)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN(OpenWindowEventDetail, nsIOpenWindowEventDetail)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIOpenWindowEventDetail)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN(AsyncScrollEventDetail, nsIAsyncScrollEventDetail)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIAsyncScrollEventDetail)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN(LockedFile, nsIDOMLockedFile)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMLockedFile)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
@ -4269,7 +4254,7 @@ nsHTMLDocumentSH::GetDocumentAllNodeList(JSContext *cx,
|
|||
// We already have a node list in our reserved slot, use it.
|
||||
JS::Rooted<JSObject*> obj(cx, JSVAL_TO_OBJECT(collection));
|
||||
nsIHTMLCollection* htmlCollection;
|
||||
rv = mozilla::dom::UnwrapObject<nsIHTMLCollection>(cx, obj, htmlCollection);
|
||||
rv = UNWRAP_OBJECT(HTMLCollection, cx, obj, htmlCollection);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
NS_ADDREF(*nodeList = static_cast<nsContentList*>(htmlCollection));
|
||||
}
|
||||
|
|
|
@ -143,9 +143,6 @@ DOMCI_CLASS(BluetoothDevice)
|
|||
DOMCI_CLASS(CameraControl)
|
||||
DOMCI_CLASS(CameraCapabilities)
|
||||
|
||||
DOMCI_CLASS(OpenWindowEventDetail)
|
||||
DOMCI_CLASS(AsyncScrollEventDetail)
|
||||
|
||||
DOMCI_CLASS(LockedFile)
|
||||
|
||||
DOMCI_CLASS(CSSFontFeatureValuesRule)
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
#include "nsContentUtils.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "prtime.h"
|
||||
#include "TimeStamp.h"
|
||||
#include "nsIURI.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
|
||||
nsDOMNavigationTiming::nsDOMNavigationTiming()
|
||||
{
|
||||
|
|
|
@ -98,7 +98,7 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
nsDOMNavigationTiming(const nsDOMNavigationTiming &){};
|
||||
nsDOMNavigationTiming(const nsDOMNavigationTiming &) MOZ_DELETE;
|
||||
~nsDOMNavigationTiming();
|
||||
|
||||
void Clear();
|
||||
|
|
|
@ -2731,7 +2731,7 @@ NS_DOMWriteStructuredClone(JSContext* cx,
|
|||
void *closure)
|
||||
{
|
||||
ImageData* imageData;
|
||||
nsresult rv = UnwrapObject<ImageData>(cx, obj, imageData);
|
||||
nsresult rv = UNWRAP_OBJECT(ImageData, cx, obj, imageData);
|
||||
if (NS_FAILED(rv)) {
|
||||
// Don't know what this is. Bail.
|
||||
xpc::Throw(cx, NS_ERROR_DOM_DATA_CLONE_ERR);
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsPerformance.h"
|
||||
#include "TimeStamp.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsITimedChannel.h"
|
||||
#include "nsDOMNavigationTiming.h"
|
||||
|
@ -13,6 +12,7 @@
|
|||
#include "mozilla/dom/PerformanceBinding.h"
|
||||
#include "mozilla/dom/PerformanceTimingBinding.h"
|
||||
#include "mozilla/dom/PerformanceNavigationBinding.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
|
|
|
@ -1679,7 +1679,7 @@ ReparentWrapper(JSContext* aCx, JS::HandleObject aObjArg)
|
|||
}
|
||||
|
||||
nsObjectLoadingContent* htmlobject;
|
||||
nsresult rv = UnwrapObject<HTMLObjectElement>(aCx, aObj, htmlobject);
|
||||
nsresult rv = UNWRAP_OBJECT(HTMLObjectElement, aCx, aObj, htmlobject);
|
||||
if (NS_FAILED(rv)) {
|
||||
rv = UnwrapObject<prototypes::id::HTMLEmbedElement,
|
||||
HTMLSharedObjectElement>(aCx, aObj, htmlobject);
|
||||
|
|
|
@ -181,6 +181,10 @@ IsDOMObject(JSObject* obj)
|
|||
return IsDOMClass(clasp) || IsDOMProxy(obj, clasp);
|
||||
}
|
||||
|
||||
#define UNWRAP_OBJECT(Interface, cx, obj, value) \
|
||||
UnwrapObject<prototypes::id::Interface, \
|
||||
mozilla::dom::Interface##Binding::NativeType>(cx, obj, value)
|
||||
|
||||
// Some callers don't want to set an exception when unwrapping fails
|
||||
// (for example, overload resolution uses unwrapping to tell what sort
|
||||
// of thing it's looking at).
|
||||
|
@ -257,15 +261,6 @@ IsConvertibleToCallbackInterface(JSContext* cx, JS::Handle<JSObject*> obj)
|
|||
return IsNotDateOrRegExp(cx, obj);
|
||||
}
|
||||
|
||||
// U must be something that a T* can be assigned to (e.g. T* or an nsRefPtr<T>).
|
||||
template <class T, typename U>
|
||||
inline nsresult
|
||||
UnwrapObject(JSContext* cx, JSObject* obj, U& value)
|
||||
{
|
||||
return UnwrapObject<static_cast<prototypes::ID>(
|
||||
PrototypeIDMap<T>::PrototypeID), T>(cx, obj, value);
|
||||
}
|
||||
|
||||
// The items in the protoAndIfaceArray are indexed by the prototypes::id::ID and
|
||||
// constructors::id::ID enums, in that order. The end of the prototype objects
|
||||
// should be the start of the interface objects.
|
||||
|
|
|
@ -80,7 +80,7 @@ class CGNativePropertyHooks(CGThing):
|
|||
def declare(self):
|
||||
if self.descriptor.workers:
|
||||
return ""
|
||||
return "extern const NativePropertyHooks sNativePropertyHooks;\n"
|
||||
return "extern const NativePropertyHooks* sNativePropertyHooks;\n"
|
||||
def define(self):
|
||||
if self.descriptor.workers:
|
||||
return ""
|
||||
|
@ -112,7 +112,7 @@ class CGNativePropertyHooks(CGThing):
|
|||
else:
|
||||
prototypeID += "_ID_Count"
|
||||
parent = self.descriptor.interface.parent
|
||||
parentHooks = ("&" + toBindingNamespace(parent.identifier.name) + "::sNativePropertyHooks"
|
||||
parentHooks = (toBindingNamespace(parent.identifier.name) + "::sNativePropertyHooks"
|
||||
if parent else 'nullptr')
|
||||
|
||||
return CGWrapper(CGIndenter(CGList([CGGeneric(resolveOwnProperty),
|
||||
|
@ -125,11 +125,13 @@ class CGNativePropertyHooks(CGThing):
|
|||
CGGeneric(constructorID),
|
||||
CGGeneric(parentHooks)],
|
||||
",\n")),
|
||||
pre="const NativePropertyHooks sNativePropertyHooks = {\n",
|
||||
post="\n};\n").define()
|
||||
pre="static const NativePropertyHooks sNativePropertyHooksStruct = {\n",
|
||||
post=("\n"
|
||||
"};\n"
|
||||
"const NativePropertyHooks* sNativePropertyHooks = &sNativePropertyHooksStruct;\n")).define()
|
||||
|
||||
def NativePropertyHooks(descriptor):
|
||||
return "&sWorkerNativePropertyHooks" if descriptor.workers else "&sNativePropertyHooks"
|
||||
return "&sWorkerNativePropertyHooks" if descriptor.workers else "sNativePropertyHooks"
|
||||
|
||||
def DOMClass(descriptor):
|
||||
protoList = ['prototypes::id::' + proto for proto in descriptor.prototypeChain]
|
||||
|
@ -166,7 +168,7 @@ class CGDOMJSClass(CGThing):
|
|||
# Our current reserved slot situation is unsafe for globals. Fix bug 760095!
|
||||
assert "Window" not in descriptor.interface.identifier.name
|
||||
def declare(self):
|
||||
return "extern DOMJSClass Class;\n"
|
||||
return ""
|
||||
def define(self):
|
||||
traceHook = TRACE_HOOK_NAME if self.descriptor.customTrace else 'nullptr'
|
||||
callHook = LEGACYCALLER_HOOK_NAME if self.descriptor.operations["LegacyCaller"] else 'nullptr'
|
||||
|
@ -179,7 +181,7 @@ class CGDOMJSClass(CGThing):
|
|||
newResolveHook = "JS_ResolveStub"
|
||||
enumerateHook = "JS_EnumerateStub"
|
||||
return """
|
||||
DOMJSClass Class = {
|
||||
static DOMJSClass Class = {
|
||||
{ "%s",
|
||||
%s,
|
||||
%s, /* addProperty */
|
||||
|
@ -565,9 +567,19 @@ class CGHeaders(CGWrapper):
|
|||
interfaceDeps = [d.interface for d in descriptors]
|
||||
ancestors = []
|
||||
for iface in interfaceDeps:
|
||||
while iface.parent:
|
||||
if iface.parent:
|
||||
# We're going to need our parent's prototype, to use as the
|
||||
# prototype of our prototype object.
|
||||
ancestors.append(iface.parent)
|
||||
iface = iface.parent
|
||||
# And if we have an interface object, we'll need the nearest
|
||||
# ancestor with an interface object too, so we can use its
|
||||
# interface object as the proto of our interface object.
|
||||
if iface.hasInterfaceObject():
|
||||
parent = iface.parent
|
||||
while parent and not parent.hasInterfaceObject():
|
||||
parent = parent.parent
|
||||
if parent:
|
||||
ancestors.append(parent)
|
||||
interfaceDeps.extend(ancestors)
|
||||
bindingIncludes = set(self.getDeclarationFilename(d) for d in interfaceDeps)
|
||||
|
||||
|
@ -639,7 +651,6 @@ class CGHeaders(CGWrapper):
|
|||
declareIncludes.add(typeDesc.headerFile)
|
||||
else:
|
||||
implementationIncludes.add(typeDesc.headerFile)
|
||||
bindingHeaders.add(self.getDeclarationFilename(typeDesc.interface))
|
||||
elif unrolled.isDictionary():
|
||||
bindingHeaders.add(self.getDeclarationFilename(unrolled.inner))
|
||||
elif unrolled.isCallback():
|
||||
|
@ -962,6 +973,14 @@ class CGAbstractClassHook(CGAbstractStaticMethod):
|
|||
# Override me
|
||||
assert(False)
|
||||
|
||||
class CGGetJSClassMethod(CGAbstractMethod):
|
||||
def __init__(self, descriptor):
|
||||
CGAbstractMethod.__init__(self, descriptor, 'GetJSClass', 'JSClass*',
|
||||
[])
|
||||
|
||||
def definition_body(self):
|
||||
return " return Class.ToJSClass();"
|
||||
|
||||
class CGAddPropertyHook(CGAbstractClassHook):
|
||||
"""
|
||||
A hook for addProperty, used to preserve our wrapper from GC.
|
||||
|
@ -1871,7 +1890,7 @@ class CGGetPerInterfaceObject(CGAbstractMethod):
|
|||
args = [Argument('JSContext*', 'aCx'),
|
||||
Argument('JS::Handle<JSObject*>', 'aGlobal')] + extraArgs
|
||||
CGAbstractMethod.__init__(self, descriptor, name,
|
||||
'JS::Handle<JSObject*>', args, inline=True)
|
||||
'JS::Handle<JSObject*>', args)
|
||||
self.id = idPrefix + "id::" + self.descriptor.name
|
||||
def definition_body(self):
|
||||
return ("""
|
||||
|
@ -2030,16 +2049,6 @@ class CGConstructorEnabledViaFunc(CGAbstractMethod):
|
|||
assert isinstance(func, list) and len(func) == 1
|
||||
return " return %s(cx, obj);" % func[0]
|
||||
|
||||
class CGIsMethod(CGAbstractMethod):
|
||||
def __init__(self, descriptor):
|
||||
args = [Argument('JSObject*', 'obj')]
|
||||
CGAbstractMethod.__init__(self, descriptor, 'Is', 'bool', args)
|
||||
|
||||
def definition_body(self):
|
||||
# Non-proxy implementation would check
|
||||
# js::GetObjectJSClass(obj) == &Class.mBase
|
||||
return """ return IsProxy(obj);"""
|
||||
|
||||
def CreateBindingJSObject(descriptor, properties, parent):
|
||||
# When we have unforgeable properties, we're going to define them
|
||||
# on our object, so we have to root it when we create it, so it
|
||||
|
@ -6868,21 +6877,7 @@ class CGPrototypeTraitsClass(CGClass):
|
|||
templateSpecialization = ['prototypes::id::' + descriptor.name]
|
||||
enums = [ClassEnum('', ['Depth'],
|
||||
[descriptor.interface.inheritanceDepth()])]
|
||||
typedefs = [ClassTypedef('NativeType', descriptor.nativeType)]
|
||||
CGClass.__init__(self, 'PrototypeTraits', indent=indent,
|
||||
templateArgs=templateArgs,
|
||||
templateSpecialization=templateSpecialization,
|
||||
enums=enums, typedefs=typedefs, isStruct=True)
|
||||
def deps(self):
|
||||
return set()
|
||||
|
||||
class CGPrototypeIDMapClass(CGClass):
|
||||
def __init__(self, descriptor, indent=''):
|
||||
templateArgs = [Argument('class', 'ConcreteClass')]
|
||||
templateSpecialization = [descriptor.nativeType]
|
||||
enums = [ClassEnum('', ['PrototypeID'],
|
||||
['prototypes::id::' + descriptor.name])]
|
||||
CGClass.__init__(self, 'PrototypeIDMap', indent=indent,
|
||||
templateArgs=templateArgs,
|
||||
templateSpecialization=templateSpecialization,
|
||||
enums=enums, isStruct=True)
|
||||
|
@ -7124,10 +7119,10 @@ class CGDOMJSProxyHandlerDOMClass(CGThing):
|
|||
CGThing.__init__(self)
|
||||
self.descriptor = descriptor
|
||||
def declare(self):
|
||||
return "extern const DOMClass Class;\n"
|
||||
return ""
|
||||
def define(self):
|
||||
return """
|
||||
const DOMClass Class = """ + DOMClass(self.descriptor) + """;
|
||||
static const DOMClass Class = """ + DOMClass(self.descriptor) + """;
|
||||
|
||||
"""
|
||||
|
||||
|
@ -7720,6 +7715,33 @@ class CGDOMJSProxyHandler(CGClass):
|
|||
constructors=constructors,
|
||||
methods=methods)
|
||||
|
||||
class CGDOMJSProxyHandlerDeclarer(CGThing):
|
||||
"""
|
||||
A class for declaring a DOMProxyHandler.
|
||||
"""
|
||||
def __init__(self, handlerThing):
|
||||
self.handlerThing = handlerThing
|
||||
|
||||
def declare(self):
|
||||
# Our class declaration should happen when we're defining
|
||||
return ""
|
||||
|
||||
def define(self):
|
||||
return self.handlerThing.declare()
|
||||
|
||||
class CGDOMJSProxyHandlerDefiner(CGThing):
|
||||
"""
|
||||
A class for defining a DOMProxyHandler.
|
||||
"""
|
||||
def __init__(self, handlerThing):
|
||||
self.handlerThing = handlerThing
|
||||
|
||||
def declare(self):
|
||||
return ""
|
||||
|
||||
def define(self):
|
||||
return self.handlerThing.define()
|
||||
|
||||
def stripTrailingWhitespace(text):
|
||||
tail = '\n' if text.endswith('\n') else ''
|
||||
lines = text.splitlines()
|
||||
|
@ -7741,6 +7763,8 @@ class CGDescriptor(CGThing):
|
|||
self._deps = descriptor.interface.getDeps()
|
||||
|
||||
cgThings = []
|
||||
cgThings.append(CGGeneric(declare="typedef %s NativeType;\n" %
|
||||
descriptor.nativeType))
|
||||
# These are set to true if at least one non-static
|
||||
# method/getter/setter or jsonifier exist on the interface.
|
||||
(hasMethod, hasGetter, hasLenientGetter, hasSetter, hasJsonifier,
|
||||
|
@ -7849,12 +7873,6 @@ class CGDescriptor(CGThing):
|
|||
if descriptor.interface.hasInterfacePrototypeObject():
|
||||
cgThings.append(CGPrototypeJSClass(descriptor, properties))
|
||||
|
||||
cgThings.append(CGCreateInterfaceObjectsMethod(descriptor, properties))
|
||||
if descriptor.interface.hasInterfacePrototypeObject():
|
||||
cgThings.append(CGGetProtoObjectMethod(descriptor))
|
||||
if descriptor.interface.hasInterfaceObject():
|
||||
cgThings.append(CGGetConstructorObjectMethod(descriptor))
|
||||
|
||||
if descriptor.interface.hasInterfaceObject():
|
||||
cgThings.append(CGDefineDOMInterfaceMethod(descriptor))
|
||||
|
||||
|
@ -7891,13 +7909,15 @@ class CGDescriptor(CGThing):
|
|||
if not descriptor.wrapperCache:
|
||||
raise TypeError("We need a wrappercache to support expandos for proxy-based "
|
||||
"bindings (" + descriptor.name + ")")
|
||||
handlerThing = CGDOMJSProxyHandler(descriptor)
|
||||
cgThings.append(CGDOMJSProxyHandlerDeclarer(handlerThing))
|
||||
cgThings.append(CGProxyIsProxy(descriptor))
|
||||
cgThings.append(CGProxyUnwrap(descriptor))
|
||||
cgThings.append(CGDOMJSProxyHandlerDOMClass(descriptor))
|
||||
cgThings.append(CGDOMJSProxyHandler(descriptor))
|
||||
cgThings.append(CGIsMethod(descriptor))
|
||||
cgThings.append(CGDOMJSProxyHandlerDefiner(handlerThing))
|
||||
else:
|
||||
cgThings.append(CGDOMJSClass(descriptor))
|
||||
cgThings.append(CGGetJSClassMethod(descriptor))
|
||||
|
||||
if descriptor.wrapperCache:
|
||||
cgThings.append(CGWrapWithCacheMethod(descriptor, properties))
|
||||
|
@ -7906,6 +7926,17 @@ class CGDescriptor(CGThing):
|
|||
cgThings.append(CGWrapNonWrapperCacheMethod(descriptor,
|
||||
properties))
|
||||
|
||||
# CGCreateInterfaceObjectsMethod needs to come after our
|
||||
# CGDOMJSClass, if any.
|
||||
cgThings.append(CGCreateInterfaceObjectsMethod(descriptor, properties))
|
||||
|
||||
# CGGetProtoObjectMethod and CGGetConstructorObjectMethod need
|
||||
# to come after CGCreateInterfaceObjectsMethod.
|
||||
if descriptor.interface.hasInterfacePrototypeObject():
|
||||
cgThings.append(CGGetProtoObjectMethod(descriptor))
|
||||
if descriptor.interface.hasInterfaceObject():
|
||||
cgThings.append(CGGetConstructorObjectMethod(descriptor))
|
||||
|
||||
cgThings = CGList((CGIndenter(t, declareOnly=True) for t in cgThings), "\n")
|
||||
cgThings = CGWrapper(cgThings, pre='\n', post='\n')
|
||||
self.cgRoot = CGWrapper(CGNamespace(toBindingNamespace(descriptor.name),
|
||||
|
@ -8168,7 +8199,6 @@ if (""",
|
|||
|
||||
|
||||
initializerCtor = ClassConstructor([],
|
||||
bodyInHeader=True,
|
||||
visibility="public",
|
||||
body=(
|
||||
"// Safe to pass a null context if we pass a null value\n"
|
||||
|
@ -8554,10 +8584,13 @@ class CGForwardDeclarations(CGWrapper):
|
|||
# Don't need to do anything for void, primitive, string, any or object.
|
||||
# There may be some other cases we are missing.
|
||||
|
||||
# Needed for at least PrototypeTraits, PrototypeIDMap, and Wrap.
|
||||
# Needed for at least Wrap.
|
||||
for d in descriptors:
|
||||
builder.add(d.nativeType)
|
||||
|
||||
# We just about always need NativePropertyHooks
|
||||
builder.addInMozillaDom("NativePropertyHooks")
|
||||
|
||||
for callback in mainCallbacks:
|
||||
forwardDeclareForType(callback)
|
||||
for t in getTypesFromCallback(callback):
|
||||
|
@ -8596,7 +8629,7 @@ class CGBindingRoot(CGThing):
|
|||
return any(m.getExtendedAttribute("Pref") for m in iface.members + [iface]);
|
||||
requiresPreferences = any(descriptorRequiresPreferences(d) for d in descriptors)
|
||||
hasOwnedDescriptors = any(d.nativeOwnership == 'owned' for d in descriptors)
|
||||
requiresContentUtils = any(d.interface.hasInterfaceObject() for d in descriptors)
|
||||
hasProxies = any(d.concrete and d.proxy for d in descriptors)
|
||||
def descriptorHasChromeOnly(desc):
|
||||
return (any(isChromeOnly(a) for a in desc.interface.members) or
|
||||
desc.interface.getExtendedAttribute("ChromeOnly") is not None or
|
||||
|
@ -8640,25 +8673,6 @@ class CGBindingRoot(CGThing):
|
|||
callForEachType(descriptors + callbackDescriptors, dictionaries,
|
||||
mainCallbacks, checkForXPConnectImpls)
|
||||
|
||||
descriptorsWithPrototype = filter(lambda d: d.interface.hasInterfacePrototypeObject(),
|
||||
descriptors)
|
||||
traitsClasses = [CGPrototypeTraitsClass(d) for d in descriptorsWithPrototype]
|
||||
|
||||
# We must have a 1:1 mapping here, skip for prototypes which
|
||||
# share an implementation with other prototypes.
|
||||
traitsClasses.extend([CGPrototypeIDMapClass(d) for d in descriptorsWithPrototype
|
||||
if d.unsharedImplementation])
|
||||
|
||||
# Wrap all of that in our namespaces.
|
||||
if len(traitsClasses) > 0:
|
||||
traitsClasses = CGNamespace.build(['mozilla', 'dom'],
|
||||
CGWrapper(CGList(traitsClasses),
|
||||
declarePre='\n'),
|
||||
declareOnly=True)
|
||||
traitsClasses = CGWrapper(traitsClasses, declarePost='\n')
|
||||
else:
|
||||
traitsClasses = None
|
||||
|
||||
# Do codegen for all the enums
|
||||
cgthings = [ CGEnum(e) for e in config.getEnums(webIDLFile) ]
|
||||
|
||||
|
@ -8709,7 +8723,7 @@ class CGBindingRoot(CGThing):
|
|||
callbackDescriptors + jsImplemented),
|
||||
CGWrapper(CGGeneric("using namespace mozilla::dom;"),
|
||||
defineOnly=True),
|
||||
traitsClasses, curr],
|
||||
curr],
|
||||
"\n")
|
||||
|
||||
# Add header includes.
|
||||
|
@ -8719,19 +8733,21 @@ class CGBindingRoot(CGThing):
|
|||
callbackDescriptors,
|
||||
['mozilla/dom/BindingDeclarations.h',
|
||||
'mozilla/ErrorResult.h',
|
||||
'mozilla/dom/DOMJSClass.h',
|
||||
'mozilla/dom/DOMJSProxyHandler.h'],
|
||||
'jspubtd.h',
|
||||
'js/RootingAPI.h',
|
||||
],
|
||||
['mozilla/dom/BindingUtils.h',
|
||||
'mozilla/dom/Nullable.h',
|
||||
'PrimitiveConversions.h',
|
||||
'WrapperFactory.h',
|
||||
'mozilla/dom/DOMJSClass.h',
|
||||
] + (['WorkerPrivate.h',
|
||||
'nsThreadUtils.h'] if hasWorkerStuff else [])
|
||||
+ (['mozilla/Preferences.h'] if requiresPreferences else [])
|
||||
+ (['mozilla/dom/NonRefcountedDOMObject.h'] if hasOwnedDescriptors else [])
|
||||
+ (['nsContentUtils.h'] if requiresContentUtils else [])
|
||||
+ (['nsCxPusher.h'] if dictionaries else [])
|
||||
+ (['AccessCheck.h'] if hasChromeOnly else [])
|
||||
+ (['mozilla/dom/DOMJSProxyHandler.h'] if hasProxies else [])
|
||||
+ (['xpcprivate.h'] if isEventTarget else [])
|
||||
+ (['nsPIDOMWindow.h'] if len(jsImplemented) != 0 else [])
|
||||
+ (['nsDOMQS.h'] if needsDOMQS["value"] else [])
|
||||
|
@ -10228,7 +10244,8 @@ class GlobalGenRoots():
|
|||
def PrototypeList(config):
|
||||
|
||||
# Prototype ID enum.
|
||||
protos = [d.name for d in config.getDescriptors(hasInterfacePrototypeObject=True)]
|
||||
descriptorsWithPrototype = config.getDescriptors(hasInterfacePrototypeObject=True)
|
||||
protos = [d.name for d in descriptorsWithPrototype]
|
||||
idEnum = CGNamespacedEnum('id', 'ID', ['_ID_Start'] + protos,
|
||||
[0, '_ID_Start'])
|
||||
idEnum = CGList([idEnum])
|
||||
|
@ -10271,16 +10288,14 @@ class GlobalGenRoots():
|
|||
|
||||
curr.append(idEnum)
|
||||
|
||||
traitsDecl = CGGeneric(declare="""
|
||||
traitsDecls = [CGGeneric(declare="""
|
||||
template <prototypes::ID PrototypeID>
|
||||
struct PrototypeTraits;
|
||||
|
||||
template <class ConcreteClass>
|
||||
struct PrototypeIDMap;
|
||||
""")
|
||||
""")]
|
||||
traitsDecls.extend(CGPrototypeTraitsClass(d) for d in descriptorsWithPrototype)
|
||||
|
||||
traitsDecl = CGNamespace.build(['mozilla', 'dom'],
|
||||
CGWrapper(traitsDecl, post='\n'))
|
||||
CGList(traitsDecls, "\n"))
|
||||
|
||||
curr.append(traitsDecl)
|
||||
|
||||
|
|
|
@ -53,13 +53,6 @@ class Configuration:
|
|||
entry.append({})
|
||||
self.descriptors.extend([Descriptor(self, iface, x) for x in entry])
|
||||
|
||||
# Mark the descriptors for which the nativeType corresponds to exactly
|
||||
# one interface.
|
||||
for descriptor in self.descriptors:
|
||||
descriptor.unsharedImplementation = all(
|
||||
d.nativeType != descriptor.nativeType or d == descriptor
|
||||
for d in self.descriptors)
|
||||
|
||||
# Keep the descriptor list sorted for determinism.
|
||||
self.descriptors.sort(lambda x,y: cmp(x.name, y.name))
|
||||
|
||||
|
|
|
@ -11,23 +11,10 @@
|
|||
|
||||
#include "mozilla/dom/PrototypeList.h" // auto-generated
|
||||
|
||||
#include "mozilla/dom/JSSlots.h"
|
||||
|
||||
class nsCycleCollectionParticipant;
|
||||
|
||||
// We use slot 0 for holding the raw object. This is safe for both
|
||||
// globals and non-globals.
|
||||
#define DOM_OBJECT_SLOT 0
|
||||
|
||||
// We use slot 1 for holding the expando object. This is not safe for globals
|
||||
// until bug 760095 is fixed, so that bug blocks converting Window to new
|
||||
// bindings.
|
||||
#define DOM_XRAY_EXPANDO_SLOT 1
|
||||
|
||||
// We use slot 2 for holding either a JS::ObjectValue which points to the cached
|
||||
// SOW or JS::UndefinedValue if this class doesn't need SOWs. This is not safe
|
||||
// for globals until bug 760095 is fixed, so that bug blocks converting Window
|
||||
// to new bindings.
|
||||
#define DOM_OBJECT_SLOT_SOW 2
|
||||
|
||||
// All DOM globals must have a slot at DOM_PROTOTYPE_SLOT.
|
||||
#define DOM_PROTOTYPE_SLOT JSCLASS_GLOBAL_SLOT_COUNT
|
||||
|
||||
|
@ -38,24 +25,6 @@ class nsCycleCollectionParticipant;
|
|||
#define JSCLASS_DOM_GLOBAL JSCLASS_USERBIT1
|
||||
#define JSCLASS_IS_DOMIFACEANDPROTOJSCLASS JSCLASS_USERBIT2
|
||||
|
||||
// NOTE: This is baked into the Ion JIT as 0 in codegen for LGetDOMProperty and
|
||||
// LSetDOMProperty. Those constants need to be changed accordingly if this value
|
||||
// changes.
|
||||
#define DOM_PROTO_INSTANCE_CLASS_SLOT 0
|
||||
|
||||
// Interface objects store a number of reserved slots equal to
|
||||
// DOM_INTERFACE_SLOTS_BASE + number of named constructors.
|
||||
#define DOM_INTERFACE_SLOTS_BASE (DOM_XRAY_EXPANDO_SLOT + 1)
|
||||
|
||||
// Interface prototype objects store a number of reserved slots equal to
|
||||
// DOM_INTERFACE_PROTO_SLOTS_BASE or DOM_INTERFACE_PROTO_SLOTS_BASE + 1 if a
|
||||
// slot for the unforgeable holder is needed.
|
||||
#define DOM_INTERFACE_PROTO_SLOTS_BASE (DOM_XRAY_EXPANDO_SLOT + 1)
|
||||
|
||||
static_assert(DOM_PROTO_INSTANCE_CLASS_SLOT != DOM_XRAY_EXPANDO_SLOT,
|
||||
"Interface prototype object use both of these, so they must "
|
||||
"not be the same slot.");
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
#include "mozilla/Util.h"
|
||||
|
||||
#include "DOMJSProxyHandler.h"
|
||||
#include "mozilla/dom/DOMJSProxyHandler.h"
|
||||
#include "xpcpublic.h"
|
||||
#include "xpcprivate.h"
|
||||
#include "XPCQuickStubs.h"
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/Likely.h"
|
||||
|
||||
#include "xpcpublic.h"
|
||||
#include "jsproxy.h"
|
||||
#include "nsStringGlue.h"
|
||||
|
||||
#define DOM_PROXY_OBJECT_SLOT js::PROXY_PRIVATE_SLOT
|
||||
|
@ -17,6 +17,8 @@
|
|||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class DOMClass;
|
||||
|
||||
enum {
|
||||
JSPROXYSLOT_EXPANDO = 0,
|
||||
JSPROXYSLOT_XRAY_EXPANDO
|
||||
|
@ -24,6 +26,21 @@ enum {
|
|||
|
||||
template<typename T> struct Prefable;
|
||||
|
||||
extern int HandlerFamily;
|
||||
inline void* ProxyFamily() { return &HandlerFamily; }
|
||||
|
||||
inline bool IsDOMProxy(JSObject *obj, const js::Class* clasp)
|
||||
{
|
||||
MOZ_ASSERT(js::GetObjectClass(obj) == clasp);
|
||||
return (js::IsObjectProxyClass(clasp) || js::IsFunctionProxyClass(clasp)) &&
|
||||
js::GetProxyHandler(obj)->family() == ProxyFamily();
|
||||
}
|
||||
|
||||
inline bool IsDOMProxy(JSObject *obj)
|
||||
{
|
||||
return IsDOMProxy(obj, js::GetObjectClass(obj));
|
||||
}
|
||||
|
||||
class BaseDOMProxyHandler : public js::BaseProxyHandler
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
|
||||
/* 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/. */
|
||||
|
||||
/**
|
||||
* This file defines various reserved slot indices used by JavaScript
|
||||
* reflections of DOM objects.
|
||||
*/
|
||||
#ifndef mozilla_dom_DOMSlots_h
|
||||
#define mozilla_dom_DOMSlots_h
|
||||
|
||||
// We use slot 0 for holding the raw object. This is safe for both
|
||||
// globals and non-globals.
|
||||
#define DOM_OBJECT_SLOT 0
|
||||
|
||||
// We use slot 1 for holding the expando object. This is not safe for globals
|
||||
// until bug 760095 is fixed, so that bug blocks converting Window to new
|
||||
// bindings.
|
||||
#define DOM_XRAY_EXPANDO_SLOT 1
|
||||
|
||||
// We use slot 2 for holding either a JS::ObjectValue which points to the cached
|
||||
// SOW or JS::UndefinedValue if this class doesn't need SOWs. This is not safe
|
||||
// for globals until bug 760095 is fixed, so that bug blocks converting Window
|
||||
// to new bindings.
|
||||
#define DOM_OBJECT_SLOT_SOW 2
|
||||
|
||||
// NOTE: This is baked into the Ion JIT as 0 in codegen for LGetDOMProperty and
|
||||
// LSetDOMProperty. Those constants need to be changed accordingly if this value
|
||||
// changes.
|
||||
#define DOM_PROTO_INSTANCE_CLASS_SLOT 0
|
||||
|
||||
// Interface objects store a number of reserved slots equal to
|
||||
// DOM_INTERFACE_SLOTS_BASE + number of named constructors.
|
||||
#define DOM_INTERFACE_SLOTS_BASE (DOM_XRAY_EXPANDO_SLOT + 1)
|
||||
|
||||
// Interface prototype objects store a number of reserved slots equal to
|
||||
// DOM_INTERFACE_PROTO_SLOTS_BASE or DOM_INTERFACE_PROTO_SLOTS_BASE + 1 if a
|
||||
// slot for the unforgeable holder is needed.
|
||||
#define DOM_INTERFACE_PROTO_SLOTS_BASE (DOM_XRAY_EXPANDO_SLOT + 1)
|
||||
|
||||
static_assert(DOM_PROTO_INSTANCE_CLASS_SLOT != DOM_XRAY_EXPANDO_SLOT,
|
||||
"Interface prototype object use both of these, so they must "
|
||||
"not be the same slot.");
|
||||
|
||||
#endif /* mozilla_dom_DOMSlots_h */
|
|
@ -10,6 +10,7 @@
|
|||
#include "jsfriendapi.h"
|
||||
#include "jsapi.h"
|
||||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
#include "nsWrapperCache.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
|
|
@ -22,6 +22,7 @@ EXPORTS.mozilla.dom += [
|
|||
'Date.h',
|
||||
'Errors.msg',
|
||||
'GeneratedAtomList.h',
|
||||
'JSSlots.h',
|
||||
'NonRefcountedDOMObject.h',
|
||||
'Nullable.h',
|
||||
'PrimitiveConversions.h',
|
||||
|
|
|
@ -14,16 +14,16 @@
|
|||
|
||||
#include "BrowserElementParent.h"
|
||||
#include "mozilla/dom/HTMLIFrameElement.h"
|
||||
#include "nsOpenWindowEventDetail.h"
|
||||
#include "nsEventDispatcher.h"
|
||||
#include "nsIDOMCustomEvent.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
#include "nsVariant.h"
|
||||
#include "nsAsyncScrollEventDetail.h"
|
||||
#include "mozilla/dom/BrowserElementDictionariesBinding.h"
|
||||
#include "nsCxPusher.h"
|
||||
#include "GeneratedEventClasses.h"
|
||||
|
||||
using mozilla::dom::Element;
|
||||
using mozilla::dom::HTMLIFrameElement;
|
||||
using mozilla::dom::TabParent;
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -72,7 +72,7 @@ CreateIframe(Element* aOpenerFrameElement, const nsAString& aName, bool aRemote)
|
|||
|
||||
bool
|
||||
DispatchCustomDOMEvent(Element* aFrameElement, const nsAString& aEventName,
|
||||
nsISupports *aDetailValue)
|
||||
JSContext* cx, JS::Handle<JS::Value> aDetailValue)
|
||||
{
|
||||
NS_ENSURE_TRUE(aFrameElement, false);
|
||||
nsIPresShell *shell = aFrameElement->OwnerDoc()->GetShell();
|
||||
|
@ -87,20 +87,24 @@ DispatchCustomDOMEvent(Element* aFrameElement, const nsAString& aEventName,
|
|||
getter_AddRefs(domEvent));
|
||||
NS_ENSURE_TRUE(domEvent, false);
|
||||
|
||||
nsCOMPtr<nsIWritableVariant> detailVariant = new nsVariant();
|
||||
nsresult rv = detailVariant->SetAsISupports(aDetailValue);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
nsCOMPtr<nsIDOMCustomEvent> customEvent = do_QueryInterface(domEvent);
|
||||
NS_ENSURE_TRUE(customEvent, false);
|
||||
customEvent->InitCustomEvent(aEventName,
|
||||
/* bubbles = */ true,
|
||||
/* cancelable = */ false,
|
||||
detailVariant);
|
||||
ErrorResult res;
|
||||
CustomEvent* event = static_cast<CustomEvent*>(customEvent.get());
|
||||
event->InitCustomEvent(cx,
|
||||
aEventName,
|
||||
/* bubbles = */ true,
|
||||
/* cancelable = */ false,
|
||||
aDetailValue,
|
||||
res);
|
||||
if (res.Failed()) {
|
||||
return false;
|
||||
}
|
||||
customEvent->SetTrusted(true);
|
||||
// Dispatch the event.
|
||||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
rv = nsEventDispatcher::DispatchDOMEvent(aFrameElement, nullptr,
|
||||
domEvent, presContext, &status);
|
||||
nsresult rv = nsEventDispatcher::DispatchDOMEvent(aFrameElement, nullptr,
|
||||
domEvent, presContext, &status);
|
||||
return NS_SUCCEEDED(rv);
|
||||
}
|
||||
|
||||
|
@ -119,18 +123,36 @@ DispatchOpenWindowEvent(Element* aOpenerFrameElement,
|
|||
const nsAString& aFeatures)
|
||||
{
|
||||
// Dispatch a CustomEvent at aOpenerFrameElement with a detail object
|
||||
// (nsIOpenWindowEventDetail) containing aPopupFrameElement, aURL, aName, and
|
||||
// (OpenWindowEventDetail) containing aPopupFrameElement, aURL, aName, and
|
||||
// aFeatures.
|
||||
|
||||
// Create the event's detail object.
|
||||
nsRefPtr<nsOpenWindowEventDetail> detail =
|
||||
new nsOpenWindowEventDetail(aURL, aName, aFeatures,
|
||||
aPopupFrameElement->AsDOMNode());
|
||||
OpenWindowEventDetailInitializer detail;
|
||||
detail.mUrl = aURL;
|
||||
detail.mName = aName;
|
||||
detail.mFeatures = aFeatures;
|
||||
detail.mFrameElement = aPopupFrameElement;
|
||||
|
||||
AutoJSContext cx;
|
||||
JS::Rooted<JS::Value> val(cx);
|
||||
|
||||
nsIGlobalObject* sgo = aPopupFrameElement->OwnerDoc()->GetScopeObject();
|
||||
if (!sgo) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> global(cx, sgo->GetGlobalJSObject());
|
||||
JSAutoCompartment ac(cx, global);
|
||||
if (!detail.ToObject(cx, global, &val)) {
|
||||
MOZ_CRASH("Failed to convert dictionary to JS::Value due to OOM.");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool dispatchSucceeded =
|
||||
DispatchCustomDOMEvent(aOpenerFrameElement,
|
||||
NS_LITERAL_STRING("mozbrowseropenwindow"),
|
||||
detail);
|
||||
cx,
|
||||
val);
|
||||
|
||||
// If the iframe is not in some document's DOM at this point, the embedder
|
||||
// has "blocked" the popup.
|
||||
|
@ -263,13 +285,27 @@ NS_IMETHODIMP DispatchAsyncScrollEventRunnable::Run()
|
|||
{
|
||||
nsCOMPtr<Element> frameElement = mTabParent->GetOwnerElement();
|
||||
// Create the event's detail object.
|
||||
nsRefPtr<nsAsyncScrollEventDetail> detail =
|
||||
new nsAsyncScrollEventDetail(mContentRect.x, mContentRect.y,
|
||||
mContentRect.width, mContentRect.height,
|
||||
mContentSize.width, mContentSize.height);
|
||||
AsyncScrollEventDetailInitializer detail;
|
||||
detail.mLeft = mContentRect.x;
|
||||
detail.mTop = mContentRect.y;
|
||||
detail.mWidth = mContentRect.width;
|
||||
detail.mHeight = mContentRect.height;
|
||||
detail.mScrollWidth = mContentRect.width;
|
||||
detail.mScrollHeight = mContentRect.height;
|
||||
AutoSafeJSContext cx;
|
||||
JS::Rooted<JS::Value> val(cx);
|
||||
|
||||
// We can get away with a null global here because
|
||||
// AsyncScrollEventDetail only contains numeric values.
|
||||
if (!detail.ToObject(cx, JS::NullPtr(), &val)) {
|
||||
MOZ_CRASH("Failed to convert dictionary to JS::Value due to OOM.");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
DispatchCustomDOMEvent(frameElement,
|
||||
NS_LITERAL_STRING("mozbrowserasyncscroll"),
|
||||
detail);
|
||||
cx,
|
||||
val);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ public:
|
|||
*
|
||||
* 1) We fire a mozbrowseropenwindow CustomEvent on the opener
|
||||
* iframe element. This event's detail is an instance of
|
||||
* nsIOpenWindowEventDetail.
|
||||
* OpenWindowEventDetail.
|
||||
*
|
||||
* 2) The embedder (the document which contains the opener iframe) can accept
|
||||
* the window.open request by inserting event.detail.frameElement (an iframe
|
||||
|
|
|
@ -6,28 +6,16 @@
|
|||
|
||||
TEST_DIRS += ['mochitest']
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
'nsIAsyncScrollEventDetail.idl',
|
||||
'nsIOpenWindowEventDetail.idl',
|
||||
]
|
||||
|
||||
XPIDL_MODULE = 'dom_browserelement'
|
||||
|
||||
MODULE = 'dom'
|
||||
|
||||
EXPORTS += [
|
||||
'nsAsyncScrollEventDetail.h',
|
||||
'nsOpenWindowEventDetail.h',
|
||||
]
|
||||
|
||||
EXPORTS.mozilla += [
|
||||
'BrowserElementParent.h',
|
||||
]
|
||||
|
||||
CPP_SOURCES += [
|
||||
'BrowserElementParent.cpp',
|
||||
'nsAsyncScrollEventDetail.cpp',
|
||||
'nsOpenWindowEventDetail.cpp',
|
||||
]
|
||||
|
||||
EXTRA_COMPONENTS += [
|
||||
|
|
|
@ -1,62 +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/. */
|
||||
|
||||
#include "nsAsyncScrollEventDetail.h"
|
||||
#include "nsDOMClassInfoID.h"
|
||||
#include "nsIDOMClassInfo.h"
|
||||
#include "nsIClassInfo.h"
|
||||
#include "nsDOMClassInfo.h"
|
||||
|
||||
NS_IMPL_ADDREF(nsAsyncScrollEventDetail)
|
||||
NS_IMPL_RELEASE(nsAsyncScrollEventDetail)
|
||||
NS_INTERFACE_MAP_BEGIN(nsAsyncScrollEventDetail)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIAsyncScrollEventDetail)
|
||||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(AsyncScrollEventDetail)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
DOMCI_DATA(AsyncScrollEventDetail, nsAsyncScrollEventDetail)
|
||||
|
||||
/* readonly attribute float top; */
|
||||
NS_IMETHODIMP nsAsyncScrollEventDetail::GetTop(float *aTop)
|
||||
{
|
||||
*aTop = mTop;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute float left; */
|
||||
NS_IMETHODIMP nsAsyncScrollEventDetail::GetLeft(float *aLeft)
|
||||
{
|
||||
*aLeft = mLeft;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute float width; */
|
||||
NS_IMETHODIMP nsAsyncScrollEventDetail::GetWidth(float *aWidth)
|
||||
{
|
||||
*aWidth = mWidth;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute float height; */
|
||||
NS_IMETHODIMP nsAsyncScrollEventDetail::GetHeight(float *aHeight)
|
||||
{
|
||||
*aHeight = mHeight;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute float scrollWidth; */
|
||||
NS_IMETHODIMP nsAsyncScrollEventDetail::GetScrollWidth(float *aScrollWidth)
|
||||
{
|
||||
*aScrollWidth = mScrollWidth;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute float scrollHeight; */
|
||||
NS_IMETHODIMP nsAsyncScrollEventDetail::GetScrollHeight(float *aScrollHeight)
|
||||
{
|
||||
*aScrollHeight = mScrollHeight;
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
@ -1,36 +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/. */
|
||||
|
||||
#include "nsIAsyncScrollEventDetail.h"
|
||||
|
||||
/**
|
||||
* When we send a mozbrowserasyncscroll event (an instance of CustomEvent), we
|
||||
* use an instance of this class as the event's detail.
|
||||
*/
|
||||
class nsAsyncScrollEventDetail : public nsIAsyncScrollEventDetail
|
||||
{
|
||||
public:
|
||||
nsAsyncScrollEventDetail(const float left, const float top,
|
||||
const float width, const float height,
|
||||
const float contentWidth, const float contentHeigh)
|
||||
: mTop(top)
|
||||
, mLeft(left)
|
||||
, mWidth(width)
|
||||
, mHeight(height)
|
||||
, mScrollWidth(contentWidth)
|
||||
, mScrollHeight(contentHeigh)
|
||||
{}
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIASYNCSCROLLEVENTDETAIL
|
||||
|
||||
private:
|
||||
virtual ~nsAsyncScrollEventDetail() {}
|
||||
const float mTop;
|
||||
const float mLeft;
|
||||
const float mWidth;
|
||||
const float mHeight;
|
||||
const float mScrollWidth;
|
||||
const float mScrollHeight;
|
||||
};
|
|
@ -1,20 +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/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIDOMNode;
|
||||
|
||||
/**
|
||||
* When we send a mozbrowseropenwindow event (an instance of CustomEvent), we
|
||||
* use an instance of this interface as the event's detail.
|
||||
*/
|
||||
[scriptable, uuid(94377af6-956a-4adf-908b-363f7023ae1a)]
|
||||
interface nsIOpenWindowEventDetail : nsISupports
|
||||
{
|
||||
readonly attribute AString url;
|
||||
readonly attribute AString name;
|
||||
readonly attribute AString features;
|
||||
readonly attribute nsIDOMNode frameElement;
|
||||
};
|
|
@ -1,49 +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/. */
|
||||
|
||||
#include "nsOpenWindowEventDetail.h"
|
||||
#include "nsDOMClassInfoID.h"
|
||||
#include "nsIDOMClassInfo.h"
|
||||
#include "nsIClassInfo.h"
|
||||
#include "nsDOMClassInfo.h"
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_1(nsOpenWindowEventDetail, mFrameElement)
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsOpenWindowEventDetail)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsOpenWindowEventDetail)
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsOpenWindowEventDetail)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIOpenWindowEventDetail)
|
||||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(OpenWindowEventDetail)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
DOMCI_DATA(OpenWindowEventDetail, nsOpenWindowEventDetail)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsOpenWindowEventDetail::GetUrl(nsAString& aOut)
|
||||
{
|
||||
aOut.Assign(mURL);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsOpenWindowEventDetail::GetName(nsAString& aOut)
|
||||
{
|
||||
aOut.Assign(mName);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsOpenWindowEventDetail::GetFeatures(nsAString& aOut)
|
||||
{
|
||||
aOut.Assign(mFeatures);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsOpenWindowEventDetail::GetFrameElement(nsIDOMNode** aOut)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> out = mFrameElement;
|
||||
out.forget(aOut);
|
||||
return NS_OK;
|
||||
}
|
|
@ -1,39 +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/. */
|
||||
|
||||
#include "nsIOpenWindowEventDetail.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsString.h"
|
||||
|
||||
/**
|
||||
* When we send a mozbrowseropenwindow event (an instance of CustomEvent), we
|
||||
* use an instance of this class as the event's detail.
|
||||
*/
|
||||
class nsOpenWindowEventDetail : public nsIOpenWindowEventDetail
|
||||
{
|
||||
public:
|
||||
nsOpenWindowEventDetail(const nsAString& aURL,
|
||||
const nsAString& aName,
|
||||
const nsAString& aFeatures,
|
||||
nsIDOMNode* aFrameElement)
|
||||
: mURL(aURL)
|
||||
, mName(aName)
|
||||
, mFeatures(aFeatures)
|
||||
, mFrameElement(aFrameElement)
|
||||
{}
|
||||
|
||||
virtual ~nsOpenWindowEventDetail() {}
|
||||
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS(nsOpenWindowEventDetail)
|
||||
NS_DECL_NSIOPENWINDOWEVENTDETAIL
|
||||
|
||||
private:
|
||||
const nsString mURL;
|
||||
const nsString mName;
|
||||
const nsString mFeatures;
|
||||
nsCOMPtr<nsIDOMNode> mFrameElement;
|
||||
};
|
|
@ -1494,7 +1494,7 @@ IDBObjectStore::StructuredCloneWriteCallback(JSContext* aCx,
|
|||
FileManager* fileManager = transaction->Database()->Manager();
|
||||
|
||||
file::FileHandle* fileHandle = nullptr;
|
||||
if (NS_SUCCEEDED(UnwrapObject<file::FileHandle>(aCx, aObj, fileHandle))) {
|
||||
if (NS_SUCCEEDED(UNWRAP_OBJECT(FileHandle, aCx, aObj, fileHandle))) {
|
||||
nsRefPtr<FileInfo> fileInfo = fileHandle->GetFileInfo();
|
||||
|
||||
// Throw when trying to store non IDB file handles or IDB file handles
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче