Merge from mozilla-inbound.

This commit is contained in:
Jan de Mooij 2013-02-08 09:20:14 +01:00
commit b4e740ec60
550 changed files with 13932 additions and 9532 deletions

View File

@ -207,12 +207,17 @@ SettingsListener.observe('devtools.debugger.remote-enabled', false, function(val
#ifdef MOZ_WIDGET_GONK
let enableAdb = value;
if (Services.prefs.getBoolPref('marionette.defaultPrefs.enabled')) {
// Marionette is enabled. Force adb on, since marionette requires remote
// debugging to be disabled (we don't want adb to track the remote debugger
// setting).
try {
if (Services.prefs.getBoolPref('marionette.defaultPrefs.enabled')) {
// Marionette is enabled. Force adb on, since marionette requires remote
// debugging to be disabled (we don't want adb to track the remote debugger
// setting).
enableAdb = true;
enableAdb = true;
}
} catch (e) {
// This means that the pref doesn't exist. Which is fine. We just leave
// enableAdb alone.
}
// Configure adb.

View File

@ -46,12 +46,6 @@ let Keyboard = {
let frameLoader = subject.QueryInterface(Ci.nsIFrameLoader);
let mm = frameLoader.messageManager;
mm.addMessageListener('Forms:Input', this);
try {
mm.loadFrameScript(kFormsFrameScript, true);
} catch (e) {
dump('Error loading ' + kFormsFrameScript + ' as frame script: ' + e + '\n');
}
},
receiveMessage: function keyboardReceiveMessage(msg) {

View File

@ -43,7 +43,6 @@ ProcessGlobal.prototype = {
switch (topic) {
case 'app-startup': {
Services.obs.addObserver(this, 'console-api-log-event', false);
Services.obs.addObserver(this, 'remote-browser-frame-shown', false);
break;
}
case 'console-api-log-event': {

View File

@ -19,8 +19,9 @@ function log(msg) {
#ifdef MOZ_WIDGET_GONK
let librecovery = (function() {
let library;
try {
let library = ctypes.open("librecovery.so");
library = ctypes.open("librecovery.so");
} catch (e) {
log("Unable to open librecovery.so");
throw Cr.NS_ERROR_FAILURE;

View File

@ -908,8 +908,13 @@ var SocialToolbar = {
toolbarButton.setAttribute("tooltiptext", icon.label);
let badge = icon.counter || "";
if (toolbarButton.getAttribute("badge") != badge)
toolbarButton.setAttribute("badge", badge);
toolbarButton.setAttribute("badge", badge);
let ariaLabel = icon.label;
// if there is a badge value, we must use a localizable string to insert it.
if (badge)
ariaLabel = gNavigatorBundle.getFormattedString("social.aria.toolbarButtonBadgeText",
[ariaLabel, badge]);
toolbarButton.setAttribute("aria-label", ariaLabel);
}
let socialToolbarItem = document.getElementById("social-toolbar-item");
socialToolbarItem.appendChild(toolbarButtons);

View File

@ -4681,9 +4681,14 @@ var TabsProgressListener = {
// We can't look for this during onLocationChange since at that point the
// document URI is not yet the about:-uri of the error page.
let doc = aWebProgress.DOMWindow.document;
if (aStateFlags & Ci.nsIWebProgressListener.STATE_STOP &&
Components.isSuccessCode(aStatus) &&
aWebProgress.DOMWindow.document.documentURI.startsWith("about:")) {
doc.documentURI.startsWith("about:") &&
!doc.documentElement.hasAttribute("hasBrowserHandlers")) {
// STATE_STOP may be received twice for documents, thus store an
// attribute to ensure handling it just once.
doc.documentElement.setAttribute("hasBrowserHandlers", "true");
aBrowser.addEventListener("click", BrowserOnClick, true);
aBrowser.addEventListener("pagehide", function onPageHide(event) {
if (event.target.defaultView.frameElement)
@ -4693,7 +4698,7 @@ var TabsProgressListener = {
}, true);
// We also want to make changes to page UI for unprivileged about pages.
BrowserOnAboutPageLoad(aWebProgress.DOMWindow.document);
BrowserOnAboutPageLoad(doc);
}
},

View File

@ -8,8 +8,7 @@ let proxyPrefValue;
function test() {
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
window.addEventListener("DOMContentLoaded", checkPage, false);
let tab = gBrowser.selectedTab = gBrowser.addTab();
// Go offline and disable the proxy and cache, then try to load the test URL.
Services.io.offline = true;
@ -22,16 +21,29 @@ function test() {
Services.prefs.setBoolPref("browser.cache.disk.enable", false);
Services.prefs.setBoolPref("browser.cache.memory.enable", false);
content.location = "http://example.com/";
window.addEventListener("DOMContentLoaded", function load() {
if (content.location == "about:blank") {
info("got about:blank, which is expected once, so return");
return;
}
window.removeEventListener("DOMContentLoaded", load, false);
let observer = new MutationObserver(function (mutations) {
for (let mutation of mutations) {
if (mutation.attributeName == "hasBrowserHandlers") {
observer.disconnect();
checkPage();
return;
}
}
});
let docElt = tab.linkedBrowser.contentDocument.documentElement;
observer.observe(docElt, { attributes: true });
}, false);
}
function checkPage() {
if(content.location == "about:blank") {
info("got about:blank, which is expected once, so return");
return;
}
window.removeEventListener("DOMContentLoaded", checkPage, false);
ok(Services.io.offline, "Setting Services.io.offline to true.");
is(gBrowser.contentDocument.documentURI.substring(0,27),
"about:neterror?e=netOffline", "Loading the Offline mode neterror page.");

View File

@ -110,11 +110,15 @@ var tests = {
}, function () {
let badge = statusIcon.getAttribute("badge");
is(badge, "42", "status value is correct");
// If there is a counter, the aria-label should reflect it.
is(statusIcon.getAttribute("aria-label"), "Test Ambient 1 \u2046 (42)");
ambience.counter = 0;
Social.provider.setAmbientNotification(ambience);
badge = statusIcon.getAttribute("badge");
is(badge, "", "status value is correct");
// If there is no counter, the aria-label should be the same as the label
is(statusIcon.getAttribute("aria-label"), "Test Ambient 1 \u2046");
// The menu bar isn't as easy to instrument on Mac.
if (navigator.platform.contains("Mac"))

View File

@ -930,8 +930,14 @@ DownloadsPlacesView.prototype = {
}
if (shouldCreateShell) {
let shell = new DownloadElementShell(aDataItem, aPlacesNode,
this._getAnnotationsFor(downloadURI));
// Bug 836271: The annotations for a url should be cached only when the
// places node is available, i.e. when we know we we'd be notified for
// annoation changes.
// Otherwise we may cache NOT_AVILABLE values first for a given session
// download, and later use these NOT_AVILABLE values when a history
// download for the same URL is added.
let cachedAnnotations = aPlacesNode ? this._getAnnotationsFor(downloadURI) : null;
let shell = new DownloadElementShell(aDataItem, aPlacesNode, cachedAnnotations);
newOrUpdatedShell = shell;
shellsForURI.add(shell);
if (aDataItem)
@ -1173,42 +1179,63 @@ DownloadsPlacesView.prototype = {
let suppressOnSelect = this._richlistbox.suppressOnSelect;
this._richlistbox.suppressOnSelect = true;
// Remove the invalidated history downloads from the list and unset the
// places node for data downloads.
// Loop backwards since _removeHistoryDownloadFromView may removeChild().
for (let i = this._richlistbox.childNodes.length - 1; i >= 0; --i) {
let element = this._richlistbox.childNodes[i];
if (element._shell.placesNode)
this._removeHistoryDownloadFromView(element._shell.placesNode);
try {
// Remove the invalidated history downloads from the list and unset the
// places node for data downloads.
// Loop backwards since _removeHistoryDownloadFromView may removeChild().
for (let i = this._richlistbox.childNodes.length - 1; i >= 0; --i) {
let element = this._richlistbox.childNodes[i];
if (element._shell.placesNode)
this._removeHistoryDownloadFromView(element._shell.placesNode);
}
}
finally {
this._richlistbox.suppressOnSelect = suppressOnSelect;
}
let elementsToAppendFragment = document.createDocumentFragment();
for (let i = 0; i < aContainer.childCount; i++) {
try {
this._addDownloadData(null, aContainer.getChild(i), false,
elementsToAppendFragment);
if (aContainer.childCount > 0) {
let elementsToAppendFragment = document.createDocumentFragment();
for (let i = 0; i < aContainer.childCount; i++) {
try {
this._addDownloadData(null, aContainer.getChild(i), false,
elementsToAppendFragment);
}
catch(ex) {
Cu.reportError(ex);
}
}
catch(ex) {
Cu.reportError(ex);
// _addDownloadData may not add new elements if there were already
// data items in place.
if (elementsToAppendFragment.firstChild) {
this._appendDownloadsFragment(elementsToAppendFragment);
this._ensureVisibleElementsAreActive();
}
}
this._appendDownloadsFragment(elementsToAppendFragment);
this._ensureVisibleElementsAreActive();
this._richlistbox.suppressOnSelect = suppressOnSelect;
goUpdateDownloadCommands();
},
_appendDownloadsFragment: function DPV__appendDownloadsFragment(aDOMFragment) {
// Workaround multiple reflows hang by removing the richlistbox
// and adding it back when we're done.
// Hack for bug 836283: reset xbl fields to their old values after the
// binding is reattached to avoid breaking the selection state
let xblFields = new Map();
for (let [key, value] in Iterator(this._richlistbox)) {
xblFields.set(key, value);
}
let parentNode = this._richlistbox.parentNode;
let nextSibling = this._richlistbox.nextSibling;
parentNode.removeChild(this._richlistbox);
this._richlistbox.appendChild(aDOMFragment);
parentNode.insertBefore(this._richlistbox, nextSibling);
for (let [key, value] of xblFields) {
this._richlistbox[key] = value;
}
},
nodeInserted: function DPV_nodeInserted(aParent, aPlacesNode) {

View File

@ -334,30 +334,26 @@ this.PlacesUIUtils = {
* See documentation at the top of bookmarkProperties.js
* @param aWindow
* Owner window for the new dialog.
* @param aResizable [optional]
* Whether the dialog is allowed to resize. Do not pass this for new
* callers since it's deprecated. It'll be removed in future releases.
*
* @see documentation at the top of bookmarkProperties.js
* @return true if any transaction has been performed, false otherwise.
*/
showBookmarkDialog:
function PUIU_showBookmarkDialog(aInfo, aParentWindow, aResizable) {
function PUIU_showBookmarkDialog(aInfo, aParentWindow) {
// Preserve size attributes differently based on the fact the dialog has
// a folder picker or not. If the picker is visible, the dialog should
// be resizable since it may not show enough content for the folders
// hierarchy.
let hasFolderPicker = !("hiddenRows" in aInfo) ||
aInfo.hiddenRows.indexOf("folderPicker") == -1;
let resizable = aResizable !== undefined ? aResizable : hasFolderPicker;
// Use a different chrome url, since this allows to persist different sizes,
// based on resizability of the dialog.
let dialogURL = resizable ?
let dialogURL = hasFolderPicker ?
"chrome://browser/content/places/bookmarkProperties2.xul" :
"chrome://browser/content/places/bookmarkProperties.xul";
let features =
"centerscreen,chrome,modal,resizable=" + (resizable ? "yes" : "no");
"centerscreen,chrome,modal,resizable=" + (hasFolderPicker ? "yes" : "no");
aParentWindow.openDialog(dialogURL, "", features, aInfo);
return ("performed" in aInfo && aInfo.performed);

View File

@ -399,6 +399,9 @@ social.error.ok.accesskey=O
social.error.closeSidebar.label=Close This Sidebar
social.error.closeSidebar.accesskey=C
# LOCALIZATION NOTE: %1$S is the label for the toolbar button, %2$S is the associated badge numbering that the social provider may provide.
social.aria.toolbarButtonBadgeText=%1$S (%2$S)
# Identity notifications popups
identity.termsOfService = Terms of Service
identity.privacyPolicy = Privacy Policy

View File

@ -21,7 +21,6 @@ EXTRA_JS_MODULES = \
NewTabUtils.jsm \
offlineAppCache.jsm \
SignInToWebsite.jsm \
TelemetryTimestamps.jsm \
webappsUI.jsm \
webrtcUI.jsm \
KeywordURLResetPrompter.jsm \

View File

@ -20,7 +20,6 @@ include $(topsrcdir)/config/rules.mk
_BROWSER_FILES = \
browser_NetworkPrioritizer.js \
browser_TelemetryTimestamps.js \
# bug 793906 - temporarily disabling desktop UI while working on b2g
# browser_SignInToWebsite.js \
$(NULL)

View File

@ -1,74 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
function getSimpleMeasurementsFromTelemetryPing() {
const TelemetryPing = Cc["@mozilla.org/base/telemetry-ping;1"].getService(Ci.nsITelemetryPing);
let ping = TelemetryPing.getPayload();
return ping.simpleMeasurements;
}
function test() {
waitForExplicitFinish()
const Telemetry = Services.telemetry;
Telemetry.asyncFetchTelemetryData(function () {
actualTest();
finish();
});
}
function actualTest() {
// Test the module logic
let tmp = {};
Cu.import("resource:///modules/TelemetryTimestamps.jsm", tmp);
let TelemetryTimestamps = tmp.TelemetryTimestamps;
let now = Date.now();
TelemetryTimestamps.add("foo");
ok(TelemetryTimestamps.get().foo, "foo was added");
ok(TelemetryTimestamps.get().foo >= now, "foo has a reasonable value");
// Add timestamp with value
// Use a value far in the future since TelemetryPing substracts the time of
// process initialization.
const YEAR_4000_IN_MS = 64060588800000;
TelemetryTimestamps.add("bar", YEAR_4000_IN_MS);
ok(TelemetryTimestamps.get().bar, "bar was added");
is(TelemetryTimestamps.get().bar, YEAR_4000_IN_MS, "bar has the right value");
// Can't add the same timestamp twice
TelemetryTimestamps.add("bar", 2);
is(TelemetryTimestamps.get().bar, YEAR_4000_IN_MS, "bar wasn't overwritten");
let threw = false;
try {
TelemetryTimestamps.add("baz", "this isn't a number");
} catch (ex) {
threw = true;
}
ok(threw, "adding baz threw");
ok(!TelemetryTimestamps.get().baz, "no baz was added");
// Test that the data gets added to the telemetry ping properly
let simpleMeasurements = getSimpleMeasurementsFromTelemetryPing();
ok(simpleMeasurements, "got simple measurements from ping data");
ok(simpleMeasurements.foo > 1, "foo was included");
ok(simpleMeasurements.bar > 1, "bar was included");
ok(!simpleMeasurements.baz, "baz wasn't included since it wasn't added");
// Check browser timestamps that we add
let props = [
// These can't be reliably tested when the test is run alone
//"delayedStartupStarted",
//"delayedStartupFinished",
"sessionRestoreInitialized",
// This doesn't get hit in the testing profile
//"sessionRestoreRestoring"
];
props.forEach(function (p) {
let value = simpleMeasurements[p];
ok(value, p + " exists");
ok(!isNaN(value), p + " is a number");
ok(value > 0, p + " value is reasonable");
});
}

View File

@ -81,6 +81,7 @@ class JarMaker(object):
self.l10nbase = None
self.l10nmerge = None
self.relativesrcdir = None
self.rootManifestAppId = None
def getCommandLineParser(self):
'''Get a optparse.OptionParser for jarmaker.
@ -117,6 +118,8 @@ class JarMaker(object):
help="relativesrcdir to be used for localization")
p.add_option('-j', type="string",
help="jarfile directory")
p.add_option('--root-manifest-entry-appid', type="string",
help="add an app id specific root chrome manifest entry.")
return p
def processIncludes(self, includes):
@ -156,6 +159,17 @@ class JarMaker(object):
self.updateManifest(chromeManifest, chromebasepath % 'chrome/',
register)
# If requested, add a root chrome manifest entry (assumed to be in the parent directory
# of chromeManifest) with the application specific id. In cases where we're building
# lang packs, the root manifest must know about application sub directories.
if self.rootManifestAppId:
rootChromeManifest = os.path.join(os.path.normpath(os.path.dirname(chromeManifest)),
'..', 'chrome.manifest')
rootChromeManifest = os.path.normpath(rootChromeManifest)
chromeDir = os.path.basename(os.path.dirname(os.path.normpath(chromeManifest)))
logging.info("adding '%s' entry to root chrome manifest appid=%s" % (chromeDir, self.rootManifestAppId))
addEntriesToListFile(rootChromeManifest, ['manifest %s/chrome.manifest application=%s' % (chromeDir, self.rootManifestAppId)])
def updateManifest(self, manifestPath, chromebasepath, register):
'''updateManifest replaces the % in the chrome registration entries
with the given chrome base path, and updates the given manifest file.
@ -447,6 +461,8 @@ def main():
elif options.locale_mergedir:
p.error('l10n-base required when using locale-mergedir')
jm.localedirs = options.l10n_src
if options.root_manifest_entry_appid:
jm.rootManifestAppId = options.root_manifest_entry_appid
noise = logging.INFO
if options.verbose is not None:
noise = (options.verbose and logging.DEBUG) or logging.WARN

View File

@ -1441,11 +1441,30 @@ $(FINAL_TARGET)/chrome: $(call mkdir_deps,$(FINAL_TARGET)/chrome)
ifneq (,$(wildcard $(JAR_MANIFEST)))
ifndef NO_DIST_INSTALL
ifdef XPI_NAME
ifdef XPI_ROOT_APPID
# For add-on packaging we may specify that an application
# sub-dir should be added to the root chrome manifest with
# a specific application id.
MAKE_JARS_FLAGS += --root-manifest-entry-appid="$(XPI_ROOT_APPID)"
endif
# if DIST_SUBDIR is defined but XPI_ROOT_APPID is not there's
# no way langpacks will get packaged right, so error out.
ifneq (,$(DIST_SUBDIR))
ifndef XPI_ROOT_APPID
$(error XPI_ROOT_APPID is not defined - langpacks will break.)
endif
endif
endif
libs realchrome:: $(CHROME_DEPS) $(FINAL_TARGET)/chrome
$(PYTHON) $(MOZILLA_DIR)/config/JarMaker.py \
$(QUIET) -j $(FINAL_TARGET)/chrome \
$(MAKE_JARS_FLAGS) $(XULPPFLAGS) $(DEFINES) $(ACDEFINES) \
$(JAR_MANIFEST)
endif
endif

View File

@ -5813,12 +5813,13 @@ fi
MOZ_PATH_PROG(JAVA, java, :, [$JAVA_PATH])
MOZ_PATH_PROG(JAVAC, javac, :, [$JAVA_PATH])
MOZ_PATH_PROG(JAVAH, javah, :, [$JAVA_PATH])
MOZ_PATH_PROG(JAR, jar, :, [$JAVA_PATH])
if test -n "${JAVA_BIN_PATH}" -o \
\( "$OS_TARGET" = Android -a x"$MOZ_WIDGET_TOOLKIT" != x"gonk" \); then
if test -z "$JAVA" -o "$JAVA" = ":" -o -z "$JAVAC" -o "$JAVAC" = ":" -o -z "$JAR" -o "$JAR" = ":"; then
AC_MSG_ERROR([The programs java, javac and jar were not found. Set \$JAVA_HOME to your java sdk directory or use --with-java-bin-path={java-bin-dir}])
if test -z "$JAVA" -o "$JAVA" = ":" -o -z "$JAVAC" -o "$JAVAC" = ":" -o -z "$JAVAH" -o "$JAVAH" = ":" -o -z "$JAR" -o "$JAR" = ":"; then
AC_MSG_ERROR([The programs java, javac, javah and jar were not found. Set \$JAVA_HOME to your java sdk directory or use --with-java-bin-path={java-bin-dir}])
fi
fi
@ -8455,6 +8456,7 @@ AC_SUBST(TOOLCHAIN_PREFIX)
AC_SUBST(JAVA)
AC_SUBST(JAVAC)
AC_SUBST(JAVAH)
AC_SUBST(JAR)
AC_SUBST(MOZ_PROFILELOCKING)

View File

@ -7541,15 +7541,30 @@ nsDocument::UnblockOnload(bool aFireSync)
--mOnloadBlockCount;
// If mScriptGlobalObject is null, we shouldn't be messing with the loadgroup
// -- it's not ours.
if (mOnloadBlockCount == 0 && mScriptGlobalObject) {
if (aFireSync && mAsyncOnloadBlockCount == 0) {
// Increment mOnloadBlockCount, since DoUnblockOnload will decrement it
++mOnloadBlockCount;
DoUnblockOnload();
} else {
PostUnblockOnloadEvent();
if (mOnloadBlockCount == 0) {
if (mScriptGlobalObject) {
// Only manipulate the loadgroup in this case, because if mScriptGlobalObject
// is null, it's not ours.
if (aFireSync && mAsyncOnloadBlockCount == 0) {
// Increment mOnloadBlockCount, since DoUnblockOnload will decrement it
++mOnloadBlockCount;
DoUnblockOnload();
} else {
PostUnblockOnloadEvent();
}
} else if (mIsBeingUsedAsImage) {
// To correctly unblock onload for a document that contains an SVG
// image, we need to know when all of the SVG document's resources are
// done loading, in a way comparable to |window.onload|. We fire this
// event to indicate that the SVG should be considered fully loaded.
// Because scripting is disabled on SVG-as-image documents, this event
// is not accessible to content authors. (See bug 837135.)
nsRefPtr<nsAsyncDOMEvent> e =
new nsAsyncDOMEvent(this,
NS_LITERAL_STRING("MozSVGAsImageDocumentLoad"),
false,
false);
e->PostDOMEvent();
}
}
}

View File

@ -175,6 +175,10 @@ DEFINE_VK_INTERNAL(_CLOSE_CURLY_BRACKET),
DEFINE_VK_INTERNAL(_TILDE),
DEFINE_VK_INTERNAL(_VOLUME_MUTE),
DEFINE_VK_INTERNAL(_VOLUME_DOWN),
DEFINE_VK_INTERNAL(_VOLUME_UP),
DEFINE_VK_INTERNAL(_COMMA),
DEFINE_VK_INTERNAL(_PERIOD),
DEFINE_VK_INTERNAL(_SLASH),

View File

@ -905,7 +905,7 @@ nsEventDispatcher::CreateEvent(nsPresContext* aPresContext,
if (aEventType.LowerCaseEqualsLiteral("customevent"))
return NS_NewDOMCustomEvent(aDOMEvent, aPresContext, nullptr);
if (aEventType.LowerCaseEqualsLiteral("mozsmsevent"))
return NS_NewDOMSmsEvent(aDOMEvent, aPresContext, nullptr);
return NS_NewDOMMozSmsEvent(aDOMEvent, aPresContext, nullptr);
if (aEventType.LowerCaseEqualsLiteral("storageevent")) {
return NS_NewDOMStorageEvent(aDOMEvent, aPresContext, nullptr);
}

View File

@ -66,7 +66,6 @@
#include "nsCaret.h"
#include "nsSubDocumentFrame.h"
#include "nsIFrameTraversal.h"
#include "nsLayoutCID.h"
#include "nsLayoutUtils.h"
#include "nsIInterfaceRequestorUtils.h"
@ -117,8 +116,6 @@ using namespace mozilla::dom;
static const nsIntPoint kInvalidRefPoint = nsIntPoint(-1,-1);
static NS_DEFINE_CID(kFrameTraversalCID, NS_FRAMETRAVERSAL_CID);
static bool sLeftClickOnly = true;
static bool sKeyCausesActivation = true;
static uint32_t sESMInstanceCount = 0;

View File

@ -34,3 +34,6 @@ skip-if(Android||B2G) == 649134-2.html 649134-2-ref.html
== hidden-2.svg hidden-2-ref.svg
== href-attr-change-restyles.html href-attr-change-restyles-ref.html
== figure.html figure-ref.html
== table-border-1.html table-border-1-ref.html
== table-border-2.html table-border-2-ref.html
!= table-border-2.html table-border-2-notref.html

View File

@ -0,0 +1,46 @@
<!DOCTYPE html>
<meta charset=utf-8>
<title>Table borders</title>
<style>
table {
border-width: 1px;
border-style: outset;
}
td {
border-width: 1px;
border-style: inset;
}
</style>
<table>
<tr><td>Test
</table>
<table>
<tr><td>Test
</table>
<table>
<tr><td>Test
</table>
<table>
<tr><td>Test
</table>
<table>
<tr><td>Test
</table>
<table>
<tr><td>Test
</table>
<table>
<tr><td>Test
</table>
<table>
<tr><td>Test
</table>
<table>
<tr><td>Test
</table>
<table>
<tr><td>Test
</table>
<table>
<tr><td>Test
</table>

View File

@ -0,0 +1,36 @@
<!DOCTYPE html>
<meta charset=utf-8>
<title>Table borders</title>
<table border>
<tr><td>Test
</table>
<table border="">
<tr><td>Test
</table>
<table border=null>
<tr><td>Test
</table>
<table border=undefined>
<tr><td>Test
</table>
<table border=foo>
<tr><td>Test
</table>
<table border=1>
<tr><td>Test
</table>
<table border=1foo>
<tr><td>Test
</table>
<table border=1%>
<tr><td>Test
</table>
<table border=-1>
<tr><td>Test
</table>
<table border=-1foo>
<tr><td>Test
</table>
<table border=-1%>
<tr><td>Test
</table>

View File

@ -0,0 +1,40 @@
<!DOCTYPE html>
<meta charset=utf-8>
<title>Table borders</title>
<style>
table {
border-width: 1px;
border-style: outset;
}
td {
border-width: 1px;
border-style: inset;
}
</style>
<table>
<tr><td>Test
</table>
<table>
<tr><td>Test
</table>
<table>
<tr><td>Test
</table>
<table>
<tr><td>Test
</table>
<table>
<tr><td>Test
</table>
<table>
<tr><td>Test
</table>
<table>
<tr><td>Test
</table>
<table>
<tr><td>Test
</table>
<table>
<tr><td>Test
</table>

View File

@ -0,0 +1,30 @@
<!DOCTYPE html>
<meta charset=utf-8>
<title>Table borders</title>
<table>
<tr><td>Test
</table>
<table>
<tr><td>Test
</table>
<table>
<tr><td>Test
</table>
<table>
<tr><td>Test
</table>
<table>
<tr><td>Test
</table>
<table>
<tr><td>Test
</table>
<table>
<tr><td>Test
</table>
<table>
<tr><td>Test
</table>
<table>
<tr><td>Test
</table>

View File

@ -0,0 +1,30 @@
<!DOCTYPE html>
<meta charset=utf-8>
<title>Table borders</title>
<table border=0>
<tr><td>Test
</table>
<table border=0foo>
<tr><td>Test
</table>
<table border=0%>
<tr><td>Test
</table>
<table border=+0>
<tr><td>Test
</table>
<table border=+0foo>
<tr><td>Test
</table>
<table border=+0%>
<tr><td>Test
</table>
<table border=-0>
<tr><td>Test
</table>
<table border=-0foo>
<tr><td>Test
</table>
<table border=-0%>
<tr><td>Test
</table>

View File

@ -3,93 +3,45 @@
* 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/Util.h"
#include "nsGenericHTMLElement.h"
#include "nsIDOMHTMLHRElement.h"
#include "nsIDOMEventTarget.h"
#include "nsGkAtoms.h"
#include "nsStyleConsts.h"
#include "nsPresContext.h"
#include "nsMappedAttributes.h"
#include "nsAttrValueInlines.h"
#include "nsRuleData.h"
#include "nsCSSProps.h"
using namespace mozilla;
using namespace mozilla::dom;
class nsHTMLHRElement : public nsGenericHTMLElement,
public nsIDOMHTMLHRElement
{
public:
nsHTMLHRElement(already_AddRefed<nsINodeInfo> aNodeInfo);
virtual ~nsHTMLHRElement();
// nsISupports
NS_DECL_ISUPPORTS_INHERITED
// nsIDOMNode
NS_FORWARD_NSIDOMNODE_TO_NSINODE
// nsIDOMElement
NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
// nsIDOMHTMLElement
NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
// nsIDOMHTMLHRElement
NS_DECL_NSIDOMHTMLHRELEMENT
virtual bool ParseAttribute(int32_t aNamespaceID,
nsIAtom* aAttribute,
const nsAString& aValue,
nsAttrValue& aResult);
NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
virtual nsXPCClassInfo* GetClassInfo();
virtual nsIDOMNode* AsDOMNode() { return this; }
};
#include "mozilla/dom/HTMLHRElement.h"
#include "mozilla/dom/HTMLHRElementBinding.h"
NS_IMPL_NS_NEW_HTML_ELEMENT(HR)
DOMCI_NODE_DATA(HTMLHRElement, mozilla::dom::HTMLHRElement)
namespace mozilla {
namespace dom {
nsHTMLHRElement::nsHTMLHRElement(already_AddRefed<nsINodeInfo> aNodeInfo)
HTMLHRElement::HTMLHRElement(already_AddRefed<nsINodeInfo> aNodeInfo)
: nsGenericHTMLElement(aNodeInfo)
{
SetIsDOMBinding();
}
nsHTMLHRElement::~nsHTMLHRElement()
HTMLHRElement::~HTMLHRElement()
{
}
NS_IMPL_ADDREF_INHERITED(HTMLHRElement, Element)
NS_IMPL_RELEASE_INHERITED(HTMLHRElement, Element)
NS_IMPL_ADDREF_INHERITED(nsHTMLHRElement, Element)
NS_IMPL_RELEASE_INHERITED(nsHTMLHRElement, Element)
DOMCI_NODE_DATA(HTMLHRElement, nsHTMLHRElement)
// QueryInterface implementation for nsHTMLHRElement
NS_INTERFACE_TABLE_HEAD(nsHTMLHRElement)
NS_HTML_CONTENT_INTERFACE_TABLE1(nsHTMLHRElement,
// QueryInterface implementation for HTMLHRElement
NS_INTERFACE_TABLE_HEAD(HTMLHRElement)
NS_HTML_CONTENT_INTERFACE_TABLE1(HTMLHRElement,
nsIDOMHTMLHRElement)
NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLHRElement,
NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(HTMLHRElement,
nsGenericHTMLElement)
NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLHRElement)
NS_IMPL_ELEMENT_CLONE(nsHTMLHRElement)
NS_IMPL_ELEMENT_CLONE(HTMLHRElement)
NS_IMPL_STRING_ATTR(nsHTMLHRElement, Align, align)
NS_IMPL_BOOL_ATTR(nsHTMLHRElement, NoShade, noshade)
NS_IMPL_STRING_ATTR(nsHTMLHRElement, Size, size)
NS_IMPL_STRING_ATTR(nsHTMLHRElement, Width, width)
NS_IMPL_STRING_ATTR(nsHTMLHRElement, Color, color)
NS_IMPL_STRING_ATTR(HTMLHRElement, Align, align)
NS_IMPL_BOOL_ATTR(HTMLHRElement, NoShade, noshade)
NS_IMPL_STRING_ATTR(HTMLHRElement, Size, size)
NS_IMPL_STRING_ATTR(HTMLHRElement, Width, width)
NS_IMPL_STRING_ATTR(HTMLHRElement, Color, color)
static const nsAttrValue::EnumTable kAlignTable[] = {
{ "left", NS_STYLE_TEXT_ALIGN_LEFT },
@ -99,10 +51,10 @@ static const nsAttrValue::EnumTable kAlignTable[] = {
};
bool
nsHTMLHRElement::ParseAttribute(int32_t aNamespaceID,
nsIAtom* aAttribute,
const nsAString& aValue,
nsAttrValue& aResult)
HTMLHRElement::ParseAttribute(int32_t aNamespaceID,
nsIAtom* aAttribute,
const nsAString& aValue,
nsAttrValue& aResult)
{
if (aNamespaceID == kNameSpaceID_None) {
if (aAttribute == nsGkAtoms::width) {
@ -289,7 +241,7 @@ MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
}
NS_IMETHODIMP_(bool)
nsHTMLHRElement::IsAttributeMapped(const nsIAtom* aAttribute) const
HTMLHRElement::IsAttributeMapped(const nsIAtom* aAttribute) const
{
static const MappedAttributeEntry attributes[] = {
{ &nsGkAtoms::align },
@ -310,7 +262,17 @@ nsHTMLHRElement::IsAttributeMapped(const nsIAtom* aAttribute) const
nsMapRuleToAttributesFunc
nsHTMLHRElement::GetAttributeMappingFunction() const
HTMLHRElement::GetAttributeMappingFunction() const
{
return &MapAttributesIntoRule;
}
JSObject*
HTMLHRElement::WrapNode(JSContext* aCx, JSObject* aScope,
bool* aTriedToWrap)
{
return HTMLHRElementBinding::Wrap(aCx, aScope, this, aTriedToWrap);
}
} // namespace mozilla
} // namespace dom

View File

@ -0,0 +1,93 @@
/* -*- 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/. */
#ifndef mozilla_dom_HTMLHRElement_h
#define mozilla_dom_HTMLHRElement_h
#include "nsGenericHTMLElement.h"
#include "nsIDOMHTMLHRElement.h"
#include "nsIDOMEventTarget.h"
#include "nsMappedAttributes.h"
#include "nsAttrValueInlines.h"
#include "nsRuleData.h"
namespace mozilla {
namespace dom {
class HTMLHRElement : public nsGenericHTMLElement,
public nsIDOMHTMLHRElement
{
public:
HTMLHRElement(already_AddRefed<nsINodeInfo> aNodeInfo);
virtual ~HTMLHRElement();
// nsISupports
NS_DECL_ISUPPORTS_INHERITED
// nsIDOMNode
NS_FORWARD_NSIDOMNODE_TO_NSINODE
// nsIDOMElement
NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
// nsIDOMHTMLElement
NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
// nsIDOMHTMLHRElement
NS_DECL_NSIDOMHTMLHRELEMENT
virtual bool ParseAttribute(int32_t aNamespaceID,
nsIAtom* aAttribute,
const nsAString& aValue,
nsAttrValue& aResult);
NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
virtual nsXPCClassInfo* GetClassInfo();
virtual nsIDOMNode* AsDOMNode() { return this; }
// WebIDL API
void SetAlign(const nsAString& aAlign, ErrorResult& aError)
{
SetHTMLAttr(nsGkAtoms::align, aAlign, aError);
}
// The XPCOM GetColor is OK for us
void SetColor(const nsAString& aColor, ErrorResult& aError)
{
SetHTMLAttr(nsGkAtoms::color, aColor, aError);
}
bool NoShade() const
{
return GetBoolAttr(nsGkAtoms::noshade);
}
void SetNoShade(bool aNoShade, ErrorResult& aError)
{
SetHTMLBoolAttr(nsGkAtoms::noshade, aNoShade, aError);
}
// The XPCOM GetSize is OK for us
void SetSize(const nsAString& aSize, ErrorResult& aError)
{
SetHTMLAttr(nsGkAtoms::size, aSize, aError);
}
// The XPCOM GetWidth is OK for us
void SetWidth(const nsAString& aWidth, ErrorResult& aError)
{
SetHTMLAttr(nsGkAtoms::width, aWidth, aError);
}
protected:
virtual JSObject* WrapNode(JSContext* aCx, JSObject* aScope,
bool* aTriedToWrap) MOZ_OVERRIDE;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_HTMLHRElement_h

View File

@ -0,0 +1,79 @@
/* -*- 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/. */
#include "mozilla/dom/HTMLMapElement.h"
#include "mozilla/dom/HTMLMapElementBinding.h"
#include "nsGkAtoms.h"
#include "nsStyleConsts.h"
#include "nsContentList.h"
#include "nsCOMPtr.h"
NS_IMPL_NS_NEW_HTML_ELEMENT(Map)
DOMCI_NODE_DATA(HTMLMapElement, mozilla::dom::HTMLMapElement)
namespace mozilla {
namespace dom {
HTMLMapElement::HTMLMapElement(already_AddRefed<nsINodeInfo> aNodeInfo)
: nsGenericHTMLElement(aNodeInfo)
{
SetIsDOMBinding();
}
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLMapElement,
nsGenericHTMLElement)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAreas)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_ADDREF_INHERITED(HTMLMapElement, Element)
NS_IMPL_RELEASE_INHERITED(HTMLMapElement, Element)
// QueryInterface implementation for HTMLMapElement
NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(HTMLMapElement)
NS_HTML_CONTENT_INTERFACE_TABLE1(HTMLMapElement, nsIDOMHTMLMapElement)
NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(HTMLMapElement,
nsGenericHTMLElement)
NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLMapElement)
NS_IMPL_ELEMENT_CLONE(HTMLMapElement)
nsIHTMLCollection*
HTMLMapElement::Areas()
{
if (!mAreas) {
// Not using NS_GetContentList because this should not be cached
mAreas = new nsContentList(this,
kNameSpaceID_XHTML,
nsGkAtoms::area,
nsGkAtoms::area,
false);
}
return mAreas;
}
NS_IMETHODIMP
HTMLMapElement::GetAreas(nsIDOMHTMLCollection** aAreas)
{
NS_ENSURE_ARG_POINTER(aAreas);
NS_ADDREF(*aAreas = Areas());
return NS_OK;
}
NS_IMPL_STRING_ATTR(HTMLMapElement, Name, name)
JSObject*
HTMLMapElement::WrapNode(JSContext* aCx, JSObject* aScope, bool* aTriedToWrap)
{
return HTMLMapElementBinding::Wrap(aCx, aScope, this, aTriedToWrap);
}
} // namespace dom
} // namespace mozilla

View File

@ -0,0 +1,66 @@
/* -*- 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/. */
#ifndef mozilla_dom_HTMLMapElement_h
#define mozilla_dom_HTMLMapElement_h
#include "nsGenericHTMLElement.h"
#include "nsIDOMHTMLMapElement.h"
#include "nsAutoPtr.h"
#include "nsGkAtoms.h"
class nsContentList;
namespace mozilla {
namespace dom {
class HTMLMapElement : public nsGenericHTMLElement,
public nsIDOMHTMLMapElement
{
public:
HTMLMapElement(already_AddRefed<nsINodeInfo> aNodeInfo);
// nsISupports
NS_DECL_ISUPPORTS_INHERITED
// nsIDOMNode
NS_FORWARD_NSIDOMNODE_TO_NSINODE
// nsIDOMElement
NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
// nsIDOMHTMLElement
NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
// nsIDOMHTMLMapElement
NS_DECL_NSIDOMHTMLMAPELEMENT
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(HTMLMapElement,
nsGenericHTMLElement)
virtual nsXPCClassInfo* GetClassInfo();
virtual nsIDOMNode* AsDOMNode() { return this; }
// XPCOM GetName is fine.
void SetName(const nsAString& aName, ErrorResult& aError)
{
SetHTMLAttr(nsGkAtoms::name, aName, aError);
}
nsIHTMLCollection* Areas();
virtual JSObject*
WrapNode(JSContext* aCx, JSObject* aScope, bool* aTriedToWrap) MOZ_OVERRIDE;
protected:
nsRefPtr<nsContentList> mAreas;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_HTMLMapElement_h

View File

@ -0,0 +1,110 @@
/* -*- 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/. */
#include "mozilla/dom/HTMLMetaElement.h"
#include "mozilla/dom/HTMLMetaElementBinding.h"
#include "nsStyleConsts.h"
#include "nsAsyncDOMEvent.h"
#include "nsContentUtils.h"
NS_IMPL_NS_NEW_HTML_ELEMENT(Meta)
DOMCI_NODE_DATA(HTMLMetaElement, mozilla::dom::HTMLMetaElement)
namespace mozilla {
namespace dom {
HTMLMetaElement::HTMLMetaElement(already_AddRefed<nsINodeInfo> aNodeInfo)
: nsGenericHTMLElement(aNodeInfo)
{
SetIsDOMBinding();
}
HTMLMetaElement::~HTMLMetaElement()
{
}
NS_IMPL_ADDREF_INHERITED(HTMLMetaElement, Element)
NS_IMPL_RELEASE_INHERITED(HTMLMetaElement, Element)
// QueryInterface implementation for HTMLMetaElement
NS_INTERFACE_TABLE_HEAD(HTMLMetaElement)
NS_HTML_CONTENT_INTERFACE_TABLE1(HTMLMetaElement, nsIDOMHTMLMetaElement)
NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(HTMLMetaElement,
nsGenericHTMLElement)
NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLMetaElement)
NS_IMPL_ELEMENT_CLONE(HTMLMetaElement)
NS_IMPL_STRING_ATTR(HTMLMetaElement, Content, content)
NS_IMPL_STRING_ATTR(HTMLMetaElement, HttpEquiv, httpEquiv)
NS_IMPL_STRING_ATTR(HTMLMetaElement, Name, name)
NS_IMPL_STRING_ATTR(HTMLMetaElement, Scheme, scheme)
void
HTMLMetaElement::GetItemValueText(nsAString& aValue)
{
GetContent(aValue);
}
void
HTMLMetaElement::SetItemValueText(const nsAString& aValue)
{
SetContent(aValue);
}
nsresult
HTMLMetaElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
bool aCompileEventHandlers)
{
nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
aBindingParent,
aCompileEventHandlers);
NS_ENSURE_SUCCESS(rv, rv);
if (aDocument &&
AttrValueIs(kNameSpaceID_None, nsGkAtoms::name, nsGkAtoms::viewport, eIgnoreCase)) {
nsAutoString content;
rv = GetContent(content);
NS_ENSURE_SUCCESS(rv, rv);
nsContentUtils::ProcessViewportInfo(aDocument, content);
}
CreateAndDispatchEvent(aDocument, NS_LITERAL_STRING("DOMMetaAdded"));
return rv;
}
void
HTMLMetaElement::UnbindFromTree(bool aDeep, bool aNullParent)
{
nsCOMPtr<nsIDocument> oldDoc = GetCurrentDoc();
CreateAndDispatchEvent(oldDoc, NS_LITERAL_STRING("DOMMetaRemoved"));
nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
}
void
HTMLMetaElement::CreateAndDispatchEvent(nsIDocument* aDoc,
const nsAString& aEventName)
{
if (!aDoc)
return;
nsRefPtr<nsAsyncDOMEvent> event = new nsAsyncDOMEvent(this, aEventName, true,
true);
event->PostDOMEvent();
}
JSObject*
HTMLMetaElement::WrapNode(JSContext* aCx, JSObject* aScope, bool* aTriedToWrap)
{
return HTMLMetaElementBinding::Wrap(aCx, aScope, this, aTriedToWrap);
}
} // namespace dom
} // namespace mozilla

View File

@ -0,0 +1,82 @@
/* -*- 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/. */
#ifndef mozilla_dom_HTMLMetaElement_h
#define mozilla_dom_HTMLMetaElement_h
#include "nsGenericHTMLElement.h"
#include "nsIDOMHTMLMetaElement.h"
namespace mozilla {
namespace dom {
class HTMLMetaElement : public nsGenericHTMLElement,
public nsIDOMHTMLMetaElement
{
public:
HTMLMetaElement(already_AddRefed<nsINodeInfo> aNodeInfo);
virtual ~HTMLMetaElement();
// nsISupports
NS_DECL_ISUPPORTS_INHERITED
// nsIDOMNode
NS_FORWARD_NSIDOMNODE_TO_NSINODE
// nsIDOMElement
NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
// nsIDOMHTMLElement
NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
// nsIDOMHTMLMetaElement
NS_DECL_NSIDOMHTMLMETAELEMENT
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
bool aCompileEventHandlers);
virtual void UnbindFromTree(bool aDeep = true,
bool aNullParent = true);
void CreateAndDispatchEvent(nsIDocument* aDoc, const nsAString& aEventName);
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
virtual nsXPCClassInfo* GetClassInfo();
virtual nsIDOMNode* AsDOMNode() { return this; }
// XPCOM GetName is fine.
void SetName(const nsAString& aName, ErrorResult& aRv)
{
SetHTMLAttr(nsGkAtoms::name, aName, aRv);
}
// XPCOM GetHttpEquiv is fine.
void SetHttpEquiv(const nsAString& aHttpEquiv, ErrorResult& aRv)
{
SetHTMLAttr(nsGkAtoms::httpEquiv, aHttpEquiv, aRv);
}
// XPCOM GetContent is fine.
void SetContent(const nsAString& aContent, ErrorResult& aRv)
{
SetHTMLAttr(nsGkAtoms::content, aContent, aRv);
}
// XPCOM GetScheme is fine.
void SetScheme(const nsAString& aScheme, ErrorResult& aRv)
{
SetHTMLAttr(nsGkAtoms::scheme, aScheme, aRv);
}
virtual JSObject*
WrapNode(JSContext* aCx, JSObject* aScope, bool* aTriedToWrap) MOZ_OVERRIDE;
protected:
virtual void GetItemValueText(nsAString& text);
virtual void SetItemValueText(const nsAString& text);
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_HTMLMetaElement_h

View File

@ -3,117 +3,47 @@
* 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 "nsIDOMHTMLMeterElement.h"
#include "nsGenericHTMLElement.h"
#include "nsAttrValue.h"
#include "nsAttrValueInlines.h"
#include "nsEventStateManager.h"
#include "nsAlgorithm.h"
#include <algorithm>
using namespace mozilla::dom;
class nsHTMLMeterElement : public nsGenericHTMLElement,
public nsIDOMHTMLMeterElement
{
public:
nsHTMLMeterElement(already_AddRefed<nsINodeInfo> aNodeInfo);
virtual ~nsHTMLMeterElement();
/* nsISupports */
NS_DECL_ISUPPORTS_INHERITED
/* nsIDOMNode */
NS_FORWARD_NSIDOMNODE_TO_NSINODE
/* nsIDOMElement */
NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
/* nsIDOMHTMLElement */
NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
/* nsIDOMHTMLMeterElement */
NS_DECL_NSIDOMHTMLMETERELEMENT
virtual nsEventStates IntrinsicState() const;
nsresult Clone(nsINodeInfo* aNodeInfo, nsINode** aResult) const;
bool ParseAttribute(int32_t aNamespaceID, nsIAtom* aAttribute,
const nsAString& aValue, nsAttrValue& aResult);
virtual nsXPCClassInfo* GetClassInfo();
virtual nsIDOMNode* AsDOMNode() { return this; }
private:
static const double kDefaultValue;
static const double kDefaultMin;
static const double kDefaultMax;
/**
* Returns the optimum state of the element.
* NS_EVENT_STATE_OPTIMUM if the actual value is in the optimum region.
* NS_EVENT_STATE_SUB_OPTIMUM if the actual value is in the sub-optimal region.
* NS_EVENT_STATE_SUB_SUB_OPTIMUM if the actual value is in the sub-sub-optimal region.
*
* @return the optimum state of the element.
*/
nsEventStates GetOptimumState() const;
/* @return the minimum value */
double GetMin() const;
/* @return the maximum value */
double GetMax() const;
/* @return the actual value */
double GetValue() const;
/* @return the low value */
double GetLow() const;
/* @return the high value */
double GetHigh() const;
/* @return the optimum value */
double GetOptimum() const;
};
const double nsHTMLMeterElement::kDefaultValue = 0.0;
const double nsHTMLMeterElement::kDefaultMin = 0.0;
const double nsHTMLMeterElement::kDefaultMax = 1.0;
#include "HTMLMeterElement.h"
#include "mozilla/dom/HTMLMeterElementBinding.h"
NS_IMPL_NS_NEW_HTML_ELEMENT(Meter)
DOMCI_NODE_DATA(HTMLMeterElement, mozilla::dom::HTMLMeterElement)
nsHTMLMeterElement::nsHTMLMeterElement(already_AddRefed<nsINodeInfo> aNodeInfo)
namespace mozilla {
namespace dom {
const double HTMLMeterElement::kDefaultValue = 0.0;
const double HTMLMeterElement::kDefaultMin = 0.0;
const double HTMLMeterElement::kDefaultMax = 1.0;
HTMLMeterElement::HTMLMeterElement(already_AddRefed<nsINodeInfo> aNodeInfo)
: nsGenericHTMLElement(aNodeInfo)
{
SetIsDOMBinding();
}
nsHTMLMeterElement::~nsHTMLMeterElement()
HTMLMeterElement::~HTMLMeterElement()
{
}
NS_IMPL_ADDREF_INHERITED(nsHTMLMeterElement, Element)
NS_IMPL_RELEASE_INHERITED(nsHTMLMeterElement, Element)
NS_IMPL_ADDREF_INHERITED(HTMLMeterElement, Element)
NS_IMPL_RELEASE_INHERITED(HTMLMeterElement, Element)
DOMCI_NODE_DATA(HTMLMeterElement, nsHTMLMeterElement)
NS_INTERFACE_TABLE_HEAD(nsHTMLMeterElement)
NS_HTML_CONTENT_INTERFACE_TABLE1(nsHTMLMeterElement,
NS_INTERFACE_TABLE_HEAD(HTMLMeterElement)
NS_HTML_CONTENT_INTERFACE_TABLE1(HTMLMeterElement,
nsIDOMHTMLMeterElement)
NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLMeterElement,
NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(HTMLMeterElement,
nsGenericHTMLElement)
NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLMeterElement)
NS_IMPL_ELEMENT_CLONE(nsHTMLMeterElement)
NS_IMPL_ELEMENT_CLONE(HTMLMeterElement)
nsEventStates
nsHTMLMeterElement::IntrinsicState() const
HTMLMeterElement::IntrinsicState() const
{
nsEventStates state = nsGenericHTMLElement::IntrinsicState();
@ -123,7 +53,7 @@ nsHTMLMeterElement::IntrinsicState() const
}
bool
nsHTMLMeterElement::ParseAttribute(int32_t aNamespaceID, nsIAtom* aAttribute,
HTMLMeterElement::ParseAttribute(int32_t aNamespaceID, nsIAtom* aAttribute,
const nsAString& aValue, nsAttrValue& aResult)
{
if (aNamespaceID == kNameSpaceID_None) {
@ -144,7 +74,7 @@ nsHTMLMeterElement::ParseAttribute(int32_t aNamespaceID, nsIAtom* aAttribute,
*/
double
nsHTMLMeterElement::GetMin() const
HTMLMeterElement::Min() const
{
/**
* If the attribute min is defined, the minimum is this value.
@ -158,7 +88,7 @@ nsHTMLMeterElement::GetMin() const
}
double
nsHTMLMeterElement::GetMax() const
HTMLMeterElement::Max() const
{
/**
* If the attribute max is defined, the maximum is this value.
@ -175,11 +105,11 @@ nsHTMLMeterElement::GetMax() const
max = kDefaultMax;
}
return std::max(max, GetMin());
return std::max(max, Min());
}
double
nsHTMLMeterElement::GetValue() const
HTMLMeterElement::Value() const
{
/**
* If the attribute value is defined, the actual value is this value.
@ -198,17 +128,17 @@ nsHTMLMeterElement::GetValue() const
value = kDefaultValue;
}
double min = GetMin();
double min = Min();
if (value <= min) {
return min;
}
return std::min(value, GetMax());
return std::min(value, Max());
}
double
nsHTMLMeterElement::GetLow() const
HTMLMeterElement::Low() const
{
/**
* If the low value is defined, the low value is this value.
@ -219,7 +149,7 @@ nsHTMLMeterElement::GetLow() const
* the low value is the same as the maximum value.
*/
double min = GetMin();
double min = Min();
const nsAttrValue* attrLow = mAttrsAndChildren.GetAttr(nsGkAtoms::low);
if (!attrLow || attrLow->Type() != nsAttrValue::eDoubleValue) {
@ -232,11 +162,11 @@ nsHTMLMeterElement::GetLow() const
return min;
}
return std::min(low, GetMax());
return std::min(low, Max());
}
double
nsHTMLMeterElement::GetHigh() const
HTMLMeterElement::High() const
{
/**
* If the high value is defined, the high value is this value.
@ -247,7 +177,7 @@ nsHTMLMeterElement::GetHigh() const
* the high value is the same as the maximum value.
*/
double max = GetMax();
double max = Max();
const nsAttrValue* attrHigh = mAttrsAndChildren.GetAttr(nsGkAtoms::high);
if (!attrHigh || attrHigh->Type() != nsAttrValue::eDoubleValue) {
@ -260,11 +190,11 @@ nsHTMLMeterElement::GetHigh() const
return max;
}
return std::max(high, GetLow());
return std::max(high, Low());
}
double
nsHTMLMeterElement::GetOptimum() const
HTMLMeterElement::Optimum() const
{
/**
* If the optimum value is defined, the optimum value is this value.
@ -277,9 +207,9 @@ nsHTMLMeterElement::GetOptimum() const
* the optimum value is the same as the maximum value.
*/
double max = GetMax();
double max = Max();
double min = GetMin();
double min = Min();
const nsAttrValue* attrOptimum =
mAttrsAndChildren.GetAttr(nsGkAtoms::optimum);
@ -301,85 +231,85 @@ nsHTMLMeterElement::GetOptimum() const
*/
NS_IMETHODIMP
nsHTMLMeterElement::GetMin(double* aValue)
HTMLMeterElement::GetMin(double* aValue)
{
*aValue = GetMin();
*aValue = Min();
return NS_OK;
}
NS_IMETHODIMP
nsHTMLMeterElement::SetMin(double aValue)
HTMLMeterElement::SetMin(double aValue)
{
return SetDoubleAttr(nsGkAtoms::min, aValue);
}
NS_IMETHODIMP
nsHTMLMeterElement::GetMax(double* aValue)
HTMLMeterElement::GetMax(double* aValue)
{
*aValue = GetMax();
*aValue = Max();
return NS_OK;
}
NS_IMETHODIMP
nsHTMLMeterElement::SetMax(double aValue)
HTMLMeterElement::SetMax(double aValue)
{
return SetDoubleAttr(nsGkAtoms::max, aValue);
}
NS_IMETHODIMP
nsHTMLMeterElement::GetValue(double* aValue)
HTMLMeterElement::GetValue(double* aValue)
{
*aValue = GetValue();
*aValue = Value();
return NS_OK;
}
NS_IMETHODIMP
nsHTMLMeterElement::SetValue(double aValue)
HTMLMeterElement::SetValue(double aValue)
{
return SetDoubleAttr(nsGkAtoms::value, aValue);
}
NS_IMETHODIMP
nsHTMLMeterElement::GetLow(double* aValue)
HTMLMeterElement::GetLow(double* aValue)
{
*aValue = GetLow();
*aValue = Low();
return NS_OK;
}
NS_IMETHODIMP
nsHTMLMeterElement::SetLow(double aValue)
HTMLMeterElement::SetLow(double aValue)
{
return SetDoubleAttr(nsGkAtoms::low, aValue);
}
NS_IMETHODIMP
nsHTMLMeterElement::GetHigh(double* aValue)
HTMLMeterElement::GetHigh(double* aValue)
{
*aValue = GetHigh();
*aValue = High();
return NS_OK;
}
NS_IMETHODIMP
nsHTMLMeterElement::SetHigh(double aValue)
HTMLMeterElement::SetHigh(double aValue)
{
return SetDoubleAttr(nsGkAtoms::high, aValue);
}
NS_IMETHODIMP
nsHTMLMeterElement::GetOptimum(double* aValue)
HTMLMeterElement::GetOptimum(double* aValue)
{
*aValue = GetOptimum();
*aValue = Optimum();
return NS_OK;
}
NS_IMETHODIMP
nsHTMLMeterElement::SetOptimum(double aValue)
HTMLMeterElement::SetOptimum(double aValue)
{
return SetDoubleAttr(nsGkAtoms::optimum, aValue);
}
nsEventStates
nsHTMLMeterElement::GetOptimumState() const
HTMLMeterElement::GetOptimumState() const
{
/*
* If the optimum value is in [minimum, low[,
@ -391,10 +321,10 @@ nsHTMLMeterElement::GetOptimumState() const
* If the optimum value is in ]high, maximum],
* return if the value is in optimal, suboptimal or sub-suboptimal region
*/
double value = GetValue();
double low = GetLow();
double high = GetHigh();
double optimum = GetOptimum();
double value = Value();
double low = Low();
double high = High();
double optimum = Optimum();
if (optimum < low) {
if (value < low) {
@ -421,3 +351,12 @@ nsHTMLMeterElement::GetOptimumState() const
return NS_EVENT_STATE_SUB_OPTIMUM;
}
JSObject*
HTMLMeterElement::WrapNode(JSContext* aCx, JSObject* aScope,
bool* aTriedToWrap)
{
return HTMLMeterElementBinding::Wrap(aCx, aScope, this, aTriedToWrap);
}
} // namespace dom
} // namespace mozilla

View File

@ -0,0 +1,121 @@
/* -*- 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/. */
#ifndef mozilla_dom_HTMLMeterElement_h
#define mozilla_dom_HTMLMeterElement_h
#include "nsIDOMHTMLMeterElement.h"
#include "nsGenericHTMLElement.h"
#include "nsAttrValue.h"
#include "nsAttrValueInlines.h"
#include "nsEventStateManager.h"
#include "nsAlgorithm.h"
#include <algorithm>
namespace mozilla {
namespace dom {
class HTMLMeterElement : public nsGenericHTMLElement,
public nsIDOMHTMLMeterElement
{
public:
HTMLMeterElement(already_AddRefed<nsINodeInfo> aNodeInfo);
virtual ~HTMLMeterElement();
/* nsISupports */
NS_DECL_ISUPPORTS_INHERITED
/* nsIDOMNode */
NS_FORWARD_NSIDOMNODE_TO_NSINODE
/* nsIDOMElement */
NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
/* nsIDOMHTMLElement */
NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
/* nsIDOMHTMLMeterElement */
NS_DECL_NSIDOMHTMLMETERELEMENT
virtual nsEventStates IntrinsicState() const;
nsresult Clone(nsINodeInfo* aNodeInfo, nsINode** aResult) const;
bool ParseAttribute(int32_t aNamespaceID, nsIAtom* aAttribute,
const nsAString& aValue, nsAttrValue& aResult);
virtual nsXPCClassInfo* GetClassInfo();
virtual nsIDOMNode* AsDOMNode() { return this; }
// WebIDL
/* @return the value */
double Value() const;
void SetValue(double aValue, ErrorResult& aRv)
{
aRv = SetValue(aValue);
}
/* @return the minimum value */
double Min() const;
void SetMin(double aValue, ErrorResult& aRv)
{
aRv = SetMin(aValue);
}
/* @return the maximum value */
double Max() const;
void SetMax(double aValue, ErrorResult& aRv)
{
aRv = SetMax(aValue);
}
/* @return the low value */
double Low() const;
void SetLow(double aValue, ErrorResult& aRv)
{
aRv = SetLow(aValue);
}
/* @return the high value */
double High() const;
void SetHigh(double aValue, ErrorResult& aRv)
{
aRv = SetHigh(aValue);
}
/* @return the optimum value */
double Optimum() const;
void SetOptimum(double aValue, ErrorResult& aRv)
{
aRv = SetOptimum(aValue);
}
protected:
virtual JSObject* WrapNode(JSContext* aCx, JSObject* aScope,
bool* aTriedToWrap) MOZ_OVERRIDE;
private:
static const double kDefaultValue;
static const double kDefaultMin;
static const double kDefaultMax;
/**
* Returns the optimum state of the element.
* NS_EVENT_STATE_OPTIMUM if the actual value is in the optimum region.
* NS_EVENT_STATE_SUB_OPTIMUM if the actual value is in the sub-optimal region.
* NS_EVENT_STATE_SUB_SUB_OPTIMUM if the actual value is in the sub-sub-optimal region.
*
* @return the optimum state of the element.
*/
nsEventStates GetOptimumState() const;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_HTMLMeterElement_h

View File

@ -0,0 +1,53 @@
/* -*- 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/. */
#include "mozilla/dom/HTMLModElement.h"
#include "mozilla/dom/HTMLModElementBinding.h"
#include "nsStyleConsts.h"
NS_IMPL_NS_NEW_HTML_ELEMENT(Mod)
DOMCI_NODE_DATA(HTMLModElement, mozilla::dom::HTMLModElement)
namespace mozilla {
namespace dom {
HTMLModElement::HTMLModElement(already_AddRefed<nsINodeInfo> aNodeInfo)
: nsGenericHTMLElement(aNodeInfo)
{
SetIsDOMBinding();
}
HTMLModElement::~HTMLModElement()
{
}
NS_IMPL_ADDREF_INHERITED(HTMLModElement, Element)
NS_IMPL_RELEASE_INHERITED(HTMLModElement, Element)
// QueryInterface implementation for HTMLModElement
NS_INTERFACE_TABLE_HEAD(HTMLModElement)
NS_HTML_CONTENT_INTERFACE_TABLE1(HTMLModElement,
nsIDOMHTMLModElement)
NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(HTMLModElement,
nsGenericHTMLElement)
NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLModElement)
NS_IMPL_ELEMENT_CLONE(HTMLModElement)
NS_IMPL_URI_ATTR(HTMLModElement, Cite, cite)
NS_IMPL_STRING_ATTR(HTMLModElement, DateTime, datetime)
JSObject*
HTMLModElement::WrapNode(JSContext* aCx, JSObject* aScope, bool* aTriedToWrap)
{
return HTMLModElementBinding::Wrap(aCx, aScope, this, aTriedToWrap);
}
} // namespace dom
} // namespace mozilla

View File

@ -0,0 +1,65 @@
/* -*- 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/. */
#ifndef mozilla_dom_HTMLModElement_h
#define mozilla_dom_HTMLModElement_h
#include "nsGenericHTMLElement.h"
#include "nsIDOMHTMLModElement.h"
#include "nsGkAtoms.h"
namespace mozilla {
namespace dom {
class HTMLModElement : public nsGenericHTMLElement,
public nsIDOMHTMLModElement
{
public:
HTMLModElement(already_AddRefed<nsINodeInfo> aNodeInfo);
virtual ~HTMLModElement();
// nsISupports
NS_DECL_ISUPPORTS_INHERITED
// nsIDOMNode
NS_FORWARD_NSIDOMNODE_TO_NSINODE
// nsIDOMElement
NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
// nsIDOMHTMLElement
NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
// nsIDOMHTMLModElement
NS_DECL_NSIDOMHTMLMODELEMENT
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
virtual nsXPCClassInfo* GetClassInfo();
virtual nsIDOMNode* AsDOMNode() { return this; }
void GetCite(nsString& aCite)
{
GetHTMLURIAttr(nsGkAtoms::cite, aCite);
}
void SetCite(const nsAString& aCite, ErrorResult& aRv)
{
SetHTMLAttr(nsGkAtoms::cite, aCite, aRv);
}
// XPCOM GetDateTime is fine.
void SetDateTime(const nsAString& aDateTime, ErrorResult& aRv)
{
SetHTMLAttr(nsGkAtoms::datetime, aDateTime, aRv);
}
virtual JSObject*
WrapNode(JSContext* aCx, JSObject* aScope, bool* aTriedToWrap) MOZ_OVERRIDE;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_HTMLModElement_h

View File

@ -0,0 +1,88 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/HTMLSourceElement.h"
#include "mozilla/dom/HTMLSourceElementBinding.h"
NS_IMPL_NS_NEW_HTML_ELEMENT(Source)
DOMCI_NODE_DATA(HTMLSourceElement, mozilla::dom::HTMLSourceElement)
namespace mozilla {
namespace dom {
HTMLSourceElement::HTMLSourceElement(already_AddRefed<nsINodeInfo> aNodeInfo)
: nsGenericHTMLElement(aNodeInfo)
{
SetIsDOMBinding();
}
HTMLSourceElement::~HTMLSourceElement()
{
}
NS_IMPL_ADDREF_INHERITED(HTMLSourceElement, Element)
NS_IMPL_RELEASE_INHERITED(HTMLSourceElement, Element)
// QueryInterface implementation for HTMLSourceElement
NS_INTERFACE_TABLE_HEAD(HTMLSourceElement)
NS_HTML_CONTENT_INTERFACE_TABLE1(HTMLSourceElement, nsIDOMHTMLSourceElement)
NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(HTMLSourceElement,
nsGenericHTMLElement)
NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLSourceElement)
NS_IMPL_ELEMENT_CLONE(HTMLSourceElement)
NS_IMPL_URI_ATTR(HTMLSourceElement, Src, src)
NS_IMPL_STRING_ATTR(HTMLSourceElement, Type, type)
NS_IMPL_STRING_ATTR(HTMLSourceElement, Media, media)
void
HTMLSourceElement::GetItemValueText(nsAString& aValue)
{
GetSrc(aValue);
}
void
HTMLSourceElement::SetItemValueText(const nsAString& aValue)
{
SetSrc(aValue);
}
nsresult
HTMLSourceElement::BindToTree(nsIDocument *aDocument,
nsIContent *aParent,
nsIContent *aBindingParent,
bool aCompileEventHandlers)
{
nsresult rv = nsGenericHTMLElement::BindToTree(aDocument,
aParent,
aBindingParent,
aCompileEventHandlers);
NS_ENSURE_SUCCESS(rv, rv);
if (!aParent || !aParent->IsNodeOfType(nsINode::eMEDIA))
return NS_OK;
nsHTMLMediaElement* media = static_cast<nsHTMLMediaElement*>(aParent);
media->NotifyAddedSource();
return NS_OK;
}
JSObject*
HTMLSourceElement::WrapNode(JSContext* aCx, JSObject* aScope,
bool* aTriedToWrap)
{
return HTMLSourceElementBinding::Wrap(aCx, aScope, this, aTriedToWrap);
}
} // namespace dom
} // namespace mozilla

View File

@ -0,0 +1,91 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_HTMLSourceElement_h
#define mozilla_dom_HTMLSourceElement_h
#include "nsIDOMHTMLSourceElement.h"
#include "nsGenericHTMLElement.h"
#include "nsHTMLMediaElement.h"
namespace mozilla {
namespace dom {
class HTMLSourceElement : public nsGenericHTMLElement,
public nsIDOMHTMLSourceElement
{
public:
HTMLSourceElement(already_AddRefed<nsINodeInfo> aNodeInfo);
virtual ~HTMLSourceElement();
// nsISupports
NS_DECL_ISUPPORTS_INHERITED
// nsIDOMNode
NS_FORWARD_NSIDOMNODE_TO_NSINODE
// nsIDOMElement
NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
// nsIDOMHTMLElement
NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
// nsIDOMHTMLSourceElement
NS_DECL_NSIDOMHTMLSOURCEELEMENT
virtual nsresult Clone(nsINodeInfo* aNodeInfo, nsINode** aResult) const;
// Override BindToTree() so that we can trigger a load when we add a
// child source element.
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
bool aCompileEventHandlers);
virtual nsXPCClassInfo* GetClassInfo();
virtual nsIDOMNode* AsDOMNode() { return this; }
// WebIDL
void GetSrc(nsString& aSrc)
{
GetURIAttr(nsGkAtoms::src, nullptr, aSrc);
}
void SetSrc(const nsAString& aSrc, mozilla::ErrorResult& rv)
{
SetHTMLAttr(nsGkAtoms::src, aSrc, rv);
}
void GetType(nsString& aType)
{
GetHTMLAttr(nsGkAtoms::type, aType);
}
void SetType(const nsAString& aType, ErrorResult& rv)
{
SetHTMLAttr(nsGkAtoms::type, aType, rv);
}
void GetMedia(nsString& aMedia)
{
GetHTMLAttr(nsGkAtoms::media, aMedia);
}
void SetMedia(const nsAString& aMedia, mozilla::ErrorResult& rv)
{
SetHTMLAttr(nsGkAtoms::media, aMedia, rv);
}
protected:
virtual JSObject* WrapNode(JSContext* aCx, JSObject* aScope,
bool* aTriedToWrap) MOZ_OVERRIDE;
protected:
virtual void GetItemValueText(nsAString& text);
virtual void SetItemValueText(const nsAString& text);
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_HTMLSourceElement_h

View File

@ -901,12 +901,6 @@ static const nsAttrValue::EnumTable kRulesTable[] = {
{ 0 }
};
static const nsAttrValue::EnumTable kLayoutTable[] = {
{ "auto", NS_STYLE_TABLE_LAYOUT_AUTO },
{ "fixed", NS_STYLE_TABLE_LAYOUT_FIXED },
{ 0 }
};
bool
HTMLTableElement::ParseAttribute(int32_t aNamespaceID,
@ -917,12 +911,10 @@ HTMLTableElement::ParseAttribute(int32_t aNamespaceID,
/* ignore summary, just a string */
if (aNamespaceID == kNameSpaceID_None) {
if (aAttribute == nsGkAtoms::cellspacing ||
aAttribute == nsGkAtoms::cellpadding) {
aAttribute == nsGkAtoms::cellpadding ||
aAttribute == nsGkAtoms::border) {
return aResult.ParseNonNegativeIntValue(aValue);
}
if (aAttribute == nsGkAtoms::border) {
return aResult.ParseIntWithBounds(aValue, 0);
}
if (aAttribute == nsGkAtoms::height) {
return aResult.ParseSpecialIntValue(aValue);
}
@ -948,9 +940,6 @@ HTMLTableElement::ParseAttribute(int32_t aNamespaceID,
if (aAttribute == nsGkAtoms::frame) {
return aResult.ParseEnumValue(aValue, kFrameTable, false);
}
if (aAttribute == nsGkAtoms::layout) {
return aResult.ParseEnumValue(aValue, kLayoutTable, false);
}
if (aAttribute == nsGkAtoms::rules) {
return aResult.ParseEnumValue(aValue, kRulesTable, false);
}
@ -996,16 +985,6 @@ MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
SetFloatValue(float(value->GetIntegerValue()), eCSSUnit_Pixel);
}
}
if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Table)) {
const nsAttrValue* value;
// layout
nsCSSValue* tableLayout = aData->ValueForTableLayout();
if (tableLayout->GetUnit() == eCSSUnit_Null) {
value = aAttributes->GetAttr(nsGkAtoms::layout);
if (value && value->Type() == nsAttrValue::eEnum)
tableLayout->SetIntValue(value->GetEnumValue(), eCSSUnit_Enumerated);
}
}
if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Margin)) {
// align; Check for enumerated type (it may be another type if
// illegal)
@ -1123,7 +1102,6 @@ NS_IMETHODIMP_(bool)
HTMLTableElement::IsAttributeMapped(const nsIAtom* aAttribute) const
{
static const MappedAttributeEntry attributes[] = {
{ &nsGkAtoms::layout },
{ &nsGkAtoms::cellpadding },
{ &nsGkAtoms::cellspacing },
{ &nsGkAtoms::border },

View File

@ -38,9 +38,14 @@ EXPORTS_mozilla/dom = \
HTMLFontElement.h \
HTMLFrameSetElement.h \
HTMLHeadingElement.h \
HTMLHRElement.h \
HTMLImageElement.h \
HTMLLabelElement.h \
HTMLLIElement.h \
HTMLMapElement.h \
HTMLMetaElement.h \
HTMLMeterElement.h \
HTMLModElement.h \
HTMLParagraphElement.h \
HTMLPreElement.h \
HTMLScriptElement.h \
@ -81,7 +86,7 @@ CPPSRCS = \
nsHTMLFormElement.cpp \
nsHTMLFrameElement.cpp \
HTMLFrameSetElement.cpp \
nsHTMLHRElement.cpp \
HTMLHRElement.cpp \
HTMLHeadingElement.cpp \
nsHTMLIFrameElement.cpp \
HTMLImageElement.cpp \
@ -90,12 +95,12 @@ CPPSRCS = \
HTMLLabelElement.cpp \
nsHTMLLegendElement.cpp \
nsHTMLLinkElement.cpp \
nsHTMLMapElement.cpp \
HTMLMapElement.cpp \
nsHTMLMenuElement.cpp \
nsHTMLMenuItemElement.cpp \
nsHTMLMetaElement.cpp \
nsHTMLMeterElement.cpp \
nsHTMLModElement.cpp \
HTMLMetaElement.cpp \
HTMLMeterElement.cpp \
HTMLModElement.cpp \
HTMLObjectElement.cpp \
nsHTMLSharedObjectElement.cpp \
nsHTMLOptionElement.cpp \
@ -127,12 +132,16 @@ CPPSRCS = \
$(NULL)
ifdef MOZ_MEDIA
EXPORTS_mozilla/dom += \
HTMLSourceElement.h \
$(NULL)
CPPSRCS += \
nsHTMLAudioElement.cpp \
nsHTMLMediaElement.cpp \
nsMediaError.cpp \
nsMediaFragmentURIParser.cpp \
nsHTMLSourceElement.cpp \
HTMLSourceElement.cpp \
nsTimeRanges.cpp \
nsHTMLVideoElement.cpp \
$(NULL)

View File

@ -1,97 +0,0 @@
/* -*- 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/. */
#include "nsIDOMHTMLMapElement.h"
#include "nsIDOMEventTarget.h"
#include "nsGenericHTMLElement.h"
#include "nsGkAtoms.h"
#include "nsStyleConsts.h"
#include "nsContentList.h"
#include "nsCOMPtr.h"
using namespace mozilla::dom;
class nsHTMLMapElement : public nsGenericHTMLElement,
public nsIDOMHTMLMapElement
{
public:
nsHTMLMapElement(already_AddRefed<nsINodeInfo> aNodeInfo);
// nsISupports
NS_DECL_ISUPPORTS_INHERITED
// nsIDOMNode
NS_FORWARD_NSIDOMNODE_TO_NSINODE
// nsIDOMElement
NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
// nsIDOMHTMLElement
NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
// nsIDOMHTMLMapElement
NS_DECL_NSIDOMHTMLMAPELEMENT
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(nsHTMLMapElement,
nsGenericHTMLElement)
virtual nsXPCClassInfo* GetClassInfo();
virtual nsIDOMNode* AsDOMNode() { return this; }
protected:
nsRefPtr<nsContentList> mAreas;
};
NS_IMPL_NS_NEW_HTML_ELEMENT(Map)
nsHTMLMapElement::nsHTMLMapElement(already_AddRefed<nsINodeInfo> aNodeInfo)
: nsGenericHTMLElement(aNodeInfo)
{
}
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsHTMLMapElement,
nsGenericHTMLElement)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAreas)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_ADDREF_INHERITED(nsHTMLMapElement, Element)
NS_IMPL_RELEASE_INHERITED(nsHTMLMapElement, Element)
DOMCI_NODE_DATA(HTMLMapElement, nsHTMLMapElement)
// QueryInterface implementation for nsHTMLMapElement
NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsHTMLMapElement)
NS_HTML_CONTENT_INTERFACE_TABLE1(nsHTMLMapElement, nsIDOMHTMLMapElement)
NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLMapElement,
nsGenericHTMLElement)
NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLMapElement)
NS_IMPL_ELEMENT_CLONE(nsHTMLMapElement)
NS_IMETHODIMP
nsHTMLMapElement::GetAreas(nsIDOMHTMLCollection** aAreas)
{
NS_ENSURE_ARG_POINTER(aAreas);
if (!mAreas) {
// Not using NS_GetContentList because this should not be cached
mAreas = new nsContentList(this,
kNameSpaceID_XHTML,
nsGkAtoms::area,
nsGkAtoms::area,
false);
}
NS_ADDREF(*aAreas = mAreas);
return NS_OK;
}
NS_IMPL_STRING_ATTR(nsHTMLMapElement, Name, name)

View File

@ -1,142 +0,0 @@
/* -*- 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/. */
#include "nsIDOMHTMLMetaElement.h"
#include "nsIDOMEventTarget.h"
#include "nsGenericHTMLElement.h"
#include "nsGkAtoms.h"
#include "nsStyleConsts.h"
#include "nsAsyncDOMEvent.h"
#include "nsContentUtils.h"
using namespace mozilla::dom;
class nsHTMLMetaElement : public nsGenericHTMLElement,
public nsIDOMHTMLMetaElement
{
public:
nsHTMLMetaElement(already_AddRefed<nsINodeInfo> aNodeInfo);
virtual ~nsHTMLMetaElement();
// nsISupports
NS_DECL_ISUPPORTS_INHERITED
// nsIDOMNode
NS_FORWARD_NSIDOMNODE_TO_NSINODE
// nsIDOMElement
NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
// nsIDOMHTMLElement
NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
// nsIDOMHTMLMetaElement
NS_DECL_NSIDOMHTMLMETAELEMENT
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
bool aCompileEventHandlers);
virtual void UnbindFromTree(bool aDeep = true,
bool aNullParent = true);
void CreateAndDispatchEvent(nsIDocument* aDoc, const nsAString& aEventName);
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
virtual nsXPCClassInfo* GetClassInfo();
virtual nsIDOMNode* AsDOMNode() { return this; }
protected:
virtual void GetItemValueText(nsAString& text);
virtual void SetItemValueText(const nsAString& text);
};
NS_IMPL_NS_NEW_HTML_ELEMENT(Meta)
nsHTMLMetaElement::nsHTMLMetaElement(already_AddRefed<nsINodeInfo> aNodeInfo)
: nsGenericHTMLElement(aNodeInfo)
{
}
nsHTMLMetaElement::~nsHTMLMetaElement()
{
}
NS_IMPL_ADDREF_INHERITED(nsHTMLMetaElement, Element)
NS_IMPL_RELEASE_INHERITED(nsHTMLMetaElement, Element)
DOMCI_NODE_DATA(HTMLMetaElement, nsHTMLMetaElement)
// QueryInterface implementation for nsHTMLMetaElement
NS_INTERFACE_TABLE_HEAD(nsHTMLMetaElement)
NS_HTML_CONTENT_INTERFACE_TABLE1(nsHTMLMetaElement, nsIDOMHTMLMetaElement)
NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLMetaElement,
nsGenericHTMLElement)
NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLMetaElement)
NS_IMPL_ELEMENT_CLONE(nsHTMLMetaElement)
NS_IMPL_STRING_ATTR(nsHTMLMetaElement, Content, content)
NS_IMPL_STRING_ATTR(nsHTMLMetaElement, HttpEquiv, httpEquiv)
NS_IMPL_STRING_ATTR(nsHTMLMetaElement, Name, name)
NS_IMPL_STRING_ATTR(nsHTMLMetaElement, Scheme, scheme)
void
nsHTMLMetaElement::GetItemValueText(nsAString& aValue)
{
GetContent(aValue);
}
void
nsHTMLMetaElement::SetItemValueText(const nsAString& aValue)
{
SetContent(aValue);
}
nsresult
nsHTMLMetaElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
bool aCompileEventHandlers)
{
nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
aBindingParent,
aCompileEventHandlers);
NS_ENSURE_SUCCESS(rv, rv);
if (aDocument &&
AttrValueIs(kNameSpaceID_None, nsGkAtoms::name, nsGkAtoms::viewport, eIgnoreCase)) {
nsAutoString content;
rv = GetContent(content);
NS_ENSURE_SUCCESS(rv, rv);
nsContentUtils::ProcessViewportInfo(aDocument, content);
}
CreateAndDispatchEvent(aDocument, NS_LITERAL_STRING("DOMMetaAdded"));
return rv;
}
void
nsHTMLMetaElement::UnbindFromTree(bool aDeep, bool aNullParent)
{
nsCOMPtr<nsIDocument> oldDoc = GetCurrentDoc();
CreateAndDispatchEvent(oldDoc, NS_LITERAL_STRING("DOMMetaRemoved"));
nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
}
void
nsHTMLMetaElement::CreateAndDispatchEvent(nsIDocument* aDoc,
const nsAString& aEventName)
{
if (!aDoc)
return;
nsRefPtr<nsAsyncDOMEvent> event = new nsAsyncDOMEvent(this, aEventName, true,
true);
event->PostDOMEvent();
}

View File

@ -1,74 +0,0 @@
/* -*- 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/. */
#include "nsIDOMHTMLModElement.h"
#include "nsIDOMEventTarget.h"
#include "nsGenericHTMLElement.h"
#include "nsGkAtoms.h"
#include "nsStyleConsts.h"
using namespace mozilla::dom;
class nsHTMLModElement : public nsGenericHTMLElement,
public nsIDOMHTMLModElement
{
public:
nsHTMLModElement(already_AddRefed<nsINodeInfo> aNodeInfo);
virtual ~nsHTMLModElement();
// nsISupports
NS_DECL_ISUPPORTS_INHERITED
// nsIDOMNode
NS_FORWARD_NSIDOMNODE_TO_NSINODE
// nsIDOMElement
NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
// nsIDOMHTMLElement
NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
// nsIDOMHTMLModElement
NS_DECL_NSIDOMHTMLMODELEMENT
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
virtual nsXPCClassInfo* GetClassInfo();
virtual nsIDOMNode* AsDOMNode() { return this; }
};
NS_IMPL_NS_NEW_HTML_ELEMENT(Mod)
nsHTMLModElement::nsHTMLModElement(already_AddRefed<nsINodeInfo> aNodeInfo)
: nsGenericHTMLElement(aNodeInfo)
{
}
nsHTMLModElement::~nsHTMLModElement()
{
}
NS_IMPL_ADDREF_INHERITED(nsHTMLModElement, Element)
NS_IMPL_RELEASE_INHERITED(nsHTMLModElement, Element)
DOMCI_NODE_DATA(HTMLModElement, nsHTMLModElement)
// QueryInterface implementation for nsHTMLModElement
NS_INTERFACE_TABLE_HEAD(nsHTMLModElement)
NS_HTML_CONTENT_INTERFACE_TABLE1(nsHTMLModElement,
nsIDOMHTMLModElement)
NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLModElement,
nsGenericHTMLElement)
NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLModElement)
NS_IMPL_ELEMENT_CLONE(nsHTMLModElement)
NS_IMPL_URI_ATTR(nsHTMLModElement, Cite, cite)
NS_IMPL_STRING_ATTR(nsHTMLModElement, DateTime, datetime)

View File

@ -1,125 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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 "nsIDOMHTMLSourceElement.h"
#include "nsIDOMEventTarget.h"
#include "nsGenericHTMLElement.h"
#include "nsGkAtoms.h"
#include "nsStyleConsts.h"
#include "nsMappedAttributes.h"
#include "nsRuleData.h"
#include "nsHTMLMediaElement.h"
#include "nsCOMPtr.h"
#include "nsThreadUtils.h"
using namespace mozilla::dom;
class nsHTMLSourceElement : public nsGenericHTMLElement,
public nsIDOMHTMLSourceElement
{
public:
nsHTMLSourceElement(already_AddRefed<nsINodeInfo> aNodeInfo);
virtual ~nsHTMLSourceElement();
// nsISupports
NS_DECL_ISUPPORTS_INHERITED
// nsIDOMNode
NS_FORWARD_NSIDOMNODE_TO_NSINODE
// nsIDOMElement
NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
// nsIDOMHTMLElement
NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
// nsIDOMHTMLSourceElement
NS_DECL_NSIDOMHTMLSOURCEELEMENT
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
// Override BindToTree() so that we can trigger a load when we add a
// child source element.
virtual nsresult BindToTree(nsIDocument *aDocument, nsIContent *aParent,
nsIContent *aBindingParent,
bool aCompileEventHandlers);
virtual nsXPCClassInfo* GetClassInfo();
virtual nsIDOMNode* AsDOMNode() { return this; }
protected:
virtual void GetItemValueText(nsAString& text);
virtual void SetItemValueText(const nsAString& text);
};
NS_IMPL_NS_NEW_HTML_ELEMENT(Source)
nsHTMLSourceElement::nsHTMLSourceElement(already_AddRefed<nsINodeInfo> aNodeInfo)
: nsGenericHTMLElement(aNodeInfo)
{
}
nsHTMLSourceElement::~nsHTMLSourceElement()
{
}
NS_IMPL_ADDREF_INHERITED(nsHTMLSourceElement, Element)
NS_IMPL_RELEASE_INHERITED(nsHTMLSourceElement, Element)
DOMCI_NODE_DATA(HTMLSourceElement, nsHTMLSourceElement)
// QueryInterface implementation for nsHTMLSourceElement
NS_INTERFACE_TABLE_HEAD(nsHTMLSourceElement)
NS_HTML_CONTENT_INTERFACE_TABLE1(nsHTMLSourceElement, nsIDOMHTMLSourceElement)
NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLSourceElement,
nsGenericHTMLElement)
NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLSourceElement)
NS_IMPL_ELEMENT_CLONE(nsHTMLSourceElement)
NS_IMPL_URI_ATTR(nsHTMLSourceElement, Src, src)
NS_IMPL_STRING_ATTR(nsHTMLSourceElement, Type, type)
NS_IMPL_STRING_ATTR(nsHTMLSourceElement, Media, media)
void
nsHTMLSourceElement::GetItemValueText(nsAString& aValue)
{
GetSrc(aValue);
}
void
nsHTMLSourceElement::SetItemValueText(const nsAString& aValue)
{
SetSrc(aValue);
}
nsresult
nsHTMLSourceElement::BindToTree(nsIDocument *aDocument,
nsIContent *aParent,
nsIContent *aBindingParent,
bool aCompileEventHandlers)
{
nsresult rv = nsGenericHTMLElement::BindToTree(aDocument,
aParent,
aBindingParent,
aCompileEventHandlers);
NS_ENSURE_SUCCESS(rv, rv);
if (!aParent || !aParent->IsNodeOfType(nsINode::eMEDIA))
return NS_OK;
nsHTMLMediaElement* media = static_cast<nsHTMLMediaElement*>(aParent);
media->NotifyAddedSource();
return NS_OK;
}

View File

@ -337,6 +337,9 @@ MOCHITEST_FILES = \
test_htmlcollection.html \
test_formelements.html \
test_rowscollection.html \
test_map_attributes_reflection.html \
test_meta_attributes_reflection.html \
test_mod_attributes_reflection.html \
test_mozaudiochannel.html \
test_style_attributes_reflection.html \
$(NULL)

View File

@ -60,7 +60,6 @@ function reflectString(aParameters)
form: [ "acceptCharset", "name", "target" ],
input: [ "accept", "alt", "formTarget", "max", "min", "name", "pattern", "placeholder", "step", "defaultValue" ],
link: [ "crossOrigin" ],
source: [ "media" ],
textarea: [ "name", "placeholder" ]
};
if (!(element.localName in todoAttrs) || todoAttrs[element.localName].indexOf(idlAttr) == -1) {

View File

@ -0,0 +1,27 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for HTMLMapElement attributes reflection</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="reflect.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
/** Test for HTMLMapElement attributes reflection **/
// .name (String)
reflectString({
element: document.createElement("map"),
attribute: "name",
})
</script>
</pre>
</body>
</html>

View File

@ -0,0 +1,45 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for HTMLMetaElement attributes reflection</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="reflect.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
/** Test for HTMLMetaElement attributes reflection **/
// .name (String)
reflectString({
element: document.createElement("meta"),
attribute: "name",
})
// .httpEquiv (String)
reflectString({
element: document.createElement("meta"),
attribute: { content: "http-equiv", idl: "httpEquiv" },
})
// .content (String)
reflectString({
element: document.createElement("meta"),
attribute: "content",
})
// .scheme (String)
reflectString({
element: document.createElement("meta"),
attribute: "scheme",
})
</script>
</pre>
</body>
</html>

View File

@ -0,0 +1,33 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for HTMLModElement attributes reflection</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="reflect.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
/** Test for HTMLModElement attributes reflection **/
// TODO: cite (URL)
// .dateTime (String)
reflectString({
element: document.createElement("ins"),
attribute: "dateTime",
})
reflectString({
element: document.createElement("del"),
attribute: "dateTime",
})
</script>
</pre>
</body>
</html>

View File

@ -61,9 +61,7 @@ NS_IMETHODIMP SVGAltGlyphElement::GetHref(nsIDOMSVGAnimatedString * *aHref)
already_AddRefed<nsIDOMSVGAnimatedString>
SVGAltGlyphElement::Href()
{
nsCOMPtr<nsIDOMSVGAnimatedString> href;
mStringAttributes[HREF].ToDOMAnimatedString(getter_AddRefs(href), this);
return href.forget();
return mStringAttributes[HREF].ToDOMAnimatedString(this);
}
void

View File

@ -115,9 +115,7 @@ SVGGradientElement::SpreadMethod()
already_AddRefed<nsIDOMSVGAnimatedString>
SVGGradientElement::Href()
{
nsCOMPtr<nsIDOMSVGAnimatedString> href;
mStringAttributes[HREF].ToDOMAnimatedString(getter_AddRefs(href), this);
return href.forget();
return mStringAttributes[HREF].ToDOMAnimatedString(this);
}
NS_IMETHODIMP

View File

@ -166,9 +166,7 @@ SVGImageElement::GetHref(nsIDOMSVGAnimatedString * *aHref)
already_AddRefed<nsIDOMSVGAnimatedString>
SVGImageElement::Href()
{
nsCOMPtr<nsIDOMSVGAnimatedString> href;
mStringAttributes[HREF].ToDOMAnimatedString(getter_AddRefs(href), this);
return href.forget();;
return mStringAttributes[HREF].ToDOMAnimatedString(this);
}
//----------------------------------------------------------------------

View File

@ -87,9 +87,7 @@ NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGMPathElement)
already_AddRefed<nsIDOMSVGAnimatedString>
SVGMPathElement::Href()
{
nsCOMPtr<nsIDOMSVGAnimatedString> href;
mStringAttributes[HREF].ToDOMAnimatedString(getter_AddRefs(href), this);
return href.forget();
return mStringAttributes[HREF].ToDOMAnimatedString(this);
}
NS_IMETHODIMP

View File

@ -113,9 +113,7 @@ SVGScriptElement::GetHref(nsIDOMSVGAnimatedString * *aHref)
already_AddRefed<nsIDOMSVGAnimatedString>
SVGScriptElement::Href()
{
nsCOMPtr<nsIDOMSVGAnimatedString> href;
mStringAttributes[HREF].ToDOMAnimatedString(getter_AddRefs(href), this);
return href.forget();
return mStringAttributes[HREF].ToDOMAnimatedString(this);
}
//----------------------------------------------------------------------

View File

@ -102,9 +102,7 @@ NS_IMETHODIMP SVGTextPathElement::GetHref(nsIDOMSVGAnimatedString * *aHref)
already_AddRefed<nsIDOMSVGAnimatedString>
SVGTextPathElement::Href()
{
nsCOMPtr<nsIDOMSVGAnimatedString> href;
mStringAttributes[HREF].ToDOMAnimatedString(getter_AddRefs(href), this);
return href.forget();
return mStringAttributes[HREF].ToDOMAnimatedString(this);
}
//----------------------------------------------------------------------

View File

@ -72,15 +72,6 @@ nsSVGClass::SetAnimValue(const nsAString& aValue, nsSVGElement *aSVGElement)
aSVGElement->DidAnimateClass();
}
nsresult
nsSVGClass::ToDOMAnimatedString(nsIDOMSVGAnimatedString **aResult,
nsSVGElement *aSVGElement)
{
*aResult = new DOMAnimatedString(this, aSVGElement);
NS_ADDREF(*aResult);
return NS_OK;
}
NS_IMETHODIMP
nsSVGClass::DOMAnimatedString::GetAnimVal(nsAString& aResult)
{

View File

@ -34,8 +34,19 @@ public:
bool IsAnimated() const
{ return !!mAnimVal; }
already_AddRefed<nsIDOMSVGAnimatedString>
ToDOMAnimatedString(nsSVGElement* aSVGElement)
{
nsRefPtr<DOMAnimatedString> result = new DOMAnimatedString(this, aSVGElement);
return result.forget();
}
nsresult ToDOMAnimatedString(nsIDOMSVGAnimatedString **aResult,
nsSVGElement *aSVGElement);
nsSVGElement *aSVGElement)
{
*aResult = ToDOMAnimatedString(aSVGElement).get();
return NS_OK;
}
// Returns a new nsISMILAttr object that the caller must delete
nsISMILAttr* ToSMILAttr(nsSVGElement *aSVGElement);

View File

@ -1163,9 +1163,7 @@ nsSVGElement::GetViewportElement()
already_AddRefed<nsIDOMSVGAnimatedString>
nsSVGElement::ClassName()
{
nsCOMPtr<nsIDOMSVGAnimatedString> className;
mClassAttribute.ToDOMAnimatedString(getter_AddRefs(className), this);
return className.forget();
return mClassAttribute.ToDOMAnimatedString(this);
}
//------------------------------------------------------------------------

View File

@ -75,6 +75,13 @@ nsSVGString::SetAnimValue(const nsAString& aValue, nsSVGElement *aSVGElement)
nsresult
nsSVGString::ToDOMAnimatedString(nsIDOMSVGAnimatedString **aResult,
nsSVGElement *aSVGElement)
{
*aResult = ToDOMAnimatedString(aSVGElement).get();
return NS_OK;
}
already_AddRefed<nsIDOMSVGAnimatedString>
nsSVGString::ToDOMAnimatedString(nsSVGElement* aSVGElement)
{
nsRefPtr<DOMAnimatedString> domAnimatedString =
sSVGAnimatedStringTearoffTable.GetTearoff(this);
@ -83,8 +90,7 @@ nsSVGString::ToDOMAnimatedString(nsIDOMSVGAnimatedString **aResult,
sSVGAnimatedStringTearoffTable.AddTearoff(this, domAnimatedString);
}
domAnimatedString.forget(aResult);
return NS_OK;
return domAnimatedString.forget();
}
nsSVGString::DOMAnimatedString::~DOMAnimatedString()

View File

@ -40,6 +40,9 @@ public:
nsresult ToDOMAnimatedString(nsIDOMSVGAnimatedString **aResult,
nsSVGElement *aSVGElement);
already_AddRefed<nsIDOMSVGAnimatedString>
ToDOMAnimatedString(nsSVGElement* aSVGElement);
// Returns a new nsISMILAttr object that the caller must delete
nsISMILAttr* ToSMILAttr(nsSVGElement *aSVGElement);

View File

@ -1487,7 +1487,9 @@ Navigator::OnNavigation()
#ifdef MOZ_MEDIA_NAVIGATOR
// Inform MediaManager in case there are live streams or pending callbacks.
MediaManager *manager = MediaManager::Get();
manager->OnNavigation(win->WindowID());
if (manager) {
manager->OnNavigation(win->WindowID());
}
#endif
if (mCameraManager) {
mCameraManager->OnNavigation(win->WindowID());

View File

@ -92,7 +92,7 @@ nsContentPermissionRequestProxy::GetElement(nsIDOMElement * *aRequestingElement)
return NS_ERROR_FAILURE;
}
NS_ADDREF(*aRequestingElement = mParent->mElement);
NS_IF_ADDREF(*aRequestingElement = mParent->mElement);
return NS_OK;
}

View File

@ -419,18 +419,12 @@ using mozilla::dom::workers::ResolveWorkerClasses;
#include "nsIDOMPowerManager.h"
#include "nsIDOMWakeLock.h"
#include "nsIDOMSmsManager.h"
#include "nsIDOMSmsMessage.h"
#include "nsIDOMSmsEvent.h"
#include "nsIDOMMozSmsMessage.h"
#include "nsIDOMSmsRequest.h"
#include "nsIDOMSmsFilter.h"
#include "nsIDOMSmsCursor.h"
#include "nsIDOMSmsSegmentInfo.h"
#include "nsIDOMConnection.h"
#ifdef MOZ_B2G_RIL
#include "nsIDOMMobileConnection.h"
#endif
#include "USSDReceivedEvent.h"
#include "DataErrorEvent.h"
#include "mozilla/dom/network/Utils.h"
#ifdef MOZ_B2G_RIL
@ -441,7 +435,7 @@ using mozilla::dom::workers::ResolveWorkerClasses;
#include "StkCommandEvent.h"
#include "nsIDOMMozCellBroadcast.h"
#include "nsIDOMMozCellBroadcastEvent.h"
#include "CFStateChangeEvent.h"
#include "nsIDOMMobileConnection.h"
#endif // MOZ_B2G_RIL
#ifdef MOZ_B2G_FM
@ -1268,9 +1262,6 @@ static nsDOMClassInfoData sClassInfoData[] = {
NS_DEFINE_CLASSINFO_DATA(MozSmsMessage, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(MozSmsEvent, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(MozSmsRequest, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
@ -1292,17 +1283,8 @@ static nsDOMClassInfoData sClassInfoData[] = {
NS_DEFINE_CLASSINFO_DATA(MozCellBroadcast, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(CFStateChangeEvent, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
#endif
NS_DEFINE_CLASSINFO_DATA(USSDReceivedEvent, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(DataErrorEvent, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(CSSFontFaceRule, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
@ -3376,11 +3358,6 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozSmsMessage)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(MozSmsEvent, nsIDOMMozSmsEvent)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozSmsEvent)
DOM_CLASSINFO_EVENT_MAP_ENTRIES
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(MozSmsRequest, nsIDOMMozSmsRequest)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozSmsRequest)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
@ -3418,23 +3395,8 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozCellBroadcastEvent)
DOM_CLASSINFO_EVENT_MAP_ENTRIES
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(CFStateChangeEvent, nsIDOMCFStateChangeEvent)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMCFStateChangeEvent)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMEvent)
DOM_CLASSINFO_MAP_END
#endif // MOZ_B2G_RIL
DOM_CLASSINFO_MAP_BEGIN(USSDReceivedEvent, nsIDOMUSSDReceivedEvent)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMUSSDReceivedEvent)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMEvent)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(DataErrorEvent, nsIDOMDataErrorEvent)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMDataErrorEvent)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMEvent)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(CSSFontFaceRule, nsIDOMCSSFontFaceRule)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSFontFaceRule)
DOM_CLASSINFO_MAP_END
@ -3985,19 +3947,6 @@ nsDOMClassInfo::PreCreate(nsISupports *nativeObj, JSContext *cx,
JSObject *globalObj, JSObject **parentObj)
{
*parentObj = globalObj;
nsCOMPtr<nsPIDOMWindow> piwin = do_QueryWrapper(cx, globalObj);
if (!piwin) {
return NS_OK;
}
if (piwin->IsOuterWindow()) {
nsGlobalWindow *win = ((nsGlobalWindow *)piwin.get())->
GetCurrentInnerWindowInternal();
return SetParentToWindow(win, parentObj);
}
return NS_OK;
}
@ -4544,10 +4493,10 @@ nsWindowSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
static JSClass sGlobalScopePolluterClass = {
"Global Scope Polluter",
JSCLASS_HAS_PRIVATE | JSCLASS_PRIVATE_IS_NSISUPPORTS | JSCLASS_NEW_RESOLVE,
nsWindowSH::SecurityCheckOnAddDelProp,
nsWindowSH::SecurityCheckOnAddDelProp,
JS_PropertyStub,
JS_PropertyStub,
nsWindowSH::GlobalScopePolluterGetProperty,
nsWindowSH::SecurityCheckOnSetProp,
JS_StrictPropertyStub,
JS_EnumerateStub,
(JSResolveOp)nsWindowSH::GlobalScopePolluterNewResolve,
JS_ConvertStub,
@ -4578,32 +4527,6 @@ nsWindowSH::GlobalScopePolluterGetProperty(JSContext *cx, JSHandleObject obj,
return JS_TRUE;
}
// static
JSBool
nsWindowSH::SecurityCheckOnAddDelProp(JSContext *cx, JSHandleObject obj, JSHandleId id,
JSMutableHandleValue vp)
{
// Someone is accessing a element by referencing its name/id in the
// global scope, do a security check to make sure that's ok.
nsresult rv =
sSecMan->CheckPropertyAccess(cx, ::JS_GetGlobalForObject(cx, obj),
"Window", id,
nsIXPCSecurityManager::ACCESS_SET_PROPERTY);
// If !NS_SUCCEEDED(rv) the security check failed. The security
// manager set a JS exception for us.
return NS_SUCCEEDED(rv);
}
// static
JSBool
nsWindowSH::SecurityCheckOnSetProp(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict,
JSMutableHandleValue vp)
{
return SecurityCheckOnAddDelProp(cx, obj, id, vp);
}
static nsHTMLDocument*
GetDocument(JSObject *obj)
{

View File

@ -347,10 +347,6 @@ public:
JSMutableHandleObject objp);
static JSBool GlobalScopePolluterGetProperty(JSContext *cx, JSHandleObject obj,
JSHandleId id, JSMutableHandleValue vp);
static JSBool SecurityCheckOnAddDelProp(JSContext *cx, JSHandleObject obj, JSHandleId id,
JSMutableHandleValue vp);
static JSBool SecurityCheckOnSetProp(JSContext *cx, JSHandleObject obj, JSHandleId id,
JSBool strict, JSMutableHandleValue vp);
static JSBool InvalidateGlobalScopePolluter(JSContext *cx, JSObject *obj);
static nsresult InstallGlobalScopePolluter(JSContext *cx, JSObject *obj,
nsIHTMLDocument *doc);

View File

@ -314,7 +314,6 @@ DOMCI_CLASS(MozWakeLock)
DOMCI_CLASS(MozSmsManager)
DOMCI_CLASS(MozSmsMessage)
DOMCI_CLASS(MozSmsEvent)
DOMCI_CLASS(MozSmsRequest)
DOMCI_CLASS(MozSmsFilter)
DOMCI_CLASS(MozSmsCursor)
@ -324,13 +323,8 @@ DOMCI_CLASS(MozConnection)
#ifdef MOZ_B2G_RIL
DOMCI_CLASS(MozMobileConnection)
DOMCI_CLASS(MozCellBroadcast)
DOMCI_CLASS(CFStateChangeEvent)
#endif
DOMCI_CLASS(USSDReceivedEvent)
DOMCI_CLASS(DataErrorEvent)
// @font-face in CSS
DOMCI_CLASS(CSSFontFaceRule)

View File

@ -1072,7 +1072,7 @@ nsJSContext::JSOptionChangedCallback(const char *pref, void *data)
else
newDefaultJSOptions &= ~JSOPTION_WERROR;
::JS_SetOptions(context->mContext, newDefaultJSOptions & JSRUNOPTION_MASK);
::JS_SetOptions(context->mContext, newDefaultJSOptions & JSOPTION_MASK);
::JS_SetParallelCompilationEnabled(context->mContext, parallelIonCompilation);

View File

@ -1260,14 +1260,19 @@ NativeToString(JSContext* cx, JSObject* wrapper, JSObject* obj, const char* pre,
} else {
if (IsDOMProxy(obj)) {
str = js::GetProxyHandler(obj)->obj_toString(cx, obj);
} else if (IsDOMClass(JS_GetClass(obj)) ||
IsDOMIfaceAndProtoClass(JS_GetClass(obj))) {
str = ConcatJSString(cx, "[object ",
JS_NewStringCopyZ(cx, JS_GetClass(obj)->name),
"]");
} else {
MOZ_ASSERT(JS_IsNativeFunction(obj, Constructor));
str = JS_DecompileFunction(cx, JS_GetObjectFunction(obj), 0);
js::Class* clasp = js::GetObjectClass(obj);
if (IsDOMClass(clasp)) {
str = ConcatJSString(cx, "[object ",
JS_NewStringCopyZ(cx, clasp->name), "]");
} else if (IsDOMIfaceAndProtoClass(clasp)) {
const DOMIfaceAndProtoJSClass* ifaceAndProtoJSClass =
DOMIfaceAndProtoJSClass::FromJSClass(clasp);
str = JS_NewStringCopyZ(cx, ifaceAndProtoJSClass->mToString);
} else {
MOZ_ASSERT(JS_IsNativeFunction(obj, Constructor));
str = JS_DecompileFunction(cx, JS_GetObjectFunction(obj), 0);
}
}
str = ConcatJSString(cx, pre, str, post);
}

View File

@ -397,15 +397,19 @@ DOMInterfaces = {
},
'HTMLFrameSetElement': {
'hasInstanceInterface': 'nsIDOMHTMLFrameSetElement',
'hasInstanceInterface': 'nsIDOMHTMLFrameSetElement',
},
'HTMLHeadingElement': {
'hasInstanceInterface': 'nsIDOMHTMLHeadingElement',
'hasInstanceInterface': 'nsIDOMHTMLHeadingElement',
},
'HTMLHRElement': {
'hasInstanceInterface': 'nsIDOMHTMLHRElement',
},
'HTMLImageElement': {
'hasInstanceInterface': 'nsIDOMHTMLImageElement',
'hasInstanceInterface': 'nsIDOMHTMLImageElement',
},
'HTMLLabelElement': {
@ -419,6 +423,22 @@ DOMInterfaces = {
'hasInstanceInterface': 'nsIDOMHTMLLIElement',
},
'HTMLMapElement': {
'hasInstanceInterface': 'nsIDOMHTMLMapElement',
},
'HTMLMetaElement': {
'hasInstanceInterface': 'nsIDOMHTMLMetaElement',
},
'HTMLMeterElement': {
'hasInstanceInterface': 'nsIDOMHTMLMeterElement',
},
'HTMLModElement': {
'hasInstanceInterface': 'nsIDOMHTMLModElement',
},
'HTMLOListElement': {
'headerFile' : 'mozilla/dom/HTMLSharedListElement.h',
'hasInstanceInterface': 'nsIDOMHTMLOListElement'
@ -450,6 +470,10 @@ DOMInterfaces = {
'hasInstanceInterface': 'nsIDOMHTMLScriptElement',
},
'HTMLSourceElement': {
'hasInstanceInterface': 'nsIDOMHTMLSourceElement',
},
'HTMLTableCellElement': {
'hasInstanceInterface': 'nsIDOMHTMLTableCellElement'
},

View File

@ -212,10 +212,12 @@ class CGPrototypeJSClass(CGThing):
JSCLASS_NO_INTERNAL_MEMBERS
},
eInterfacePrototype,
%s
%s,
"[object %sPrototype]"
};
""" % (self.descriptor.interface.identifier.name,
NativePropertyHooks(self.descriptor))
NativePropertyHooks(self.descriptor),
self.descriptor.interface.identifier.name)
class CGInterfaceObjectJSClass(CGThing):
def __init__(self, descriptor, properties):
@ -254,9 +256,11 @@ static DOMIfaceAndProtoJSClass InterfaceObjectClass = {
JSCLASS_NO_INTERNAL_MEMBERS
},
eInterface,
%s
%s,
"function %s() {\\n [native code]\\n}"
};
""" % (ctorname, hasinstance, ctorname, NativePropertyHooks(self.descriptor))
""" % (ctorname, hasinstance, ctorname, NativePropertyHooks(self.descriptor),
self.descriptor.interface.identifier.name)
class CGList(CGThing):
"""

View File

@ -204,6 +204,10 @@ struct DOMIfaceAndProtoJSClass
const NativePropertyHooks* mNativeHooks;
// The value to return for toString() on this interface or interface prototype
// object.
const char* mToString;
static const DOMIfaceAndProtoJSClass* FromJSClass(const JSClass* base) {
MOZ_ASSERT(base->flags & JSCLASS_IS_DOMIFACEANDPROTOJSCLASS);
return reinterpret_cast<const DOMIfaceAndProtoJSClass*>(base);

View File

@ -8,858 +8,29 @@ let { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/Geometry.jsm");
Cu.import("resource://gre/modules/BrowserElementPromptService.jsm");
// Event whitelisted for bubbling.
let whitelistedEvents = [
Ci.nsIDOMKeyEvent.DOM_VK_ESCAPE, // Back button.
Ci.nsIDOMKeyEvent.DOM_VK_SLEEP, // Power button.
Ci.nsIDOMKeyEvent.DOM_VK_CONTEXT_MENU,
Ci.nsIDOMKeyEvent.DOM_VK_F5, // Search button.
Ci.nsIDOMKeyEvent.DOM_VK_PAGE_UP, // Volume up.
Ci.nsIDOMKeyEvent.DOM_VK_PAGE_DOWN // Volume down.
];
function debug(msg) {
//dump("BrowserElementChild - " + msg + "\n");
}
function sendAsyncMsg(msg, data) {
if (!data) {
data = { };
}
// NB: this must happen before we process any messages from
// mozbrowser API clients.
docShell.isActive = true;
data.msg_name = msg;
sendAsyncMessage('browser-element-api:call', data);
let infos = sendSyncMessage('browser-element-api:call',
{ 'msg_name': 'hello' })[0];
docShell.QueryInterface(Ci.nsIDocShellTreeItem).name = infos.name;
docShell.setFullscreenAllowed(infos.fullscreenAllowed);
if (!('BrowserElementIsPreloaded' in this)) {
// This is a produc-specific file that's sometimes unavailable.
try {
Services.scriptloader.loadSubScript("chrome://browser/content/forms.js");
} catch (e) {
}
Services.scriptloader.loadSubScript("chrome://global/content/BrowserElementPanning.js");
Services.scriptloader.loadSubScript("chrome://global/content/BrowserElementChildPreload.js");
}
function sendSyncMsg(msg, data) {
if (!data) {
data = { };
}
data.msg_name = msg;
return sendSyncMessage('browser-element-api:call', data);
}
/**
* The BrowserElementChild implements one half of <iframe mozbrowser>.
* (The other half is, unsurprisingly, BrowserElementParent.)
*
* This script is injected into an <iframe mozbrowser> via
* nsIMessageManager::LoadFrameScript().
*
* Our job here is to listen for events within this frame and bubble them up to
* the parent process.
*/
var global = this;
function BrowserElementChild() {
// Maps outer window id --> weak ref to window. Used by modal dialog code.
this._windowIDDict = {};
// _forcedVisible corresponds to the visibility state our owner has set on us
// (via iframe.setVisible). ownerVisible corresponds to whether the docShell
// whose window owns this element is visible.
//
// Our docShell is visible iff _forcedVisible and _ownerVisible are both
// true.
this._forcedVisible = true;
this._ownerVisible = true;
this._nextPaintHandler = null;
this._init();
};
BrowserElementChild.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
Ci.nsISupportsWeakReference]),
_init: function() {
debug("Starting up.");
// NB: this must happen before we process any messages from
// mozbrowser API clients.
docShell.isActive = true;
sendAsyncMsg("hello");
// Set the docshell's name according to our <iframe>'s name attribute.
docShell.QueryInterface(Ci.nsIDocShellTreeItem).name =
sendSyncMsg('get-name')[0];
docShell.setFullscreenAllowed(sendSyncMsg('get-fullscreen-allowed')[0]);
BrowserElementPromptService.mapWindowToBrowserElementChild(content, this);
docShell.QueryInterface(Ci.nsIWebProgress)
.addProgressListener(this._progressListener,
Ci.nsIWebProgress.NOTIFY_LOCATION |
Ci.nsIWebProgress.NOTIFY_SECURITY |
Ci.nsIWebProgress.NOTIFY_STATE_WINDOW);
docShell.QueryInterface(Ci.nsIWebNavigation)
.sessionHistory = Cc["@mozilla.org/browser/shistory;1"]
.createInstance(Ci.nsISHistory);
// This is necessary to get security web progress notifications.
var securityUI = Cc['@mozilla.org/secure_browser_ui;1']
.createInstance(Ci.nsISecureBrowserUI);
securityUI.init(content);
// A cache of the menuitem dom objects keyed by the id we generate
// and pass to the embedder
this._ctxHandlers = {};
// Counter of contextmenu events fired
this._ctxCounter = 0;
addEventListener('DOMTitleChanged',
this._titleChangedHandler.bind(this),
/* useCapture = */ true,
/* wantsUntrusted = */ false);
addEventListener('DOMLinkAdded',
this._iconChangedHandler.bind(this),
/* useCapture = */ true,
/* wantsUntrusted = */ false);
// Registers a MozAfterPaint handler for the very first paint.
this._addMozAfterPaintHandler(function () {
sendAsyncMsg('firstpaint');
});
let self = this;
let mmCalls = {
"purge-history": this._recvPurgeHistory,
"get-screenshot": this._recvGetScreenshot,
"set-visible": this._recvSetVisible,
"get-visible": this._recvVisible,
"send-mouse-event": this._recvSendMouseEvent,
"send-touch-event": this._recvSendTouchEvent,
"get-can-go-back": this._recvCanGoBack,
"get-can-go-forward": this._recvCanGoForward,
"go-back": this._recvGoBack,
"go-forward": this._recvGoForward,
"reload": this._recvReload,
"stop": this._recvStop,
"unblock-modal-prompt": this._recvStopWaiting,
"fire-ctx-callback": this._recvFireCtxCallback,
"owner-visibility-change": this._recvOwnerVisibilityChange,
"exit-fullscreen": this._recvExitFullscreen.bind(this),
"activate-next-paint-listener": this._activateNextPaintListener.bind(this),
"deactivate-next-paint-listener": this._deactivateNextPaintListener.bind(this)
}
addMessageListener("browser-element-api:call", function(aMessage) {
if (aMessage.data.msg_name in mmCalls) {
return mmCalls[aMessage.data.msg_name].apply(self, arguments);
}
});
let els = Cc["@mozilla.org/eventlistenerservice;1"]
.getService(Ci.nsIEventListenerService);
// We are using the system group for those events so if something in the
// content called .stopPropagation() this will still be called.
els.addSystemEventListener(global, 'keydown',
this._keyEventHandler.bind(this),
/* useCapture = */ true);
els.addSystemEventListener(global, 'keypress',
this._keyEventHandler.bind(this),
/* useCapture = */ true);
els.addSystemEventListener(global, 'keyup',
this._keyEventHandler.bind(this),
/* useCapture = */ true);
els.addSystemEventListener(global, 'DOMWindowClose',
this._windowCloseHandler.bind(this),
/* useCapture = */ false);
els.addSystemEventListener(global, 'DOMWindowCreated',
this._windowCreatedHandler.bind(this),
/* useCapture = */ true);
els.addSystemEventListener(global, 'contextmenu',
this._contextmenuHandler.bind(this),
/* useCapture = */ false);
els.addSystemEventListener(global, 'scroll',
this._scrollEventHandler.bind(this),
/* useCapture = */ false);
Services.obs.addObserver(this,
"fullscreen-origin-change",
/* ownsWeak = */ true);
Services.obs.addObserver(this,
'ask-parent-to-exit-fullscreen',
/* ownsWeak = */ true);
Services.obs.addObserver(this,
'ask-parent-to-rollback-fullscreen',
/* ownsWeak = */ true);
},
observe: function(subject, topic, data) {
// Ignore notifications not about our document.
if (subject != content.document)
return;
switch (topic) {
case 'fullscreen-origin-change':
sendAsyncMsg('fullscreen-origin-change', { _payload_: data });
break;
case 'ask-parent-to-exit-fullscreen':
sendAsyncMsg('exit-fullscreen');
break;
case 'ask-parent-to-rollback-fullscreen':
sendAsyncMsg('rollback-fullscreen');
break;
}
},
_tryGetInnerWindowID: function(win) {
let utils = win.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
try {
return utils.currentInnerWindowID;
}
catch(e) {
return null;
}
},
/**
* Show a modal prompt. Called by BrowserElementPromptService.
*/
showModalPrompt: function(win, args) {
let utils = win.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
args.windowID = { outer: utils.outerWindowID,
inner: this._tryGetInnerWindowID(win) };
sendAsyncMsg('showmodalprompt', args);
let returnValue = this._waitForResult(win);
if (args.promptType == 'prompt' ||
args.promptType == 'confirm' ||
args.promptType == 'custom-prompt') {
return returnValue;
}
},
/**
* Spin in a nested event loop until we receive a unblock-modal-prompt message for
* this window.
*/
_waitForResult: function(win) {
debug("_waitForResult(" + win + ")");
let utils = win.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
let outerWindowID = utils.outerWindowID;
let innerWindowID = this._tryGetInnerWindowID(win);
if (innerWindowID === null) {
// I have no idea what waiting for a result means when there's no inner
// window, so let's just bail.
debug("_waitForResult: No inner window. Bailing.");
return;
}
this._windowIDDict[outerWindowID] = Cu.getWeakReference(win);
debug("Entering modal state (outerWindowID=" + outerWindowID + ", " +
"innerWindowID=" + innerWindowID + ")");
// In theory, we're supposed to pass |modalStateWin| back to
// leaveModalStateWithWindow. But in practice, the window is always null,
// because it's the window associated with this script context, which
// doesn't have a window. But we'll play along anyway in case this
// changes.
var modalStateWin = utils.enterModalStateWithWindow();
// We'll decrement win.modalDepth when we receive a unblock-modal-prompt message
// for the window.
if (!win.modalDepth) {
win.modalDepth = 0;
}
win.modalDepth++;
let origModalDepth = win.modalDepth;
let thread = Services.tm.currentThread;
debug("Nested event loop - begin");
while (win.modalDepth == origModalDepth) {
// Bail out of the loop if the inner window changed; that means the
// window navigated.
if (this._tryGetInnerWindowID(win) !== innerWindowID) {
debug("_waitForResult: Inner window ID changed " +
"while in nested event loop.");
break;
}
thread.processNextEvent(/* mayWait = */ true);
}
debug("Nested event loop - finish");
// If we exited the loop because the inner window changed, then bail on the
// modal prompt.
if (innerWindowID !== this._tryGetInnerWindowID(win)) {
throw Components.Exception("Modal state aborted by navigation",
Cr.NS_ERROR_NOT_AVAILABLE);
}
let returnValue = win.modalReturnValue;
delete win.modalReturnValue;
utils.leaveModalStateWithWindow(modalStateWin);
debug("Leaving modal state (outerID=" + outerWindowID + ", " +
"innerID=" + innerWindowID + ")");
return returnValue;
},
_recvStopWaiting: function(msg) {
let outerID = msg.json.windowID.outer;
let innerID = msg.json.windowID.inner;
let returnValue = msg.json.returnValue;
debug("recvStopWaiting(outer=" + outerID + ", inner=" + innerID +
", returnValue=" + returnValue + ")");
if (!this._windowIDDict[outerID]) {
debug("recvStopWaiting: No record of outer window ID " + outerID);
return;
}
let win = this._windowIDDict[outerID].get();
delete this._windowIDDict[outerID];
if (!win) {
debug("recvStopWaiting, but window is gone\n");
return;
}
if (innerID !== this._tryGetInnerWindowID(win)) {
debug("recvStopWaiting, but inner ID has changed\n");
return;
}
debug("recvStopWaiting " + win);
win.modalReturnValue = returnValue;
win.modalDepth--;
},
_recvExitFullscreen: function() {
var utils = content.document.defaultView
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
utils.exitFullscreen();
},
_titleChangedHandler: function(e) {
debug("Got titlechanged: (" + e.target.title + ")");
var win = e.target.defaultView;
// Ignore titlechanges which don't come from the top-level
// <iframe mozbrowser> window.
if (win == content) {
sendAsyncMsg('titlechange', { _payload_: e.target.title });
}
else {
debug("Not top level!");
}
},
_iconChangedHandler: function(e) {
debug("Got iconchanged: (" + e.target.href + ")");
var hasIcon = e.target.rel.split(' ').some(function(x) {
return x.toLowerCase() === 'icon';
});
if (hasIcon) {
var win = e.target.ownerDocument.defaultView;
// Ignore iconchanges which don't come from the top-level
// <iframe mozbrowser> window.
if (win == content) {
sendAsyncMsg('iconchange', { _payload_: e.target.href });
}
else {
debug("Not top level!");
}
}
},
_addMozAfterPaintHandler: function(callback) {
function onMozAfterPaint() {
let uri = docShell.QueryInterface(Ci.nsIWebNavigation).currentURI;
debug("Got afterpaint event: " + uri.spec);
if (uri.spec != "about:blank") {
removeEventListener('MozAfterPaint', onMozAfterPaint,
/* useCapture = */ true);
callback();
}
}
addEventListener('MozAfterPaint', onMozAfterPaint, /* useCapture = */ true);
return onMozAfterPaint;
},
_removeMozAfterPaintHandler: function(listener) {
removeEventListener('MozAfterPaint', listener,
/* useCapture = */ true);
},
_activateNextPaintListener: function(e) {
if (!this._nextPaintHandler) {
this._nextPaintHandler = this._addMozAfterPaintHandler(function () {
this._nextPaintHandler = null;
sendAsyncMsg('nextpaint');
}.bind(this));
}
},
_deactivateNextPaintListener: function(e) {
if (this._nextPaintHandler) {
this._removeMozAfterPaintHandler(this._nextPaintHandler);
this._nextPaintHandler = null;
}
},
_windowCloseHandler: function(e) {
let win = e.target;
if (win != content || e.defaultPrevented) {
return;
}
debug("Closing window " + win);
sendAsyncMsg('close');
// Inform the window implementation that we handled this close ourselves.
e.preventDefault();
},
_windowCreatedHandler: function(e) {
let targetDocShell = e.target.defaultView
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation);
if (targetDocShell != docShell) {
return;
}
let uri = docShell.QueryInterface(Ci.nsIWebNavigation).currentURI;
debug("Window created: " + uri.spec);
if (uri.spec != "about:blank") {
this._addMozAfterPaintHandler(function () {
sendAsyncMsg('documentfirstpaint');
});
}
},
_contextmenuHandler: function(e) {
debug("Got contextmenu");
if (e.defaultPrevented) {
return;
}
e.preventDefault();
this._ctxCounter++;
this._ctxHandlers = {};
var elem = e.target;
var menuData = {systemTargets: [], contextmenu: null};
var ctxMenuId = null;
while (elem && elem.parentNode) {
var ctxData = this._getSystemCtxMenuData(elem);
if (ctxData) {
menuData.systemTargets.push({
nodeName: elem.nodeName,
data: ctxData
});
}
if (!ctxMenuId && 'hasAttribute' in elem && elem.hasAttribute('contextmenu')) {
ctxMenuId = elem.getAttribute('contextmenu');
}
elem = elem.parentNode;
}
if (ctxMenuId) {
var menu = e.target.ownerDocument.getElementById(ctxMenuId);
if (menu) {
menuData.contextmenu = this._buildMenuObj(menu, '');
}
}
sendAsyncMsg('contextmenu', menuData);
},
_getSystemCtxMenuData: function(elem) {
if ((elem instanceof Ci.nsIDOMHTMLAnchorElement && elem.href) ||
(elem instanceof Ci.nsIDOMHTMLAreaElement && elem.href)) {
return elem.href;
}
if (elem instanceof Ci.nsIImageLoadingContent && elem.currentURI) {
return elem.currentURI.spec;
}
if ((elem instanceof Ci.nsIDOMHTMLMediaElement) ||
(elem instanceof Ci.nsIDOMHTMLImageElement)) {
return elem.currentSrc || elem.src;
}
return false;
},
_scrollEventHandler: function(e) {
let win = e.target.defaultView;
if (win != content) {
return;
}
debug("scroll event " + win);
sendAsyncMsg("scroll", { top: win.scrollY, left: win.scrollX });
},
_recvPurgeHistory: function(data) {
debug("Received purgeHistory message: (" + data.json.id + ")");
let history = docShell.QueryInterface(Ci.nsIWebNavigation).sessionHistory;
try {
if (history && history.count) {
history.PurgeHistory(history.count);
}
} catch(e) {}
sendAsyncMsg('got-purge-history', { id: data.json.id, successRv: true });
},
_recvGetScreenshot: function(data) {
debug("Received getScreenshot message: (" + data.json.id + ")");
let self = this;
let maxWidth = data.json.args.width;
let maxHeight = data.json.args.height;
let domRequestID = data.json.id;
let takeScreenshotClosure = function() {
self._takeScreenshot(maxWidth, maxHeight, domRequestID);
};
let maxDelayMS = 2000;
try {
maxDelayMS = Services.prefs.getIntPref('dom.browserElement.maxScreenshotDelayMS');
}
catch(e) {}
// Try to wait for the event loop to go idle before we take the screenshot,
// but once we've waited maxDelayMS milliseconds, go ahead and take it
// anyway.
Cc['@mozilla.org/message-loop;1'].getService(Ci.nsIMessageLoop).postIdleTask(
takeScreenshotClosure, maxDelayMS);
},
/**
* Actually take a screenshot and foward the result up to our parent, given
* the desired maxWidth and maxHeight, and given the DOMRequest ID associated
* with the request from the parent.
*/
_takeScreenshot: function(maxWidth, maxHeight, domRequestID) {
// You can think of the screenshotting algorithm as carrying out the
// following steps:
//
// - Let scaleWidth be the factor by which we'd need to downscale the
// viewport so it would fit within maxWidth. (If the viewport's width
// is less than maxWidth, let scaleWidth be 1.) Compute scaleHeight
// the same way.
//
// - Scale the viewport by max(scaleWidth, scaleHeight). Now either the
// viewport's width is no larger than maxWidth, the viewport's height is
// no larger than maxHeight, or both.
//
// - Crop the viewport so its width is no larger than maxWidth and its
// height is no larger than maxHeight.
//
// - Return a screenshot of the page's viewport scaled and cropped per
// above.
debug("Taking a screenshot: maxWidth=" + maxWidth +
", maxHeight=" + maxHeight +
", domRequestID=" + domRequestID + ".");
let scaleWidth = Math.min(1, maxWidth / content.innerWidth);
let scaleHeight = Math.min(1, maxHeight / content.innerHeight);
let scale = Math.max(scaleWidth, scaleHeight);
let canvasWidth = Math.min(maxWidth, Math.round(content.innerWidth * scale));
let canvasHeight = Math.min(maxHeight, Math.round(content.innerHeight * scale));
var canvas = content.document
.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
canvas.mozOpaque = true;
canvas.width = canvasWidth;
canvas.height = canvasHeight;
var ctx = canvas.getContext("2d");
ctx.scale(scale, scale);
ctx.drawWindow(content, 0, 0, content.innerWidth, content.innerHeight,
"rgb(255,255,255)");
// Take a JPEG screenshot to hack around the fact that we can't specify
// opaque PNG. This requires us to unpremultiply the alpha channel, which
// is expensive on ARM processors because they lack a hardware integer
// division instruction.
canvas.toBlob(function(blob) {
sendAsyncMsg('got-screenshot', {
id: domRequestID,
successRv: blob
});
}, 'image/jpeg');
},
_recvFireCtxCallback: function(data) {
debug("Received fireCtxCallback message: (" + data.json.menuitem + ")");
// We silently ignore if the embedder uses an incorrect id in the callback
if (data.json.menuitem in this._ctxHandlers) {
this._ctxHandlers[data.json.menuitem].click();
this._ctxHandlers = {};
} else {
debug("Ignored invalid contextmenu invocation");
}
},
_buildMenuObj: function(menu, idPrefix) {
function maybeCopyAttribute(src, target, attribute) {
if (src.getAttribute(attribute)) {
target[attribute] = src.getAttribute(attribute);
}
}
var menuObj = {type: 'menu', items: []};
maybeCopyAttribute(menu, menuObj, 'label');
for (var i = 0, child; child = menu.children[i++];) {
if (child.nodeName === 'MENU') {
menuObj.items.push(this._buildMenuObj(child, idPrefix + i + '_'));
} else if (child.nodeName === 'MENUITEM') {
var id = this._ctxCounter + '_' + idPrefix + i;
var menuitem = {id: id, type: 'menuitem'};
maybeCopyAttribute(child, menuitem, 'label');
maybeCopyAttribute(child, menuitem, 'icon');
this._ctxHandlers[id] = child;
menuObj.items.push(menuitem);
}
}
return menuObj;
},
_recvSetVisible: function(data) {
debug("Received setVisible message: (" + data.json.visible + ")");
this._forcedVisible = data.json.visible;
this._updateDocShellVisibility();
},
_recvVisible: function(data) {
sendAsyncMsg('got-visible', {
id: data.json.id,
successRv: docShell.isActive
});
},
/**
* Called when the window which contains this iframe becomes hidden or
* visible.
*/
_recvOwnerVisibilityChange: function(data) {
debug("Received ownerVisibilityChange: (" + data.json.visible + ")");
this._ownerVisible = data.json.visible;
this._updateDocShellVisibility();
},
_updateDocShellVisibility: function() {
var visible = this._forcedVisible && this._ownerVisible;
if (docShell.isActive !== visible) {
docShell.isActive = visible;
}
},
_recvSendMouseEvent: function(data) {
let json = data.json;
let utils = content.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
utils.sendMouseEvent(json.type, json.x, json.y, json.button,
json.clickCount, json.modifiers);
},
_recvSendTouchEvent: function(data) {
let json = data.json;
let utils = content.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
utils.sendTouchEvent(json.type, json.identifiers, json.touchesX,
json.touchesY, json.radiisX, json.radiisY,
json.rotationAngles, json.forces, json.count,
json.modifiers);
},
_recvCanGoBack: function(data) {
var webNav = docShell.QueryInterface(Ci.nsIWebNavigation);
sendAsyncMsg('got-can-go-back', {
id: data.json.id,
successRv: webNav.canGoBack
});
},
_recvCanGoForward: function(data) {
var webNav = docShell.QueryInterface(Ci.nsIWebNavigation);
sendAsyncMsg('got-can-go-forward', {
id: data.json.id,
successRv: webNav.canGoForward
});
},
_recvGoBack: function(data) {
try {
docShell.QueryInterface(Ci.nsIWebNavigation).goBack();
} catch(e) {
// Silently swallow errors; these happen when we can't go back.
}
},
_recvGoForward: function(data) {
try {
docShell.QueryInterface(Ci.nsIWebNavigation).goForward();
} catch(e) {
// Silently swallow errors; these happen when we can't go forward.
}
},
_recvReload: function(data) {
let webNav = docShell.QueryInterface(Ci.nsIWebNavigation);
let reloadFlags = data.json.hardReload ?
webNav.LOAD_FLAGS_BYPASS_PROXY | webNav.LOAD_FLAGS_BYPASS_CACHE :
webNav.LOAD_FLAGS_NONE;
try {
webNav.reload(reloadFlags);
} catch(e) {
// Silently swallow errors; these can happen if a used cancels reload
}
},
_recvStop: function(data) {
let webNav = docShell.QueryInterface(Ci.nsIWebNavigation);
webNav.stop(webNav.STOP_NETWORK);
},
_keyEventHandler: function(e) {
if (whitelistedEvents.indexOf(e.keyCode) != -1 && !e.defaultPrevented) {
sendAsyncMsg('keyevent', {
type: e.type,
keyCode: e.keyCode,
charCode: e.charCode,
});
}
},
// The docShell keeps a weak reference to the progress listener, so we need
// to keep a strong ref to it ourselves.
_progressListener: {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener,
Ci.nsISupportsWeakReference]),
_seenLoadStart: false,
onLocationChange: function(webProgress, request, location, flags) {
// We get progress events from subshells here, which is kind of weird.
if (webProgress != docShell) {
return;
}
// Ignore locationchange events which occur before the first loadstart.
// These are usually about:blank loads we don't care about.
if (!this._seenLoadStart) {
return;
}
// Remove password and wyciwyg from uri.
location = Cc["@mozilla.org/docshell/urifixup;1"]
.getService(Ci.nsIURIFixup).createExposableURI(location);
sendAsyncMsg('locationchange', { _payload_: location.spec });
},
onStateChange: function(webProgress, request, stateFlags, status) {
if (webProgress != docShell) {
return;
}
if (stateFlags & Ci.nsIWebProgressListener.STATE_START) {
this._seenLoadStart = true;
sendAsyncMsg('loadstart');
}
if (stateFlags & Ci.nsIWebProgressListener.STATE_STOP) {
sendAsyncMsg('loadend');
// Ignoring NS_BINDING_ABORTED, which is set when loading page is
// stopped.
if (status == Cr.NS_OK ||
status == Cr.NS_BINDING_ABORTED) {
return;
}
// TODO See nsDocShell::DisplayLoadError for a list of all the error
// codes (the status param) we should eventually handle here.
sendAsyncMsg('error', { type: 'other' });
}
},
onSecurityChange: function(webProgress, request, state) {
if (webProgress != docShell) {
return;
}
var stateDesc;
if (state & Ci.nsIWebProgressListener.STATE_IS_SECURE) {
stateDesc = 'secure';
}
else if (state & Ci.nsIWebProgressListener.STATE_IS_BROKEN) {
stateDesc = 'broken';
}
else if (state & Ci.nsIWebProgressListener.STATE_IS_INSECURE) {
stateDesc = 'insecure';
}
else {
debug("Unexpected securitychange state!");
stateDesc = '???';
}
// XXX Until bug 764496 is fixed, this will always return false.
var isEV = !!(state & Ci.nsIWebProgressListener.STATE_IDENTITY_EV_TOPLEVEL);
sendAsyncMsg('securitychange', { state: stateDesc, extendedValidation: isEV });
},
onStatusChange: function(webProgress, request, status, message) {},
onProgressChange: function(webProgress, request, curSelfProgress,
maxSelfProgress, curTotalProgress, maxTotalProgress) {},
},
// Expose the message manager for WebApps and others.
_messageManagerPublic: {
sendAsyncMessage: global.sendAsyncMessage.bind(global),
sendSyncMessage: global.sendSyncMessage.bind(global),
addMessageListener: global.addMessageListener.bind(global),
removeMessageListener: global.removeMessageListener.bind(global)
},
get messageManager() {
return this._messageManagerPublic;
}
};
var api = new BrowserElementChild();
// FIXME/bug 775438: use a JSM?
//
// The code in this included file depends on the |addEventListener|,
// |addMessageListener|, |content|, |Geometry| and |Services| symbols
// being "exported" from here.
#include BrowserElementScrolling.js
var BrowserElementIsReady = true;

View File

@ -0,0 +1,846 @@
/* 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";
dump("######################## BrowserElementChildPreload.js loaded\n");
var BrowserElementIsReady = false;
let { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/BrowserElementPromptService.jsm");
// Event whitelisted for bubbling.
let whitelistedEvents = [
Ci.nsIDOMKeyEvent.DOM_VK_ESCAPE, // Back button.
Ci.nsIDOMKeyEvent.DOM_VK_SLEEP, // Power button.
Ci.nsIDOMKeyEvent.DOM_VK_CONTEXT_MENU,
Ci.nsIDOMKeyEvent.DOM_VK_F5, // Search button.
Ci.nsIDOMKeyEvent.DOM_VK_PAGE_UP, // Volume up.
Ci.nsIDOMKeyEvent.DOM_VK_PAGE_DOWN // Volume down.
];
function debug(msg) {
//dump("BrowserElementChildPreload - " + msg + "\n");
}
function sendAsyncMsg(msg, data) {
// Ensure that we don't send any messages before BrowserElementChild.js
// finishes loading.
if (!BrowserElementIsReady)
return;
if (!data) {
data = { };
}
data.msg_name = msg;
sendAsyncMessage('browser-element-api:call', data);
}
/**
* The BrowserElementChild implements one half of <iframe mozbrowser>.
* (The other half is, unsurprisingly, BrowserElementParent.)
*
* This script is injected into an <iframe mozbrowser> via
* nsIMessageManager::LoadFrameScript().
*
* Our job here is to listen for events within this frame and bubble them up to
* the parent process.
*/
var global = this;
function BrowserElementChild() {
// Maps outer window id --> weak ref to window. Used by modal dialog code.
this._windowIDDict = {};
// _forcedVisible corresponds to the visibility state our owner has set on us
// (via iframe.setVisible). ownerVisible corresponds to whether the docShell
// whose window owns this element is visible.
//
// Our docShell is visible iff _forcedVisible and _ownerVisible are both
// true.
this._forcedVisible = true;
this._ownerVisible = true;
this._nextPaintHandler = null;
this._init();
};
BrowserElementChild.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
Ci.nsISupportsWeakReference]),
_init: function() {
debug("Starting up.");
BrowserElementPromptService.mapWindowToBrowserElementChild(content, this);
docShell.QueryInterface(Ci.nsIWebProgress)
.addProgressListener(this._progressListener,
Ci.nsIWebProgress.NOTIFY_LOCATION |
Ci.nsIWebProgress.NOTIFY_SECURITY |
Ci.nsIWebProgress.NOTIFY_STATE_WINDOW);
docShell.QueryInterface(Ci.nsIWebNavigation)
.sessionHistory = Cc["@mozilla.org/browser/shistory;1"]
.createInstance(Ci.nsISHistory);
// This is necessary to get security web progress notifications.
var securityUI = Cc['@mozilla.org/secure_browser_ui;1']
.createInstance(Ci.nsISecureBrowserUI);
securityUI.init(content);
// A cache of the menuitem dom objects keyed by the id we generate
// and pass to the embedder
this._ctxHandlers = {};
// Counter of contextmenu events fired
this._ctxCounter = 0;
addEventListener('DOMTitleChanged',
this._titleChangedHandler.bind(this),
/* useCapture = */ true,
/* wantsUntrusted = */ false);
addEventListener('DOMLinkAdded',
this._iconChangedHandler.bind(this),
/* useCapture = */ true,
/* wantsUntrusted = */ false);
// Registers a MozAfterPaint handler for the very first paint.
this._addMozAfterPaintHandler(function () {
sendAsyncMsg('firstpaint');
});
let self = this;
let mmCalls = {
"purge-history": this._recvPurgeHistory,
"get-screenshot": this._recvGetScreenshot,
"set-visible": this._recvSetVisible,
"get-visible": this._recvVisible,
"send-mouse-event": this._recvSendMouseEvent,
"send-touch-event": this._recvSendTouchEvent,
"get-can-go-back": this._recvCanGoBack,
"get-can-go-forward": this._recvCanGoForward,
"go-back": this._recvGoBack,
"go-forward": this._recvGoForward,
"reload": this._recvReload,
"stop": this._recvStop,
"unblock-modal-prompt": this._recvStopWaiting,
"fire-ctx-callback": this._recvFireCtxCallback,
"owner-visibility-change": this._recvOwnerVisibilityChange,
"exit-fullscreen": this._recvExitFullscreen.bind(this),
"activate-next-paint-listener": this._activateNextPaintListener.bind(this),
"deactivate-next-paint-listener": this._deactivateNextPaintListener.bind(this)
}
addMessageListener("browser-element-api:call", function(aMessage) {
if (aMessage.data.msg_name in mmCalls) {
return mmCalls[aMessage.data.msg_name].apply(self, arguments);
}
});
let els = Cc["@mozilla.org/eventlistenerservice;1"]
.getService(Ci.nsIEventListenerService);
// We are using the system group for those events so if something in the
// content called .stopPropagation() this will still be called.
els.addSystemEventListener(global, 'keydown',
this._keyEventHandler.bind(this),
/* useCapture = */ true);
els.addSystemEventListener(global, 'keypress',
this._keyEventHandler.bind(this),
/* useCapture = */ true);
els.addSystemEventListener(global, 'keyup',
this._keyEventHandler.bind(this),
/* useCapture = */ true);
els.addSystemEventListener(global, 'DOMWindowClose',
this._windowCloseHandler.bind(this),
/* useCapture = */ false);
els.addSystemEventListener(global, 'DOMWindowCreated',
this._windowCreatedHandler.bind(this),
/* useCapture = */ true);
els.addSystemEventListener(global, 'contextmenu',
this._contextmenuHandler.bind(this),
/* useCapture = */ false);
els.addSystemEventListener(global, 'scroll',
this._scrollEventHandler.bind(this),
/* useCapture = */ false);
Services.obs.addObserver(this,
"fullscreen-origin-change",
/* ownsWeak = */ true);
Services.obs.addObserver(this,
'ask-parent-to-exit-fullscreen',
/* ownsWeak = */ true);
Services.obs.addObserver(this,
'ask-parent-to-rollback-fullscreen',
/* ownsWeak = */ true);
},
observe: function(subject, topic, data) {
// Ignore notifications not about our document.
if (subject != content.document)
return;
switch (topic) {
case 'fullscreen-origin-change':
sendAsyncMsg('fullscreen-origin-change', { _payload_: data });
break;
case 'ask-parent-to-exit-fullscreen':
sendAsyncMsg('exit-fullscreen');
break;
case 'ask-parent-to-rollback-fullscreen':
sendAsyncMsg('rollback-fullscreen');
break;
}
},
_tryGetInnerWindowID: function(win) {
let utils = win.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
try {
return utils.currentInnerWindowID;
}
catch(e) {
return null;
}
},
/**
* Show a modal prompt. Called by BrowserElementPromptService.
*/
showModalPrompt: function(win, args) {
let utils = win.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
args.windowID = { outer: utils.outerWindowID,
inner: this._tryGetInnerWindowID(win) };
sendAsyncMsg('showmodalprompt', args);
let returnValue = this._waitForResult(win);
if (args.promptType == 'prompt' ||
args.promptType == 'confirm' ||
args.promptType == 'custom-prompt') {
return returnValue;
}
},
/**
* Spin in a nested event loop until we receive a unblock-modal-prompt message for
* this window.
*/
_waitForResult: function(win) {
debug("_waitForResult(" + win + ")");
let utils = win.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
let outerWindowID = utils.outerWindowID;
let innerWindowID = this._tryGetInnerWindowID(win);
if (innerWindowID === null) {
// I have no idea what waiting for a result means when there's no inner
// window, so let's just bail.
debug("_waitForResult: No inner window. Bailing.");
return;
}
this._windowIDDict[outerWindowID] = Cu.getWeakReference(win);
debug("Entering modal state (outerWindowID=" + outerWindowID + ", " +
"innerWindowID=" + innerWindowID + ")");
// In theory, we're supposed to pass |modalStateWin| back to
// leaveModalStateWithWindow. But in practice, the window is always null,
// because it's the window associated with this script context, which
// doesn't have a window. But we'll play along anyway in case this
// changes.
var modalStateWin = utils.enterModalStateWithWindow();
// We'll decrement win.modalDepth when we receive a unblock-modal-prompt message
// for the window.
if (!win.modalDepth) {
win.modalDepth = 0;
}
win.modalDepth++;
let origModalDepth = win.modalDepth;
let thread = Services.tm.currentThread;
debug("Nested event loop - begin");
while (win.modalDepth == origModalDepth) {
// Bail out of the loop if the inner window changed; that means the
// window navigated.
if (this._tryGetInnerWindowID(win) !== innerWindowID) {
debug("_waitForResult: Inner window ID changed " +
"while in nested event loop.");
break;
}
thread.processNextEvent(/* mayWait = */ true);
}
debug("Nested event loop - finish");
// If we exited the loop because the inner window changed, then bail on the
// modal prompt.
if (innerWindowID !== this._tryGetInnerWindowID(win)) {
throw Components.Exception("Modal state aborted by navigation",
Cr.NS_ERROR_NOT_AVAILABLE);
}
let returnValue = win.modalReturnValue;
delete win.modalReturnValue;
utils.leaveModalStateWithWindow(modalStateWin);
debug("Leaving modal state (outerID=" + outerWindowID + ", " +
"innerID=" + innerWindowID + ")");
return returnValue;
},
_recvStopWaiting: function(msg) {
let outerID = msg.json.windowID.outer;
let innerID = msg.json.windowID.inner;
let returnValue = msg.json.returnValue;
debug("recvStopWaiting(outer=" + outerID + ", inner=" + innerID +
", returnValue=" + returnValue + ")");
if (!this._windowIDDict[outerID]) {
debug("recvStopWaiting: No record of outer window ID " + outerID);
return;
}
let win = this._windowIDDict[outerID].get();
delete this._windowIDDict[outerID];
if (!win) {
debug("recvStopWaiting, but window is gone\n");
return;
}
if (innerID !== this._tryGetInnerWindowID(win)) {
debug("recvStopWaiting, but inner ID has changed\n");
return;
}
debug("recvStopWaiting " + win);
win.modalReturnValue = returnValue;
win.modalDepth--;
},
_recvExitFullscreen: function() {
var utils = content.document.defaultView
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
utils.exitFullscreen();
},
_titleChangedHandler: function(e) {
debug("Got titlechanged: (" + e.target.title + ")");
var win = e.target.defaultView;
// Ignore titlechanges which don't come from the top-level
// <iframe mozbrowser> window.
if (win == content) {
sendAsyncMsg('titlechange', { _payload_: e.target.title });
}
else {
debug("Not top level!");
}
},
_iconChangedHandler: function(e) {
debug("Got iconchanged: (" + e.target.href + ")");
var hasIcon = e.target.rel.split(' ').some(function(x) {
return x.toLowerCase() === 'icon';
});
if (hasIcon) {
var win = e.target.ownerDocument.defaultView;
// Ignore iconchanges which don't come from the top-level
// <iframe mozbrowser> window.
if (win == content) {
sendAsyncMsg('iconchange', { _payload_: e.target.href });
}
else {
debug("Not top level!");
}
}
},
_addMozAfterPaintHandler: function(callback) {
function onMozAfterPaint() {
let uri = docShell.QueryInterface(Ci.nsIWebNavigation).currentURI;
if (uri.spec != "about:blank") {
debug("Got afterpaint event: " + uri.spec);
removeEventListener('MozAfterPaint', onMozAfterPaint,
/* useCapture = */ true);
callback();
}
}
addEventListener('MozAfterPaint', onMozAfterPaint, /* useCapture = */ true);
return onMozAfterPaint;
},
_removeMozAfterPaintHandler: function(listener) {
removeEventListener('MozAfterPaint', listener,
/* useCapture = */ true);
},
_activateNextPaintListener: function(e) {
if (!this._nextPaintHandler) {
this._nextPaintHandler = this._addMozAfterPaintHandler(function () {
this._nextPaintHandler = null;
sendAsyncMsg('nextpaint');
}.bind(this));
}
},
_deactivateNextPaintListener: function(e) {
if (this._nextPaintHandler) {
this._removeMozAfterPaintHandler(this._nextPaintHandler);
this._nextPaintHandler = null;
}
},
_windowCloseHandler: function(e) {
let win = e.target;
if (win != content || e.defaultPrevented) {
return;
}
debug("Closing window " + win);
sendAsyncMsg('close');
// Inform the window implementation that we handled this close ourselves.
e.preventDefault();
},
_windowCreatedHandler: function(e) {
let targetDocShell = e.target.defaultView
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation);
if (targetDocShell != docShell) {
return;
}
let uri = docShell.QueryInterface(Ci.nsIWebNavigation).currentURI;
debug("Window created: " + uri.spec);
if (uri.spec != "about:blank") {
this._addMozAfterPaintHandler(function () {
sendAsyncMsg('documentfirstpaint');
});
}
},
_contextmenuHandler: function(e) {
debug("Got contextmenu");
if (e.defaultPrevented) {
return;
}
e.preventDefault();
this._ctxCounter++;
this._ctxHandlers = {};
var elem = e.target;
var menuData = {systemTargets: [], contextmenu: null};
var ctxMenuId = null;
while (elem && elem.parentNode) {
var ctxData = this._getSystemCtxMenuData(elem);
if (ctxData) {
menuData.systemTargets.push({
nodeName: elem.nodeName,
data: ctxData
});
}
if (!ctxMenuId && 'hasAttribute' in elem && elem.hasAttribute('contextmenu')) {
ctxMenuId = elem.getAttribute('contextmenu');
}
elem = elem.parentNode;
}
if (ctxMenuId) {
var menu = e.target.ownerDocument.getElementById(ctxMenuId);
if (menu) {
menuData.contextmenu = this._buildMenuObj(menu, '');
}
}
sendAsyncMsg('contextmenu', menuData);
},
_getSystemCtxMenuData: function(elem) {
if ((elem instanceof Ci.nsIDOMHTMLAnchorElement && elem.href) ||
(elem instanceof Ci.nsIDOMHTMLAreaElement && elem.href)) {
return elem.href;
}
if (elem instanceof Ci.nsIImageLoadingContent && elem.currentURI) {
return elem.currentURI.spec;
}
if ((elem instanceof Ci.nsIDOMHTMLMediaElement) ||
(elem instanceof Ci.nsIDOMHTMLImageElement)) {
return elem.currentSrc || elem.src;
}
return false;
},
_scrollEventHandler: function(e) {
let win = e.target.defaultView;
if (win != content) {
return;
}
debug("scroll event " + win);
sendAsyncMsg("scroll", { top: win.scrollY, left: win.scrollX });
},
_recvPurgeHistory: function(data) {
debug("Received purgeHistory message: (" + data.json.id + ")");
let history = docShell.QueryInterface(Ci.nsIWebNavigation).sessionHistory;
try {
if (history && history.count) {
history.PurgeHistory(history.count);
}
} catch(e) {}
sendAsyncMsg('got-purge-history', { id: data.json.id, successRv: true });
},
_recvGetScreenshot: function(data) {
debug("Received getScreenshot message: (" + data.json.id + ")");
let self = this;
let maxWidth = data.json.args.width;
let maxHeight = data.json.args.height;
let domRequestID = data.json.id;
let takeScreenshotClosure = function() {
self._takeScreenshot(maxWidth, maxHeight, domRequestID);
};
let maxDelayMS = 2000;
try {
maxDelayMS = Services.prefs.getIntPref('dom.browserElement.maxScreenshotDelayMS');
}
catch(e) {}
// Try to wait for the event loop to go idle before we take the screenshot,
// but once we've waited maxDelayMS milliseconds, go ahead and take it
// anyway.
Cc['@mozilla.org/message-loop;1'].getService(Ci.nsIMessageLoop).postIdleTask(
takeScreenshotClosure, maxDelayMS);
},
/**
* Actually take a screenshot and foward the result up to our parent, given
* the desired maxWidth and maxHeight, and given the DOMRequest ID associated
* with the request from the parent.
*/
_takeScreenshot: function(maxWidth, maxHeight, domRequestID) {
// You can think of the screenshotting algorithm as carrying out the
// following steps:
//
// - Let scaleWidth be the factor by which we'd need to downscale the
// viewport so it would fit within maxWidth. (If the viewport's width
// is less than maxWidth, let scaleWidth be 1.) Compute scaleHeight
// the same way.
//
// - Scale the viewport by max(scaleWidth, scaleHeight). Now either the
// viewport's width is no larger than maxWidth, the viewport's height is
// no larger than maxHeight, or both.
//
// - Crop the viewport so its width is no larger than maxWidth and its
// height is no larger than maxHeight.
//
// - Return a screenshot of the page's viewport scaled and cropped per
// above.
debug("Taking a screenshot: maxWidth=" + maxWidth +
", maxHeight=" + maxHeight +
", domRequestID=" + domRequestID + ".");
let scaleWidth = Math.min(1, maxWidth / content.innerWidth);
let scaleHeight = Math.min(1, maxHeight / content.innerHeight);
let scale = Math.max(scaleWidth, scaleHeight);
let canvasWidth = Math.min(maxWidth, Math.round(content.innerWidth * scale));
let canvasHeight = Math.min(maxHeight, Math.round(content.innerHeight * scale));
var canvas = content.document
.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
canvas.mozOpaque = true;
canvas.width = canvasWidth;
canvas.height = canvasHeight;
var ctx = canvas.getContext("2d");
ctx.scale(scale, scale);
ctx.drawWindow(content, 0, 0, content.innerWidth, content.innerHeight,
"rgb(255,255,255)");
// Take a JPEG screenshot to hack around the fact that we can't specify
// opaque PNG. This requires us to unpremultiply the alpha channel, which
// is expensive on ARM processors because they lack a hardware integer
// division instruction.
canvas.toBlob(function(blob) {
sendAsyncMsg('got-screenshot', {
id: domRequestID,
successRv: blob
});
}, 'image/jpeg');
},
_recvFireCtxCallback: function(data) {
debug("Received fireCtxCallback message: (" + data.json.menuitem + ")");
// We silently ignore if the embedder uses an incorrect id in the callback
if (data.json.menuitem in this._ctxHandlers) {
this._ctxHandlers[data.json.menuitem].click();
this._ctxHandlers = {};
} else {
debug("Ignored invalid contextmenu invocation");
}
},
_buildMenuObj: function(menu, idPrefix) {
function maybeCopyAttribute(src, target, attribute) {
if (src.getAttribute(attribute)) {
target[attribute] = src.getAttribute(attribute);
}
}
var menuObj = {type: 'menu', items: []};
maybeCopyAttribute(menu, menuObj, 'label');
for (var i = 0, child; child = menu.children[i++];) {
if (child.nodeName === 'MENU') {
menuObj.items.push(this._buildMenuObj(child, idPrefix + i + '_'));
} else if (child.nodeName === 'MENUITEM') {
var id = this._ctxCounter + '_' + idPrefix + i;
var menuitem = {id: id, type: 'menuitem'};
maybeCopyAttribute(child, menuitem, 'label');
maybeCopyAttribute(child, menuitem, 'icon');
this._ctxHandlers[id] = child;
menuObj.items.push(menuitem);
}
}
return menuObj;
},
_recvSetVisible: function(data) {
debug("Received setVisible message: (" + data.json.visible + ")");
this._forcedVisible = data.json.visible;
this._updateDocShellVisibility();
},
_recvVisible: function(data) {
sendAsyncMsg('got-visible', {
id: data.json.id,
successRv: docShell.isActive
});
},
/**
* Called when the window which contains this iframe becomes hidden or
* visible.
*/
_recvOwnerVisibilityChange: function(data) {
debug("Received ownerVisibilityChange: (" + data.json.visible + ")");
this._ownerVisible = data.json.visible;
this._updateDocShellVisibility();
},
_updateDocShellVisibility: function() {
var visible = this._forcedVisible && this._ownerVisible;
if (docShell.isActive !== visible) {
docShell.isActive = visible;
}
},
_recvSendMouseEvent: function(data) {
let json = data.json;
let utils = content.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
utils.sendMouseEvent(json.type, json.x, json.y, json.button,
json.clickCount, json.modifiers);
},
_recvSendTouchEvent: function(data) {
let json = data.json;
let utils = content.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
utils.sendTouchEvent(json.type, json.identifiers, json.touchesX,
json.touchesY, json.radiisX, json.radiisY,
json.rotationAngles, json.forces, json.count,
json.modifiers);
},
_recvCanGoBack: function(data) {
var webNav = docShell.QueryInterface(Ci.nsIWebNavigation);
sendAsyncMsg('got-can-go-back', {
id: data.json.id,
successRv: webNav.canGoBack
});
},
_recvCanGoForward: function(data) {
var webNav = docShell.QueryInterface(Ci.nsIWebNavigation);
sendAsyncMsg('got-can-go-forward', {
id: data.json.id,
successRv: webNav.canGoForward
});
},
_recvGoBack: function(data) {
try {
docShell.QueryInterface(Ci.nsIWebNavigation).goBack();
} catch(e) {
// Silently swallow errors; these happen when we can't go back.
}
},
_recvGoForward: function(data) {
try {
docShell.QueryInterface(Ci.nsIWebNavigation).goForward();
} catch(e) {
// Silently swallow errors; these happen when we can't go forward.
}
},
_recvReload: function(data) {
let webNav = docShell.QueryInterface(Ci.nsIWebNavigation);
let reloadFlags = data.json.hardReload ?
webNav.LOAD_FLAGS_BYPASS_PROXY | webNav.LOAD_FLAGS_BYPASS_CACHE :
webNav.LOAD_FLAGS_NONE;
try {
webNav.reload(reloadFlags);
} catch(e) {
// Silently swallow errors; these can happen if a used cancels reload
}
},
_recvStop: function(data) {
let webNav = docShell.QueryInterface(Ci.nsIWebNavigation);
webNav.stop(webNav.STOP_NETWORK);
},
_keyEventHandler: function(e) {
if (whitelistedEvents.indexOf(e.keyCode) != -1 && !e.defaultPrevented) {
sendAsyncMsg('keyevent', {
type: e.type,
keyCode: e.keyCode,
charCode: e.charCode,
});
}
},
// The docShell keeps a weak reference to the progress listener, so we need
// to keep a strong ref to it ourselves.
_progressListener: {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener,
Ci.nsISupportsWeakReference]),
_seenLoadStart: false,
onLocationChange: function(webProgress, request, location, flags) {
// We get progress events from subshells here, which is kind of weird.
if (webProgress != docShell) {
return;
}
// Ignore locationchange events which occur before the first loadstart.
// These are usually about:blank loads we don't care about.
if (!this._seenLoadStart) {
return;
}
// Remove password and wyciwyg from uri.
location = Cc["@mozilla.org/docshell/urifixup;1"]
.getService(Ci.nsIURIFixup).createExposableURI(location);
sendAsyncMsg('locationchange', { _payload_: location.spec });
},
onStateChange: function(webProgress, request, stateFlags, status) {
if (webProgress != docShell) {
return;
}
if (stateFlags & Ci.nsIWebProgressListener.STATE_START) {
this._seenLoadStart = true;
sendAsyncMsg('loadstart');
}
if (stateFlags & Ci.nsIWebProgressListener.STATE_STOP) {
sendAsyncMsg('loadend');
// Ignoring NS_BINDING_ABORTED, which is set when loading page is
// stopped.
if (status == Cr.NS_OK ||
status == Cr.NS_BINDING_ABORTED) {
return;
}
// TODO See nsDocShell::DisplayLoadError for a list of all the error
// codes (the status param) we should eventually handle here.
sendAsyncMsg('error', { type: 'other' });
}
},
onSecurityChange: function(webProgress, request, state) {
if (webProgress != docShell) {
return;
}
var stateDesc;
if (state & Ci.nsIWebProgressListener.STATE_IS_SECURE) {
stateDesc = 'secure';
}
else if (state & Ci.nsIWebProgressListener.STATE_IS_BROKEN) {
stateDesc = 'broken';
}
else if (state & Ci.nsIWebProgressListener.STATE_IS_INSECURE) {
stateDesc = 'insecure';
}
else {
debug("Unexpected securitychange state!");
stateDesc = '???';
}
// XXX Until bug 764496 is fixed, this will always return false.
var isEV = !!(state & Ci.nsIWebProgressListener.STATE_IDENTITY_EV_TOPLEVEL);
sendAsyncMsg('securitychange', { state: stateDesc, extendedValidation: isEV });
},
onStatusChange: function(webProgress, request, status, message) {},
onProgressChange: function(webProgress, request, curSelfProgress,
maxSelfProgress, curTotalProgress, maxTotalProgress) {},
},
// Expose the message manager for WebApps and others.
_messageManagerPublic: {
sendAsyncMessage: global.sendAsyncMessage.bind(global),
sendSyncMessage: global.sendSyncMessage.bind(global),
addMessageListener: global.addMessageListener.bind(global),
removeMessageListener: global.removeMessageListener.bind(global)
},
get messageManager() {
return this._messageManagerPublic;
}
};
var api = new BrowserElementChild();

View File

@ -5,6 +5,14 @@
* 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";
dump("############################### browserElementPanning.js loaded\n");
let { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/Geometry.jsm");
const ContentPanning = {
// Are we listening to touch or mouse events?
watchedEventsType: '',
@ -35,8 +43,8 @@ const ContentPanning = {
this.watchedEventsType = 'mouse';
}
events.forEach(function(type) {
addEventListener(type, ContentPanning, false);
});
addEventListener(type, this, false);
}.bind(this));
addMessageListener("Viewport:Change", this._recvViewportChange.bind(this));
addMessageListener("Gesture:DoubleTap", this._recvDoubleTap.bind(this));

View File

@ -95,8 +95,6 @@ function BrowserElementParent(frameLoader, hasRemoteFrame) {
// We use a single message and dispatch to various function based
// on data.msg_name
let mmCalls = {
"get-name": this._recvGetName,
"get-fullscreen-allowed": this._recvGetFullscreenAllowed,
"hello": this._recvHello,
"contextmenu": this._fireCtxMenuEvent,
"locationchange": this._fireEventFromMsg,
@ -281,15 +279,13 @@ BrowserElementParent.prototype = {
if (this._window.document.hidden) {
this._ownerVisibilityChange();
}
},
_recvGetName: function(data) {
return this._frameElement.getAttribute('name');
},
_recvGetFullscreenAllowed: function(data) {
return this._frameElement.hasAttribute('allowfullscreen') ||
this._frameElement.hasAttribute('mozallowfullscreen');
return {
name: this._frameElement.getAttribute('name'),
fullscreenAllowed:
this._frameElement.hasAttribute('allowfullscreen') ||
this._frameElement.hasAttribute('mozallowfullscreen')
}
},
_fireCtxMenuEvent: function(data) {
@ -321,7 +317,7 @@ BrowserElementParent.prototype = {
// For events that send a "_payload_" property, we just want to transmit
// this in the event.
if (detail._payload_) {
if ("_payload_" in detail) {
detail = detail._payload_;
}
@ -571,7 +567,7 @@ BrowserElementParent.prototype = {
},
_remoteFullscreenOriginChange: function(data) {
let origin = data.json;
let origin = data.json._payload_;
this._windowUtils.remoteFrameFullscreenChanged(this._frameElement, origin);
},

View File

@ -93,6 +93,9 @@ function testEtwsMessageAttributes() {
cbs.addEventListener("received", function onreceived(event) {
cbs.removeEventListener("received", onreceived);
// Bug 838542: following check throws an exception and fails this case.
// ok(event instanceof MozCellBroadcastEvent,
// "event is instanceof " + event.constructor)
ok(event, "event is valid");
let message = event.message;

View File

@ -148,6 +148,9 @@ function testGsmMessageAttributes() {
cbs.addEventListener("received", function onreceived(event) {
cbs.removeEventListener("received", onreceived);
// Bug 838542: following check throws an exception and fails this case.
// ok(event instanceof MozCellBroadcastEvent,
// "event is instanceof " + event.constructor)
ok(event, "event is valid");
let message = event.message;

View File

@ -57,17 +57,16 @@ class FileUpdateDispatcher MOZ_FINAL
};
class nsDOMDeviceStorage MOZ_FINAL
: public nsIDOMDeviceStorage
, public nsDOMEventTargetHelper
: public nsDOMEventTargetHelper
, public nsIDOMDeviceStorage
, public nsIObserver
{
public:
NS_DECL_ISUPPORTS
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIDOMDEVICESTORAGE
NS_DECL_NSIOBSERVER
NS_DECL_NSIDOMEVENTTARGET
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsDOMDeviceStorage, nsDOMEventTargetHelper)
nsDOMDeviceStorage();

View File

@ -1818,11 +1818,9 @@ NS_IMPL_CYCLE_COLLECTION_5(DeviceStorageRequest,
mListener)
NS_IMPL_CYCLE_COLLECTION_INHERITED_0(nsDOMDeviceStorage, nsDOMEventTargetHelper)
DOMCI_DATA(DeviceStorage, nsDOMDeviceStorage)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsDOMDeviceStorage)
NS_INTERFACE_MAP_BEGIN(nsDOMDeviceStorage)
NS_INTERFACE_MAP_ENTRY(nsIDOMDeviceStorage)
NS_INTERFACE_MAP_ENTRY(nsIObserver)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(DeviceStorage)

View File

@ -11050,8 +11050,6 @@
"[[\"removeformat\",\"\"]] \"foo<del>b[a]r</del>baz\" compare innerHTML":true,
"[[\"removeformat\",\"\"]] \"[foo<nobr>bar</nobr>baz]\" compare innerHTML":true,
"[[\"removeformat\",\"\"]] \"foo<nobr>b[a]r</nobr>baz\" compare innerHTML":true,
"[[\"removeformat\",\"\"]] \"[foo<video></video>bar]\" compare innerHTML":true,
"[[\"removeformat\",\"\"]] \"[foo<video src=abc></video>bar]\" compare innerHTML":true,
"[[\"removeformat\",\"\"]] \"[foo<svg><circle fill=blue r=20 cx=20 cy=20 /></svg>bar]\" compare innerHTML":true,
"[[\"removeformat\",\"\"]] \"[foo<nonexistentelement>bar</nonexistentelement>baz]\" compare innerHTML":true,
"[[\"removeformat\",\"\"]] \"foo<nonexistentelement>b[a]r</nonexistentelement>baz\" compare innerHTML":true,

View File

@ -325,8 +325,6 @@ NS_NewDOMAnimationEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresCo
nsresult
NS_NewDOMTouchEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, class nsTouchEvent *aEvent);
nsresult
NS_NewDOMSmsEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, nsEvent* aEvent);
nsresult
NS_NewDOMMozSettingsEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, nsEvent* aEvent);
nsresult
NS_NewDOMMozApplicationEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, nsEvent* aEvent);

View File

@ -166,6 +166,10 @@ interface nsIDOMKeyEvent : nsIDOMUIEvent
const unsigned long DOM_VK_TILDE = 0xB0;
const unsigned long DOM_VK_VOLUME_MUTE = 0xB5;
const unsigned long DOM_VK_VOLUME_DOWN = 0xB6;
const unsigned long DOM_VK_VOLUME_UP = 0xB7;
const unsigned long DOM_VK_COMMA = 0xBC;
const unsigned long DOM_VK_PERIOD = 0xBE;
const unsigned long DOM_VK_SLASH = 0xBF;

View File

@ -16,7 +16,7 @@
* http://www.whatwg.org/specs/web-apps/current-work/
*/
[scriptable, uuid(526C4DC4-25CD-46DE-A9B2-1501D624F7DF)]
[scriptable, builtinclass, uuid(526C4DC4-25CD-46DE-A9B2-1501D624F7DF)]
interface nsIDOMHTMLTableCaptionElement : nsIDOMHTMLElement
{
attribute DOMString align;

View File

@ -16,7 +16,7 @@
* http://www.whatwg.org/specs/web-apps/current-work/
*/
[scriptable, uuid(006D2482-0B89-401B-9A16-EDE4D9971F02)]
[scriptable, builtinclass, uuid(006D2482-0B89-401B-9A16-EDE4D9971F02)]
interface nsIDOMHTMLTableSectionElement : nsIDOMHTMLElement
{
attribute DOMString align;

View File

@ -22,7 +22,10 @@ ifneq (cocoa,$(MOZ_WIDGET_TOOLKIT))
TEST_DIRS += tests
endif
EXPORTS = PCOMContentPermissionRequestChild.h
EXPORTS = \
nsICachedFileDescriptorListener.h \
PCOMContentPermissionRequestChild.h \
$(NULL)
EXPORTS_NAMESPACES = \
mozilla \

View File

@ -31,6 +31,7 @@ using gfxSize;
using mozilla::layers::LayersBackend;
using mozilla::layers::FrameMetrics;
using mozilla::layout::ScrollingBehavior;
using mozilla::void_t;
using mozilla::WindowsHandle;
using nscolor;
using nsCompositionEvent;
@ -290,6 +291,8 @@ child:
LoadURL(nsCString uri);
CacheFileDescriptor(nsString path, FileDescriptor fd);
UpdateDimensions(nsRect rect, nsIntSize size, ScreenOrientation orientation) compress;
UpdateFrame(FrameMetrics frame) compress;

View File

@ -18,6 +18,7 @@
#include "mozilla/dom/PContentChild.h"
#include "mozilla/dom/PContentDialogChild.h"
#include "mozilla/ipc/DocumentRendererChild.h"
#include "mozilla/ipc/FileDescriptorUtils.h"
#include "mozilla/layers/AsyncPanZoomController.h"
#include "mozilla/layers/CompositorChild.h"
#include "mozilla/layers/PLayersChild.h"
@ -37,6 +38,7 @@
#include "mozilla/dom/Element.h"
#include "nsIAppsService.h"
#include "nsIBaseWindow.h"
#include "nsICachedFileDescriptorListener.h"
#include "nsIComponentManager.h"
#include "nsIDocumentInlines.h"
#include "nsIDOMClassInfo.h"
@ -121,6 +123,98 @@ public:
const InfallibleTArray<nsString>& aStringParams);
};
class TabChild::CachedFileDescriptorInfo
{
struct PathOnlyComparatorHelper
{
bool Equals(const nsAutoPtr<CachedFileDescriptorInfo>& a,
const CachedFileDescriptorInfo& b) const
{
return a->mPath == b.mPath;
}
};
struct PathAndCallbackComparatorHelper
{
bool Equals(const nsAutoPtr<CachedFileDescriptorInfo>& a,
const CachedFileDescriptorInfo& b) const
{
return a->mPath == b.mPath &&
a->mCallback == b.mCallback;
}
};
public:
nsString mPath;
FileDescriptor mFileDescriptor;
nsCOMPtr<nsICachedFileDescriptorListener> mCallback;
bool mCanceled;
CachedFileDescriptorInfo(const nsAString& aPath)
: mPath(aPath), mCanceled(false)
{ }
CachedFileDescriptorInfo(const nsAString& aPath,
const FileDescriptor& aFileDescriptor)
: mPath(aPath), mFileDescriptor(aFileDescriptor), mCanceled(false)
{ }
CachedFileDescriptorInfo(const nsAString& aPath,
nsICachedFileDescriptorListener* aCallback)
: mPath(aPath), mCallback(aCallback), mCanceled(false)
{ }
PathOnlyComparatorHelper PathOnlyComparator() const
{
return PathOnlyComparatorHelper();
}
PathAndCallbackComparatorHelper PathAndCallbackComparator() const
{
return PathAndCallbackComparatorHelper();
}
void FireCallback() const
{
mCallback->OnCachedFileDescriptor(mPath, mFileDescriptor);
}
};
class TabChild::CachedFileDescriptorCallbackRunnable : public nsRunnable
{
typedef TabChild::CachedFileDescriptorInfo CachedFileDescriptorInfo;
nsAutoPtr<CachedFileDescriptorInfo> mInfo;
public:
CachedFileDescriptorCallbackRunnable(CachedFileDescriptorInfo* aInfo)
: mInfo(aInfo)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aInfo);
MOZ_ASSERT(!aInfo->mPath.IsEmpty());
MOZ_ASSERT(aInfo->mCallback);
}
void Dispatch()
{
MOZ_ASSERT(NS_IsMainThread());
nsresult rv = NS_DispatchToCurrentThread(this);
NS_ENSURE_SUCCESS_VOID(rv);
}
private:
NS_IMETHOD Run()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mInfo);
mInfo->FireCallback();
return NS_OK;
}
};
StaticRefPtr<TabChild> sPreallocatedTab;
/*static*/ void
@ -135,8 +229,6 @@ TabChild::PreloadSlowThings()
}
// Just load and compile these scripts, but don't run them.
tab->TryCacheLoadAndCompileScript(BROWSER_ELEMENT_CHILD_SCRIPT);
tab->TryCacheLoadAndCompileScript(
NS_LITERAL_STRING("chrome://browser/content/forms.js"));
// Load, compile, and run these scripts.
tab->RecvLoadRemoteScript(
NS_LITERAL_STRING("chrome://global/content/preload.js"));
@ -1119,6 +1211,130 @@ TabChild::RecvLoadURL(const nsCString& uri)
return true;
}
bool
TabChild::RecvCacheFileDescriptor(const nsString& aPath,
const FileDescriptor& aFileDescriptor)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!aPath.IsEmpty());
// aFileDescriptor may be invalid here, but the callback will choose how to
// handle it.
// First see if we already have a request for this path.
const CachedFileDescriptorInfo search(aPath);
uint32_t index =
mCachedFileDescriptorInfos.IndexOf(search, 0,
search.PathOnlyComparator());
if (index == mCachedFileDescriptorInfos.NoIndex) {
// We haven't had any requests for this path yet. Assume that we will
// in a little while and save the file descriptor here.
mCachedFileDescriptorInfos.AppendElement(
new CachedFileDescriptorInfo(aPath, aFileDescriptor));
return true;
}
nsAutoPtr<CachedFileDescriptorInfo>& info =
mCachedFileDescriptorInfos[index];
MOZ_ASSERT(info);
MOZ_ASSERT(info->mPath == aPath);
MOZ_ASSERT(!info->mFileDescriptor.IsValid());
MOZ_ASSERT(info->mCallback);
// If this callback has been canceled then we can simply close the file
// descriptor and forget about the callback.
if (info->mCanceled) {
// Only close if this is a valid file descriptor.
if (aFileDescriptor.IsValid()) {
nsRefPtr<CloseFileRunnable> runnable =
new CloseFileRunnable(aFileDescriptor);
runnable->Dispatch();
}
} else {
// Not canceled so fire the callback.
info->mFileDescriptor = aFileDescriptor;
// We don't need a runnable here because we should already be at the top
// of the event loop. Just fire immediately.
info->FireCallback();
}
mCachedFileDescriptorInfos.RemoveElementAt(index);
return true;
}
bool
TabChild::GetCachedFileDescriptor(const nsAString& aPath,
nsICachedFileDescriptorListener* aCallback)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!aPath.IsEmpty());
MOZ_ASSERT(aCallback);
// First see if we've already received a cached file descriptor for this
// path.
const CachedFileDescriptorInfo search(aPath);
uint32_t index =
mCachedFileDescriptorInfos.IndexOf(search, 0,
search.PathOnlyComparator());
if (index == mCachedFileDescriptorInfos.NoIndex) {
// We haven't received a file descriptor for this path yet. Assume that
// we will in a little while and save the request here.
mCachedFileDescriptorInfos.AppendElement(
new CachedFileDescriptorInfo(aPath, aCallback));
return false;
}
nsAutoPtr<CachedFileDescriptorInfo>& info =
mCachedFileDescriptorInfos[index];
MOZ_ASSERT(info);
MOZ_ASSERT(info->mPath == aPath);
MOZ_ASSERT(!info->mCallback);
MOZ_ASSERT(!info->mCanceled);
info->mCallback = aCallback;
nsRefPtr<CachedFileDescriptorCallbackRunnable> runnable =
new CachedFileDescriptorCallbackRunnable(info);
runnable->Dispatch();
mCachedFileDescriptorInfos.RemoveElementAt(index);
return true;
}
void
TabChild::CancelCachedFileDescriptorCallback(
const nsAString& aPath,
nsICachedFileDescriptorListener* aCallback)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!aPath.IsEmpty());
MOZ_ASSERT(aCallback);
const CachedFileDescriptorInfo search(aPath, aCallback);
uint32_t index =
mCachedFileDescriptorInfos.IndexOf(search, 0,
search.PathAndCallbackComparator());
if (index == mCachedFileDescriptorInfos.NoIndex) {
// Nothing to do here.
return;
}
nsAutoPtr<CachedFileDescriptorInfo>& info =
mCachedFileDescriptorInfos[index];
MOZ_ASSERT(info);
MOZ_ASSERT(info->mPath == aPath);
MOZ_ASSERT(!info->mFileDescriptor.IsValid());
MOZ_ASSERT(info->mCallback == aCallback);
MOZ_ASSERT(!info->mCanceled);
// Set this flag so that we will close the file descriptor when it arrives.
info->mCanceled = true;
}
void
TabChild::DoFakeShow()
{

View File

@ -54,6 +54,7 @@
#include "mozilla/dom/TabContext.h"
struct gfxMatrix;
class nsICachedFileDescriptorListener;
namespace mozilla {
namespace layout {
@ -196,6 +197,9 @@ public:
const mozilla::dom::StructuredCloneData& aData);
virtual bool RecvLoadURL(const nsCString& uri);
virtual bool RecvCacheFileDescriptor(const nsString& aPath,
const FileDescriptor& aFileDescriptor)
MOZ_OVERRIDE;
virtual bool RecvShow(const nsIntSize& size);
virtual bool RecvUpdateDimensions(const nsRect& rect, const nsIntSize& size, const ScreenOrientation& orientation);
virtual bool RecvUpdateFrame(const mozilla::layers::FrameMetrics& aFrameMetrics);
@ -317,6 +321,15 @@ public:
*/
void GetAppType(nsAString& aAppType) const { aAppType = mAppType; }
// Returns true if the file descriptor was found in the cache, false
// otherwise.
bool GetCachedFileDescriptor(const nsAString& aPath,
nsICachedFileDescriptorListener* aCallback);
void CancelCachedFileDescriptorCallback(
const nsAString& aPath,
nsICachedFileDescriptorListener* aCallback);
protected:
virtual PRenderFrameChild* AllocPRenderFrame(ScrollingBehavior* aScrolling,
LayersBackend* aBackend,
@ -412,6 +425,9 @@ private:
return utils;
}
class CachedFileDescriptorInfo;
class CachedFileDescriptorCallbackRunnable;
nsCOMPtr<nsIWebNavigation> mWebNav;
nsCOMPtr<nsIWidget> mWidget;
nsCOMPtr<nsIURI> mLastURI;
@ -430,6 +446,9 @@ private:
// the touch we're tracking. That is, if touchend or a touchmove
// that exceeds the gesture threshold doesn't happen.
CancelableTask* mTapHoldTimer;
// At present only 1 of these is really expected.
nsAutoTArray<nsAutoPtr<CachedFileDescriptorInfo>, 1>
mCachedFileDescriptorInfos;
float mOldViewportWidth;
nscolor mLastBackgroundColor;
ScrollingBehavior mScrolling;

View File

@ -50,6 +50,7 @@
#include "nsSerializationHelper.h"
#include "nsServiceManagerUtils.h"
#include "nsThreadUtils.h"
#include "private/pprio.h"
#include "StructuredCloneUtils.h"
#include "TabChild.h"
#include <algorithm>
@ -66,6 +67,116 @@ using namespace mozilla::dom::indexedDB;
// from the ones registered by webProgressListeners.
#define NOTIFY_FLAG_SHIFT 16
class OpenFileAndSendFDRunnable : public nsRunnable
{
const nsString mPath;
nsRefPtr<TabParent> mTabParent;
nsCOMPtr<nsIEventTarget> mEventTarget;
PRFileDesc* mFD;
public:
OpenFileAndSendFDRunnable(const nsAString& aPath, TabParent* aTabParent)
: mPath(aPath), mTabParent(aTabParent), mFD(nullptr)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!aPath.IsEmpty());
MOZ_ASSERT(aTabParent);
}
void Dispatch()
{
MOZ_ASSERT(NS_IsMainThread());
mEventTarget = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
NS_ENSURE_TRUE_VOID(mEventTarget);
nsresult rv = mEventTarget->Dispatch(this, NS_DISPATCH_NORMAL);
NS_ENSURE_SUCCESS_VOID(rv);
}
private:
~OpenFileAndSendFDRunnable()
{
MOZ_ASSERT(!mFD);
}
// This shouldn't be called directly except by the event loop. Use Dispatch
// to start the sequence.
NS_IMETHOD Run()
{
if (NS_IsMainThread()) {
SendResponse();
} else if (mFD) {
CloseFile();
} else {
OpenFile();
}
return NS_OK;
}
void SendResponse()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mTabParent);
MOZ_ASSERT(mEventTarget);
MOZ_ASSERT(mFD);
nsRefPtr<TabParent> tabParent;
mTabParent.swap(tabParent);
FileDescriptor::PlatformHandleType handle =
FileDescriptor::PlatformHandleType(PR_FileDesc2NativeHandle(mFD));
mozilla::unused << tabParent->SendCacheFileDescriptor(mPath, handle);
nsCOMPtr<nsIEventTarget> eventTarget;
mEventTarget.swap(eventTarget);
if (NS_FAILED(eventTarget->Dispatch(this, NS_DISPATCH_NORMAL))) {
NS_WARNING("Failed to dispatch to stream transport service!");
// It's probably safer to take the main thread IO hit here rather
// than leak a file descriptor.
CloseFile();
}
}
void OpenFile()
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(!mFD);
nsCOMPtr<nsIFile> file;
nsresult rv = NS_NewLocalFile(mPath, false, getter_AddRefs(file));
NS_ENSURE_SUCCESS_VOID(rv);
PRFileDesc* fd;
rv = file->OpenNSPRFileDesc(PR_RDONLY, 0, &fd);
NS_ENSURE_SUCCESS_VOID(rv);
mFD = fd;
if (NS_FAILED(NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL))) {
NS_WARNING("Failed to dispatch to main thread!");
CloseFile();
}
}
void CloseFile()
{
// It's possible for this to happen on the main thread if the dispatch
// to the stream service fails after we've already opened the file so
// we can't assert the thread we're running on.
MOZ_ASSERT(mFD);
PR_Close(mFD);
mFD = nullptr;
}
};
namespace mozilla {
namespace dom {
@ -93,6 +204,7 @@ TabParent::TabParent(const TabContext& aContext)
, mUpdatedDimensions(false)
, mMarkedDestroying(false)
, mIsDestroyed(false)
, mAppPackageFileDescriptorSent(false)
{
}
@ -230,23 +342,66 @@ TabParent::AnswerCreateWindow(PBrowserParent** retval)
void
TabParent::LoadURL(nsIURI* aURI)
{
MOZ_ASSERT(aURI);
if (mIsDestroyed) {
return;
}
if (!mShown) {
nsAutoCString spec;
if (aURI) {
aURI->GetSpec(spec);
}
NS_WARNING(nsPrintfCString("TabParent::LoadURL(%s) called before "
"Show(). Ignoring LoadURL.\n", spec.get()).get());
return;
return;
}
nsCString spec;
aURI->GetSpec(spec);
if (!mShown) {
NS_WARNING(nsPrintfCString("TabParent::LoadURL(%s) called before "
"Show(). Ignoring LoadURL.\n",
spec.get()).get());
return;
}
unused << SendLoadURL(spec);
// If this app is a packaged app then we can speed startup by sending over
// the file descriptor for the "application.zip" file that it will
// invariably request. Only do this once.
if (!mAppPackageFileDescriptorSent) {
mAppPackageFileDescriptorSent = true;
nsCOMPtr<mozIApplication> app = GetOwnOrContainingApp();
if (app) {
nsString manifestURL;
nsresult rv = app->GetManifestURL(manifestURL);
NS_ENSURE_SUCCESS_VOID(rv);
if (StringBeginsWith(manifestURL, NS_LITERAL_STRING("app:"))) {
nsString basePath;
rv = app->GetBasePath(basePath);
NS_ENSURE_SUCCESS_VOID(rv);
nsString appId;
rv = app->GetId(appId);
NS_ENSURE_SUCCESS_VOID(rv);
nsCOMPtr<nsIFile> packageFile;
rv = NS_NewLocalFile(basePath, false,
getter_AddRefs(packageFile));
NS_ENSURE_SUCCESS_VOID(rv);
rv = packageFile->Append(appId);
NS_ENSURE_SUCCESS_VOID(rv);
rv = packageFile->Append(NS_LITERAL_STRING("application.zip"));
NS_ENSURE_SUCCESS_VOID(rv);
nsString path;
rv = packageFile->GetPath(path);
NS_ENSURE_SUCCESS_VOID(rv);
nsRefPtr<OpenFileAndSendFDRunnable> openFileRunnable =
new OpenFileAndSendFDRunnable(path, this);
openFileRunnable->Dispatch();
}
}
}
}
void

View File

@ -304,6 +304,8 @@ private:
// When true, the TabParent is invalid and we should not send IPC messages
// anymore.
bool mIsDestroyed;
// Whether we have already sent a FileDescriptor for the app package.
bool mAppPackageFileDescriptorSent;
};
} // namespace dom

View File

@ -5,5 +5,7 @@
toolkit.jar:
content/global/test-ipc.xul (test.xul)
content/global/remote-test-ipc.js (remote-test.js)
* content/global/BrowserElementChild.js (../browser-element/BrowserElementChild.js)
content/global/BrowserElementChild.js (../browser-element/BrowserElementChild.js)
* content/global/BrowserElementChildPreload.js (../browser-element/BrowserElementChildPreload.js)
* content/global/BrowserElementPanning.js (../browser-element/BrowserElementPanning.js)
content/global/preload.js (preload.js)

View File

@ -0,0 +1,38 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_ipc_nsICachedFileDescriptorListener_h
#define mozilla_dom_ipc_nsICachedFileDescriptorListener_h
#include "nsISupports.h"
#ifndef NS_NO_VTABLE
#define NS_NO_VTABLE
#endif
#define NS_ICACHEDFILEDESCRIPTORLISTENER_IID \
{0x2cedaee0, 0x6ef2, 0x4f60, {0x9a, 0x6c, 0xdf, 0x4e, 0x4d, 0x65, 0x6a, 0xf7}}
class nsAString;
namespace mozilla {
namespace ipc {
class FileDescriptor;
}
}
class NS_NO_VTABLE nsICachedFileDescriptorListener : public nsISupports
{
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ICACHEDFILEDESCRIPTORLISTENER_IID)
virtual void
OnCachedFileDescriptor(const nsAString& aPath,
const mozilla::ipc::FileDescriptor& aFD) = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsICachedFileDescriptorListener,
NS_ICACHEDFILEDESCRIPTORLISTENER_IID)
#endif // mozilla_dom_ipc_nsICachedFileDescriptorListener_h

View File

@ -7,9 +7,11 @@
// This script is run when the preallocated process starts. It is injected as
// a frame script.
"use strict";
const BrowserElementIsPreloaded = true;
(function (global) {
"use strict";
(function () {
let Cu = Components.utils;
let Cc = Components.classes;
let Ci = Components.interfaces;
@ -73,10 +75,23 @@
Cc["@mozilla.org/thread-manager;1"].getService(Ci["nsIThreadManager"]);
Cc["@mozilla.org/toolkit/app-startup;1"].getService(Ci["nsIAppStartup"]);
Cc["@mozilla.org/uriloader;1"].getService(Ci["nsIURILoader"]);
Cc["@mozilla.org/contentsecuritypolicy;1"].createInstance(Ci["nsIContentSecurityPolicy"]);
/* Applications Specific Helper */
Cc["@mozilla.org/settingsManager;1"].getService(Ci["nsIDOMSettingsManager"]);
// This is a produc-specific file that's sometimes unavailable.
try {
Services.scriptloader.loadSubScript("chrome://browser/content/forms.js", global);
} catch (e) {
}
Services.scriptloader.loadSubScript("chrome://global/content/BrowserElementPanning.js", global);
Services.scriptloader.loadSubScript("chrome://global/content/BrowserElementChildPreload.js", global);
Services.io.getProtocolHandler("app");
Services.io.getProtocolHandler("default");
docShell.isActive = false;
docShell.createAboutBlankContentViewer(null);
})();
})(this);

View File

@ -360,10 +360,13 @@ public:
NS_ASSERTION(NS_IsMainThread(), "Only create MediaManager on main thread");
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
obs->AddObserver(sSingleton, "xpcom-shutdown", false);
obs->AddObserver(sSingleton, "getUserMedia:response:allow", false);
obs->AddObserver(sSingleton, "getUserMedia:response:deny", false);
obs->AddObserver(sSingleton, "getUserMedia:revoke", false);
if (obs) {
obs->AddObserver(sSingleton, "xpcom-shutdown", false);
obs->AddObserver(sSingleton, "getUserMedia:response:allow", false);
obs->AddObserver(sSingleton, "getUserMedia:response:deny", false);
obs->AddObserver(sSingleton, "getUserMedia:revoke", false);
}
// else MediaManager won't work properly and will leak (see bug 837874)
}
return sSingleton;
}

View File

@ -4,7 +4,7 @@
#include "nsIDOMEvent.idl"
[scriptable, builtinclass, uuid(9342c4eb-b6b3-414c-892f-c3630ce35c40)]
[scriptable, builtinclass, uuid(905348f1-3d06-443c-8762-567e7e4b6696)]
interface nsIDOMCFStateChangeEvent : nsIDOMEvent
{
/**
@ -51,4 +51,24 @@ interface nsIDOMCFStateChangeEvent : nsIDOMEvent
* nsIDOMMozMobileConnectionInfo.ICC_SERVICE_CLASS_* values.
*/
readonly attribute unsigned short serviceClass;
[noscript] void initCFStateChangeEvent(in DOMString aType,
in boolean aCanBubble,
in boolean aCancelable,
in boolean aSuccess,
in unsigned short aAction,
in unsigned short aReason,
in DOMString aNumber,
in unsigned short aTimeSeconds,
in unsigned short aServiceClass);
};
dictionary CFStateChangeEventInit : EventInit
{
boolean success;
unsigned short action;
unsigned short reason;
DOMString number;
unsigned short timeSeconds;
unsigned short serviceClass;
};

View File

@ -4,8 +4,18 @@
#include "nsIDOMEvent.idl"
[scriptable, builtinclass, uuid(494cf68f-0ca8-4cf9-924b-84cf379c9631)]
[scriptable, builtinclass, uuid(8b4ed443-a6b0-4445-aab0-9aa9fd5f6c1e)]
interface nsIDOMDataErrorEvent : nsIDOMEvent
{
readonly attribute DOMString message;
[noscript] void initDataErrorEvent(in DOMString aType,
in boolean aCanBubble,
in boolean aCancelable,
in DOMString aMessage);
};
dictionary DataErrorEventInit : EventInit
{
DOMString message;
};

View File

@ -4,9 +4,21 @@
#include "nsIDOMEvent.idl"
[scriptable, builtinclass, uuid(56e18850-96f1-4898-a0de-47e0c994c4ab)]
[scriptable, builtinclass, uuid(d26880c8-0468-4abb-94a6-9143defb5545)]
interface nsIDOMUSSDReceivedEvent : nsIDOMEvent
{
readonly attribute DOMString message;
[infallible] readonly attribute boolean sessionEnded;
[noscript] void initUSSDReceivedEvent(in DOMString aType,
in boolean aCanBubble,
in boolean aCancelable,
in DOMString aMessage,
in boolean aSessionEnded);
};
dictionary USSDReceivedEventInit : EventInit
{
DOMString message;
boolean sessionEnded;
};

View File

@ -1,90 +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 "CFStateChangeEvent.h"
#include "nsIDOMClassInfo.h"
#include "nsDOMClassInfoID.h"
#include "nsContentUtils.h"
DOMCI_DATA(CFStateChangeEvent, mozilla::dom::network::CFStateChangeEvent)
namespace mozilla {
namespace dom {
namespace network {
already_AddRefed<CFStateChangeEvent>
CFStateChangeEvent::Create(bool aSuccess,
uint16_t aAction,
uint16_t aReason,
nsAString& aNumber,
uint16_t aTimeSeconds,
uint16_t aServiceClass)
{
NS_ASSERTION(!aNumber.IsEmpty(), "Empty number!");
nsRefPtr<CFStateChangeEvent> event = new CFStateChangeEvent();
event->mSuccess = aSuccess;
event->mAction = aAction;
event->mReason = aReason;
event->mNumber = aNumber;
event->mTimeSeconds = aTimeSeconds;
event->mServiceClass = aServiceClass;
return event.forget();
}
NS_IMPL_ADDREF_INHERITED(CFStateChangeEvent, nsDOMEvent)
NS_IMPL_RELEASE_INHERITED(CFStateChangeEvent, nsDOMEvent)
NS_INTERFACE_MAP_BEGIN(CFStateChangeEvent)
NS_INTERFACE_MAP_ENTRY(nsIDOMCFStateChangeEvent)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CFStateChangeEvent)
NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent)
NS_IMETHODIMP
CFStateChangeEvent::GetSuccess(bool* aSuccess)
{
*aSuccess = mSuccess;
return NS_OK;
}
NS_IMETHODIMP
CFStateChangeEvent::GetAction(uint16_t* aAction)
{
*aAction = mAction;
return NS_OK;
}
NS_IMETHODIMP
CFStateChangeEvent::GetReason(uint16_t* aReason)
{
*aReason = mReason;
return NS_OK;
}
NS_IMETHODIMP
CFStateChangeEvent::GetNumber(nsAString& aNumber)
{
aNumber.Assign(mNumber);
return NS_OK;
}
NS_IMETHODIMP
CFStateChangeEvent::GetTimeSeconds(uint16_t* aTimeSeconds)
{
*aTimeSeconds = mTimeSeconds;
return NS_OK;
}
NS_IMETHODIMP
CFStateChangeEvent::GetServiceClass(uint16_t* aServiceClass)
{
*aServiceClass = mServiceClass;
return NS_OK;
}
}
}
}

View File

@ -1,70 +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/. */
#ifndef mozilla_dom_network_cfstatechangeevent_h
#define mozilla_dom_network_cfstatechangeevent_h
#include "nsIDOMCFStateChangeEvent.h"
#include "nsDOMEvent.h"
namespace mozilla {
namespace dom {
namespace network {
class CFStateChangeEvent : public nsDOMEvent,
public nsIDOMCFStateChangeEvent
{
bool mSuccess;
uint16_t mAction;
uint16_t mReason;
nsString mNumber;
uint16_t mTimeSeconds;
uint16_t mServiceClass;
public:
NS_DECL_ISUPPORTS_INHERITED
NS_FORWARD_TO_NSDOMEVENT
NS_DECL_NSIDOMCFSTATECHANGEEVENT
static already_AddRefed<CFStateChangeEvent>
Create(bool aSuccess,
uint16_t aAction,
uint16_t aReason,
nsAString& aNumber,
uint16_t aTimeSeconds,
uint16_t aServiceClass);
nsresult
Dispatch(nsIDOMEventTarget* aTarget, const nsAString& aEventType)
{
NS_ASSERTION(aTarget, "Null pointer!");
NS_ASSERTION(!aEventType.IsEmpty(), "Empty event type!");
nsresult rv = InitEvent(aEventType, false, false);
NS_ENSURE_SUCCESS(rv, rv);
SetTrusted(true);
nsDOMEvent* thisEvent = this;
bool dummy;
rv = aTarget->DispatchEvent(thisEvent, &dummy);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
private:
CFStateChangeEvent()
: nsDOMEvent(nullptr, nullptr)
{ }
~CFStateChangeEvent()
{ }
};
}
}
}
#endif // mozilla_dom_network_cfstatechangeevent_h

View File

@ -1,43 +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 "DataErrorEvent.h"
#include "nsIDOMClassInfo.h"
DOMCI_DATA(DataErrorEvent, mozilla::dom::network::DataErrorEvent)
namespace mozilla {
namespace dom {
namespace network {
already_AddRefed<DataErrorEvent>
DataErrorEvent::Create(nsAString& aMessage)
{
NS_ASSERTION(!aMessage.IsEmpty(), "Empty message!");
nsRefPtr<DataErrorEvent> event = new DataErrorEvent();
event->mMessage = aMessage;
return event.forget();
}
NS_IMPL_ADDREF_INHERITED(DataErrorEvent, nsDOMEvent)
NS_IMPL_RELEASE_INHERITED(DataErrorEvent, nsDOMEvent)
NS_INTERFACE_MAP_BEGIN(DataErrorEvent)
NS_INTERFACE_MAP_ENTRY(nsIDOMDataErrorEvent)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(DataErrorEvent)
NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent)
NS_IMETHODIMP
DataErrorEvent::GetMessage(nsAString& aMessage)
{
aMessage.Assign(mMessage);
return NS_OK;
}
}
}
}

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