mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-21 01:05:45 +00:00
Merge mozilla-central into services-central
This commit is contained in:
commit
6ecc3ed030
@ -7,11 +7,12 @@
|
||||
|
||||
#include "nsARIAMap.h"
|
||||
|
||||
#include "nsAccUtils.h"
|
||||
#include "nsCoreUtils.h"
|
||||
#include "Role.h"
|
||||
#include "States.h"
|
||||
|
||||
#include "nsIContent.h"
|
||||
#include "nsAttrName.h"
|
||||
#include "nsWhitespaceTokenizer.h"
|
||||
|
||||
using namespace mozilla;
|
||||
@ -684,3 +685,39 @@ aria::UniversalStatesFor(mozilla::dom::Element* aElement)
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// AttrIterator class
|
||||
|
||||
bool
|
||||
AttrIterator::Next(nsAString& aAttrName, nsAString& aAttrValue)
|
||||
{
|
||||
while (mAttrIdx < mAttrCount) {
|
||||
const nsAttrName* attr = mContent->GetAttrNameAt(mAttrIdx);
|
||||
mAttrIdx++;
|
||||
if (attr->NamespaceEquals(kNameSpaceID_None)) {
|
||||
nsIAtom* attrAtom = attr->Atom();
|
||||
nsDependentAtomString attrStr(attrAtom);
|
||||
if (!StringBeginsWith(attrStr, NS_LITERAL_STRING("aria-")))
|
||||
continue; // Not ARIA
|
||||
|
||||
PRUint8 attrFlags = nsAccUtils::GetAttributeCharacteristics(attrAtom);
|
||||
if (attrFlags & ATTR_BYPASSOBJ)
|
||||
continue; // No need to handle exposing as obj attribute here
|
||||
|
||||
if ((attrFlags & ATTR_VALTOKEN) &&
|
||||
!nsAccUtils::HasDefinedARIAToken(mContent, attrAtom))
|
||||
continue; // only expose token based attributes if they are defined
|
||||
|
||||
nsAutoString value;
|
||||
if (mContent->GetAttr(kNameSpaceID_None, attrAtom, value)) {
|
||||
aAttrName.Assign(Substring(attrStr, 5));
|
||||
aAttrValue.Assign(value);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -12,8 +12,8 @@
|
||||
#include "mozilla/a11y/Role.h"
|
||||
|
||||
#include "nsIAtom.h"
|
||||
#include "nsIContent.h"
|
||||
|
||||
class nsIContent;
|
||||
class nsINode;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -226,6 +226,31 @@ nsRoleMapEntry* GetRoleMap(nsINode* aNode);
|
||||
*/
|
||||
PRUint64 UniversalStatesFor(mozilla::dom::Element* aElement);
|
||||
|
||||
/**
|
||||
* Represents a simple enumerator for iterating through ARIA attributes
|
||||
* exposed as object attributes on a given accessible.
|
||||
*/
|
||||
class AttrIterator
|
||||
{
|
||||
public:
|
||||
AttrIterator(nsIContent* aContent) :
|
||||
mContent(aContent), mAttrIdx(0)
|
||||
{
|
||||
mAttrCount = mContent->GetAttrCount();
|
||||
}
|
||||
|
||||
bool Next(nsAString& aAttrName, nsAString& aAttrValue);
|
||||
|
||||
private:
|
||||
AttrIterator() MOZ_DELETE;
|
||||
AttrIterator(const AttrIterator&) MOZ_DELETE;
|
||||
AttrIterator& operator= (const AttrIterator&) MOZ_DELETE;
|
||||
|
||||
nsIContent* mContent;
|
||||
PRUint32 mAttrIdx;
|
||||
PRUint32 mAttrCount;
|
||||
};
|
||||
|
||||
} // namespace aria
|
||||
} // namespace a11y
|
||||
} // namespace mozilla
|
||||
|
@ -1225,25 +1225,11 @@ Accessible::GetAttributes(nsIPersistentProperties **aAttributes)
|
||||
groupPos.setSize, groupPos.posInSet);
|
||||
|
||||
// Expose object attributes from ARIA attributes.
|
||||
PRUint32 numAttrs = mContent->GetAttrCount();
|
||||
for (PRUint32 count = 0; count < numAttrs; count ++) {
|
||||
const nsAttrName *attr = mContent->GetAttrNameAt(count);
|
||||
if (attr && attr->NamespaceEquals(kNameSpaceID_None)) {
|
||||
nsIAtom *attrAtom = attr->Atom();
|
||||
nsDependentAtomString attrStr(attrAtom);
|
||||
if (!StringBeginsWith(attrStr, NS_LITERAL_STRING("aria-")))
|
||||
continue; // Not ARIA
|
||||
PRUint8 attrFlags = nsAccUtils::GetAttributeCharacteristics(attrAtom);
|
||||
if (attrFlags & ATTR_BYPASSOBJ)
|
||||
continue; // No need to handle exposing as obj attribute here
|
||||
if ((attrFlags & ATTR_VALTOKEN) &&
|
||||
!nsAccUtils::HasDefinedARIAToken(mContent, attrAtom))
|
||||
continue; // only expose token based attributes if they are defined
|
||||
nsAutoString value;
|
||||
if (mContent->GetAttr(kNameSpaceID_None, attrAtom, value)) {
|
||||
attributes->SetStringProperty(NS_ConvertUTF16toUTF8(Substring(attrStr, 5)), value, oldValueUnused);
|
||||
}
|
||||
}
|
||||
aria::AttrIterator attribIter(mContent);
|
||||
nsAutoString name, value;
|
||||
while(attribIter.Next(name, value)) {
|
||||
attributes->SetStringProperty(NS_ConvertUTF16toUTF8(name), value,
|
||||
oldValueUnused);
|
||||
}
|
||||
|
||||
// If there is no aria-live attribute then expose default value of 'live'
|
||||
@ -3258,3 +3244,4 @@ KeyBinding::ToAtkFormat(nsAString& aValue) const
|
||||
|
||||
aValue.Append(mKey);
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#include "AccessibleWrap.h"
|
||||
#include "nsIPersistentProperties2.h"
|
||||
#include "nsARIAMap.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::a11y;
|
||||
@ -199,6 +200,30 @@ uiaRawElmProvider::GetPropertyValue(PROPERTYID aPropertyId,
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
//ARIA Properties
|
||||
case UIA_AriaPropertiesPropertyId: {
|
||||
nsAutoString ariaProperties;
|
||||
|
||||
aria::AttrIterator attribIter(mAcc->GetContent());
|
||||
nsAutoString attribName, attribValue;
|
||||
while (attribIter.Next(attribName, attribValue)) {
|
||||
ariaProperties.Append(attribName);
|
||||
ariaProperties.Append('=');
|
||||
ariaProperties.Append(attribValue);
|
||||
ariaProperties.Append(';');
|
||||
}
|
||||
|
||||
if (!ariaProperties.IsEmpty()) {
|
||||
//remove last delimiter:
|
||||
ariaProperties.Truncate(ariaProperties.Length()-1);
|
||||
aPropertyValue->vt = VT_BSTR;
|
||||
aPropertyValue->bstrVal = ::SysAllocString(ariaProperties.get());
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
|
@ -472,6 +472,9 @@ pref("dom.disable_window_print", true);
|
||||
// Disable window.showModalDialog
|
||||
pref("dom.disable_window_showModalDialog", true);
|
||||
|
||||
// Enable new experimental html forms
|
||||
pref("dom.experimental_forms", true);
|
||||
|
||||
// Turns on gralloc-based direct texturing for Gonk
|
||||
pref("gfx.gralloc.enabled", false);
|
||||
|
||||
|
@ -180,15 +180,15 @@ FormAssistant.init();
|
||||
function getJSON(element) {
|
||||
let type = element.type || "";
|
||||
|
||||
// FIXME/bug 344616 is input type="number"
|
||||
// Until then, let's return 'number' even if the platform returns 'text'
|
||||
// Until the input type=date/datetime/time have been implemented
|
||||
// let's return their real type even if the platform returns 'text'
|
||||
// Related to Bug 769352 - Implement <input type=date>
|
||||
// Related to Bug 777279 - Implement <input type=time>
|
||||
let attributeType = element.getAttribute("type") || "";
|
||||
|
||||
if (attributeType) {
|
||||
var typeLowerCase = attributeType.toLowerCase();
|
||||
switch (typeLowerCase) {
|
||||
case "number":
|
||||
case "date":
|
||||
case "time":
|
||||
case "datetime":
|
||||
|
@ -48,29 +48,6 @@ function getContentWindow() {
|
||||
return shell.contentBrowser.contentWindow;
|
||||
}
|
||||
|
||||
// FIXME Bug 707625
|
||||
// Please don't add more permissions here.
|
||||
// XXX never grant 'content-camera' to non-gaia apps
|
||||
function addPermissions(urls) {
|
||||
let permissions = [
|
||||
'indexedDB-unlimited', 'webapps-manage', 'offline-app', 'pin-app',
|
||||
'content-camera', 'wifi-manage', 'desktop-notification',
|
||||
'geolocation', 'device-storage', 'alarms'
|
||||
];
|
||||
|
||||
urls.forEach(function(url) {
|
||||
url = url.trim();
|
||||
if (url) {
|
||||
let uri = Services.io.newURI(url, null, null);
|
||||
let allow = Ci.nsIPermissionManager.ALLOW_ACTION;
|
||||
|
||||
permissions.forEach(function(permission) {
|
||||
Services.perms.add(uri, permission, allow);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var shell = {
|
||||
|
||||
get CrashSubmit() {
|
||||
@ -160,13 +137,6 @@ var shell = {
|
||||
dump('Error setting master volume: ' + e + '\n');
|
||||
}
|
||||
|
||||
let domains = "";
|
||||
try {
|
||||
domains = Services.prefs.getCharPref('b2g.privileged.domains');
|
||||
} catch(e) {}
|
||||
|
||||
addPermissions(domains.split(","));
|
||||
|
||||
CustomEventManager.init();
|
||||
WebappsHelper.init();
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0"?>
|
||||
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1343854380000">
|
||||
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1344613852000">
|
||||
<emItems>
|
||||
<emItem blockID="i58" id="webmaster@buzzzzvideos.info">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
@ -120,6 +120,10 @@
|
||||
</emItem>
|
||||
<emItem blockID="i13" id="{E8E88AB0-7182-11DF-904E-6045E0D72085}">
|
||||
</emItem>
|
||||
<emItem blockID="i117" id="{ce7e73df-6a44-4028-8079-5927a588c948}">
|
||||
<versionRange minVersion="0" maxVersion="1.0.8" severity="1">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i24" id="{6E19037A-12E3-4295-8915-ED48BC341614}">
|
||||
<versionRange minVersion="0.1" maxVersion="1.3.328.4" severity="1">
|
||||
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
|
||||
|
@ -510,34 +510,23 @@ pref("browser.gesture.twist.right", "");
|
||||
pref("browser.gesture.twist.left", "");
|
||||
pref("browser.gesture.tap", "cmd_fullZoomReset");
|
||||
|
||||
// 0=lines, 1=pages, 2=history , 3=text size
|
||||
// 0: Nothing happens
|
||||
// 1: Scrolling contents
|
||||
// 2: Go back or go forward, in your history
|
||||
// 3: Zoom in or out.
|
||||
#ifdef XP_MACOSX
|
||||
// On OS X, if the wheel has one axis only, shift+wheel comes through as a
|
||||
// horizontal scroll event. Thus, we can't assign anything other than normal
|
||||
// scrolling to shift+wheel.
|
||||
pref("mousewheel.withshiftkey.action",0);
|
||||
pref("mousewheel.withshiftkey.sysnumlines",true);
|
||||
pref("mousewheel.withshiftkey.numlines",1);
|
||||
pref("mousewheel.withaltkey.action",2);
|
||||
pref("mousewheel.withaltkey.sysnumlines",false);
|
||||
pref("mousewheel.withaltkey.numlines",1);
|
||||
pref("mousewheel.withmetakey.action",0);
|
||||
pref("mousewheel.withmetakey.sysnumlines",false);
|
||||
pref("mousewheel.withmetakey.numlines",1);
|
||||
pref("mousewheel.with_alt.action", 2);
|
||||
pref("mousewheel.with_shift.action", 1);
|
||||
#else
|
||||
pref("mousewheel.withshiftkey.action",2);
|
||||
pref("mousewheel.withshiftkey.sysnumlines",false);
|
||||
pref("mousewheel.withshiftkey.numlines",1);
|
||||
pref("mousewheel.withaltkey.action",0);
|
||||
pref("mousewheel.withaltkey.sysnumlines",false);
|
||||
pref("mousewheel.withaltkey.numlines",1);
|
||||
pref("mousewheel.withmetakey.action",0);
|
||||
pref("mousewheel.withmetakey.sysnumlines",true);
|
||||
pref("mousewheel.withmetakey.numlines",1);
|
||||
pref("mousewheel.with_alt.action", 1);
|
||||
pref("mousewheel.with_shift.action", 2);
|
||||
#endif
|
||||
pref("mousewheel.withcontrolkey.action",3);
|
||||
pref("mousewheel.withcontrolkey.sysnumlines",false);
|
||||
pref("mousewheel.withcontrolkey.numlines",1);
|
||||
pref("mousewheel.with_control.action",3);
|
||||
pref("mousewheel.with_meta.action", 1); // command key on Mac
|
||||
pref("mousewheel.with_win.action", 1);
|
||||
|
||||
// pref to control the alert notification
|
||||
pref("alerts.slideIncrement", 1);
|
||||
|
@ -156,7 +156,7 @@ _BROWSER_FILES = \
|
||||
browser_bug749738.js \
|
||||
browser_bug763468.js \
|
||||
browser_bug767836.js \
|
||||
browser_shareButton.js \
|
||||
browser_social_shareButton.js \
|
||||
browser_canonizeURL.js \
|
||||
browser_customize.js \
|
||||
browser_findbarClose.js \
|
||||
@ -232,6 +232,7 @@ _BROWSER_FILES = \
|
||||
plugin_clickToPlayAllow.html \
|
||||
plugin_clickToPlayDeny.html \
|
||||
plugin_bug749455.html \
|
||||
plugin_hidden_to_visible.html \
|
||||
alltabslistener.html \
|
||||
zoom_test.html \
|
||||
dummy_page.html \
|
||||
|
@ -72,11 +72,11 @@ function runOverflowTests(aEvent) {
|
||||
"(" + left(scrollbox) + " <= " + firstScrollableLeft + ")");
|
||||
|
||||
for (var i = 2; i; i--)
|
||||
EventUtils.synthesizeMouseScroll(scrollbox, 1, 1, {axis: "horizontal", delta: -1});
|
||||
EventUtils.synthesizeWheel(scrollbox, 1, 1, { deltaX: -1.0, deltaMode: WheelEvent.DOM_DELTA_LINE });
|
||||
is(left(firstScrollable()), firstScrollableLeft, "Remained at the start with the mouse wheel");
|
||||
|
||||
element = nextRightElement();
|
||||
EventUtils.synthesizeMouseScroll(scrollbox, 1, 1, {axis: "horizontal", delta: 1});
|
||||
EventUtils.synthesizeWheel(scrollbox, 1, 1, { deltaX: 1.0, deltaMode: WheelEvent.DOM_DELTA_LINE});
|
||||
isRight(element, "Scrolled one tab to the right with the mouse wheel");
|
||||
|
||||
while (tabs.length > 1)
|
||||
|
@ -689,5 +689,56 @@ function test19f() {
|
||||
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
ok(objLoadingContent.activated, "Test 19f, Plugin should be activated");
|
||||
|
||||
prepareTest(test20a, gTestRoot + "plugin_hidden_to_visible.html");
|
||||
}
|
||||
|
||||
// Tests that a plugin in a div that goes from style="display: none" to
|
||||
// "display: block" can be clicked to activate.
|
||||
function test20a() {
|
||||
var clickToPlayNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
|
||||
ok(clickToPlayNotification, "Test 20a, Should have a click-to-play notification");
|
||||
var doc = gTestBrowser.contentDocument;
|
||||
var plugin = doc.getElementById("plugin");
|
||||
var mainBox = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox");
|
||||
ok(mainBox, "Test 20a, plugin overlay should not be null");
|
||||
var pluginRect = mainBox.getBoundingClientRect();
|
||||
ok(pluginRect.width == 0, "Test 20a, plugin should have an overlay with 0px width");
|
||||
ok(pluginRect.height == 0, "Test 20a, plugin should have an overlay with 0px height");
|
||||
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
ok(!objLoadingContent.activated, "Test 20a, plugin should not be activated");
|
||||
var div = doc.getElementById("container");
|
||||
ok(div.style.display == "none", "Test 20a, container div should be display: none");
|
||||
|
||||
div.style.display = "block";
|
||||
var condition = function() {
|
||||
var pluginRect = mainBox.getBoundingClientRect();
|
||||
return (pluginRect.width == 200);
|
||||
}
|
||||
waitForCondition(condition, test20b, "Test 20a, Waited too long for plugin to become visible");
|
||||
}
|
||||
|
||||
function test20b() {
|
||||
var doc = gTestBrowser.contentDocument;
|
||||
var plugin = doc.getElementById("plugin");
|
||||
var pluginRect = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox").getBoundingClientRect();
|
||||
ok(pluginRect.width == 200, "Test 20b, plugin should have an overlay with 200px width");
|
||||
ok(pluginRect.height == 200, "Test 20b, plugin should have an overlay with 200px height");
|
||||
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
ok(!objLoadingContent.activated, "Test 20b, plugin should not be activated");
|
||||
|
||||
EventUtils.synthesizeMouseAtCenter(plugin, {}, gTestBrowser.contentWindow);
|
||||
var condition = function() objLoadingContent.activated;
|
||||
waitForCondition(condition, test20c, "Test 20b, Waited too long for plugin to activate");
|
||||
}
|
||||
|
||||
function test20c() {
|
||||
var doc = gTestBrowser.contentDocument;
|
||||
var plugin = doc.getElementById("plugin");
|
||||
var pluginRect = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox").getBoundingClientRect();
|
||||
ok(pluginRect.width == 0, "Test 20c, plugin should have click-to-play overlay with zero width");
|
||||
ok(pluginRect.height == 0, "Test 20c, plugin should have click-to-play overlay with zero height");
|
||||
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
ok(objLoadingContent.activated, "Test 20c, plugin should be activated");
|
||||
|
||||
finishTest();
|
||||
}
|
||||
|
@ -2,14 +2,7 @@
|
||||
* 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/. */
|
||||
|
||||
let SocialService = Cu.import("resource://gre/modules/SocialService.jsm", {}).SocialService;
|
||||
|
||||
function test() {
|
||||
// XXX Bug 775779
|
||||
if (Cc["@mozilla.org/xpcom/debug;1"].getService(Ci.nsIDebug2).isDebugBuild) {
|
||||
ok(true, "can't run social sidebar test in debug builds because they falsely report leaks");
|
||||
return;
|
||||
}
|
||||
waitForExplicitFinish();
|
||||
|
||||
let manifest = { // normal provider
|
||||
@ -19,10 +12,8 @@ function test() {
|
||||
workerURL: "http://example.com/browser/browser/base/content/test/social_worker.js",
|
||||
iconURL: "chrome://branding/content/icon48.png"
|
||||
};
|
||||
runSocialTestWithProvider(manifest, function () {
|
||||
runSocialTests(tests, undefined, undefined, function () {
|
||||
SocialService.removeProvider(Social.provider.origin, finish);
|
||||
});
|
||||
runSocialTestWithProvider(manifest, function (finishcb) {
|
||||
runSocialTests(tests, undefined, undefined, finishcb);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,8 @@ let prefName = "social.enabled",
|
||||
shareButton,
|
||||
sharePopup,
|
||||
okButton,
|
||||
undoButton;
|
||||
undoButton,
|
||||
gFinishCB;
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
@ -18,9 +19,6 @@ function test() {
|
||||
executeSoon(tabLoaded);
|
||||
}, true);
|
||||
|
||||
// Enable the service to start
|
||||
Services.prefs.setBoolPref(prefName, true);
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
Services.prefs.clearUserPref(prefName);
|
||||
gBrowser.removeTab(tab);
|
||||
@ -30,19 +28,20 @@ function test() {
|
||||
function tabLoaded() {
|
||||
ok(Social, "Social module loaded");
|
||||
|
||||
// If the UI is already active, run the test immediately, otherwise wait
|
||||
// for initialization.
|
||||
if (Social.provider) {
|
||||
executeSoon(testInitial);
|
||||
} else {
|
||||
Services.obs.addObserver(function obs() {
|
||||
Services.obs.removeObserver(obs, "test-social-ui-ready");
|
||||
executeSoon(testInitial);
|
||||
}, "test-social-ui-ready", false);
|
||||
}
|
||||
let manifest = { // normal provider
|
||||
name: "provider 1",
|
||||
origin: "https://example.com",
|
||||
sidebarURL: "https://example.com/browser/browser/base/content/test/social_sidebar.html",
|
||||
workerURL: "https://example.com/browser/browser/base/content/test/social_worker.js",
|
||||
iconURL: "chrome://branding/content/icon48.png"
|
||||
};
|
||||
runSocialTestWithProvider(manifest, function (finishcb) {
|
||||
gFinishCB = finishcb;
|
||||
testInitial();
|
||||
});
|
||||
}
|
||||
|
||||
function testInitial() {
|
||||
function testInitial(finishcb) {
|
||||
ok(Social.provider, "Social provider is active");
|
||||
ok(Social.provider.enabled, "Social provider is enabled");
|
||||
ok(Social.provider.port, "Social provider has a port to its FrameWorker");
|
||||
@ -116,19 +115,33 @@ function checkShortcutWorked(keyTarget) {
|
||||
|
||||
function checkOKButton() {
|
||||
is(document.activeElement, okButton, "ok button should be focused by default");
|
||||
checkNextInTabOrder(undoButton, function () {
|
||||
checkNextInTabOrder(okButton, testCloseBySpace);
|
||||
});
|
||||
}
|
||||
|
||||
function checkNextInTabOrder(element, next) {
|
||||
// This particular test doesn't really apply on Mac, since buttons aren't
|
||||
// focusable by default.
|
||||
// This rest of particular test doesn't really apply on Mac, since buttons
|
||||
// aren't focusable by default.
|
||||
if (navigator.platform.indexOf("Mac") != -1) {
|
||||
executeSoon(next);
|
||||
executeSoon(testCloseBySpace);
|
||||
return;
|
||||
}
|
||||
|
||||
let displayName = document.getElementById("socialUserDisplayName");
|
||||
|
||||
// Linux has the buttons in the [unshare] [ok] order, so displayName will come first.
|
||||
if (navigator.platform.indexOf("Linux") != -1) {
|
||||
checkNextInTabOrder(displayName, function () {
|
||||
checkNextInTabOrder(undoButton, function () {
|
||||
checkNextInTabOrder(okButton, testCloseBySpace);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
checkNextInTabOrder(undoButton, function () {
|
||||
checkNextInTabOrder(displayName, function () {
|
||||
checkNextInTabOrder(okButton, testCloseBySpace);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function checkNextInTabOrder(element, next) {
|
||||
function listener() {
|
||||
element.removeEventListener("focus", listener);
|
||||
is(document.activeElement, element, element.id + " should be next in tab order");
|
||||
@ -155,5 +168,5 @@ function testCloseBySpace() {
|
||||
function testDisable() {
|
||||
Services.prefs.setBoolPref(prefName, false);
|
||||
is(shareButton.hidden, true, "Share button should be hidden when pref is disabled");
|
||||
finish();
|
||||
gFinishCB();
|
||||
}
|
@ -2,15 +2,7 @@
|
||||
* 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/. */
|
||||
|
||||
let SocialService = Cu.import("resource://gre/modules/SocialService.jsm", {}).SocialService;
|
||||
|
||||
function test() {
|
||||
// XXX Bug 775779
|
||||
if (Cc["@mozilla.org/xpcom/debug;1"].getService(Ci.nsIDebug2).isDebugBuild) {
|
||||
ok(true, "can't run social sidebar test in debug builds because they falsely report leaks");
|
||||
return;
|
||||
}
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
||||
let manifest = { // normal provider
|
||||
@ -23,7 +15,7 @@ function test() {
|
||||
runSocialTestWithProvider(manifest, doTest);
|
||||
}
|
||||
|
||||
function doTest() {
|
||||
function doTest(finishcb) {
|
||||
ok(SocialSidebar.canShow, "social sidebar should be able to be shown");
|
||||
ok(SocialSidebar.enabled, "social sidebar should be on by default");
|
||||
|
||||
@ -56,8 +48,8 @@ function doTest() {
|
||||
|
||||
checkShown(true);
|
||||
|
||||
// Remove the test provider
|
||||
SocialService.removeProvider(Social.provider.origin, finish);
|
||||
// Finish the test
|
||||
finishcb();
|
||||
});
|
||||
|
||||
// Toggle it back on
|
||||
|
@ -2,8 +2,6 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
let SocialService = Cu.import("resource://gre/modules/SocialService.jsm", {}).SocialService;
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
@ -13,10 +11,8 @@ function test() {
|
||||
workerURL: "https://example1.com/worker.js",
|
||||
iconURL: "chrome://branding/content/icon48.png"
|
||||
};
|
||||
runSocialTestWithProvider(manifest, function () {
|
||||
runSocialTests(tests, undefined, undefined, function () {
|
||||
SocialService.removeProvider(Social.provider.origin, finish);
|
||||
});
|
||||
runSocialTestWithProvider(manifest, function (finishcb) {
|
||||
runSocialTests(tests, undefined, undefined, finishcb);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -89,8 +89,13 @@ function waitForCondition(condition, nextTest, errorMsg) {
|
||||
}
|
||||
|
||||
function runSocialTestWithProvider(manifest, callback) {
|
||||
let SocialService = Cu.import("resource://gre/modules/SocialService.jsm", {}).SocialService;
|
||||
|
||||
info("runSocialTestWithProvider: " + manifest.toSource());
|
||||
|
||||
let oldProvider;
|
||||
function saveOldProviderAndStartTestWith(provider) {
|
||||
SocialService.addProvider(manifest, function(provider) {
|
||||
info("runSocialTestWithProvider: provider added");
|
||||
oldProvider = Social.provider;
|
||||
Social.provider = provider;
|
||||
|
||||
@ -102,20 +107,10 @@ function runSocialTestWithProvider(manifest, callback) {
|
||||
Services.prefs.clearUserPref("social.enabled");
|
||||
});
|
||||
|
||||
callback();
|
||||
}
|
||||
|
||||
SocialService.addProvider(manifest, function(provider) {
|
||||
// If the UI is already active, run the test immediately, otherwise wait
|
||||
// for initialization.
|
||||
if (Social.provider) {
|
||||
saveOldProviderAndStartTestWith(provider);
|
||||
} else {
|
||||
Services.obs.addObserver(function obs() {
|
||||
Services.obs.removeObserver(obs, "test-social-ui-ready");
|
||||
saveOldProviderAndStartTestWith(provider);
|
||||
}, "test-social-ui-ready", false);
|
||||
function finishSocialTest() {
|
||||
SocialService.removeProvider(provider.origin, finish);
|
||||
}
|
||||
callback(finishSocialTest);
|
||||
});
|
||||
}
|
||||
|
||||
|
11
browser/base/content/test/plugin_hidden_to_visible.html
Normal file
11
browser/base/content/test/plugin_hidden_to_visible.html
Normal file
@ -0,0 +1,11 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
<body>
|
||||
<div id="container" style="display: none">
|
||||
<object id="plugin" type="application/x-test" style="width: 200px; height: 200px;"></object>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -51,8 +51,8 @@ function performScrollingTest()
|
||||
InspectorUI.highlighter.removeListener("nodeselected", performScrollingTest);
|
||||
|
||||
executeSoon(function() {
|
||||
EventUtils.synthesizeMouseScroll(div, 10, 10,
|
||||
{axis:"vertical", delta:50, type:"MozMousePixelScroll"},
|
||||
EventUtils.synthesizeWheel(div, 10, 10,
|
||||
{ deltaY: 50.0, deltaMode: WheelEvent.DOM_DELTA_PIXEL },
|
||||
iframe.contentWindow);
|
||||
});
|
||||
|
||||
|
@ -40,9 +40,6 @@ SUBMAKEFILES += \
|
||||
# This makefile uses variable overrides from the libs-% target to
|
||||
# build non-default locales to non-default dist/ locations. Be aware!
|
||||
|
||||
# XXXCallek Unused?
|
||||
APP_VERSION := $(shell cat $(srcdir)/../config/version.txt)
|
||||
|
||||
PWD := $(CURDIR)
|
||||
|
||||
# These are defaulted to be compatible with the files the wget-en-US target
|
||||
|
@ -31,7 +31,6 @@ let Social = {
|
||||
if (providers.length)
|
||||
this.provider = providers[0];
|
||||
callback();
|
||||
Services.obs.notifyObservers(null, "test-social-ui-ready", "");
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
|
@ -356,6 +356,7 @@ class Automation(object):
|
||||
{'allowXULXBL':[(l.host, 'noxul' not in l.options) for l in locations]});
|
||||
|
||||
part = """\
|
||||
user_pref("social.skipLoadingProviders", true);
|
||||
user_pref("browser.console.showInPanel", true);
|
||||
user_pref("browser.dom.window.dump.enabled", true);
|
||||
user_pref("browser.firstrun.show.localepicker", false);
|
||||
|
@ -6,6 +6,11 @@ elif [ -d "$topsrcdir/../clang" ]; then
|
||||
# comm-central based build
|
||||
export CC=$topsrcdir/../clang/bin/clang
|
||||
export CXX=$topsrcdir/../clang/bin/clang++
|
||||
else
|
||||
# SeaMonkey does not have clang installed so need
|
||||
# to set CC and CXX here.
|
||||
export CC=/usr/bin/gcc-4.2
|
||||
export CXX=/usr/bin/g++-4.2
|
||||
fi
|
||||
|
||||
ac_add_options --enable-stdcxx-compat
|
||||
|
@ -35,16 +35,19 @@ class B2GRemoteAutomation(Automation):
|
||||
_devicemanager = None
|
||||
|
||||
def __init__(self, deviceManager, appName='', remoteLog=None,
|
||||
marionette=None):
|
||||
marionette=None, context_chrome=True):
|
||||
self._devicemanager = deviceManager
|
||||
self._appName = appName
|
||||
self._remoteProfile = None
|
||||
self._remoteLog = remoteLog
|
||||
self.marionette = marionette
|
||||
self.context_chrome = context_chrome
|
||||
self._is_emulator = False
|
||||
|
||||
# Default our product to b2g
|
||||
self._product = "b2g"
|
||||
# Default log finish to mochitest standard
|
||||
self.logFinish = 'INFO SimpleTest FINISHED'
|
||||
Automation.__init__(self)
|
||||
|
||||
def setEmulator(self, is_emulator):
|
||||
@ -121,7 +124,7 @@ class B2GRemoteAutomation(Automation):
|
||||
|
||||
def waitForFinish(self, proc, utilityPath, timeout, maxTime, startTime,
|
||||
debuggerInfo, symbolsPath):
|
||||
""" Wait for mochitest to finish (as evidenced by a signature string
|
||||
""" Wait for tests to finish (as evidenced by a signature string
|
||||
in logcat), or for a given amount of time to elapse with no
|
||||
output.
|
||||
"""
|
||||
@ -135,7 +138,7 @@ class B2GRemoteAutomation(Automation):
|
||||
if currentlog:
|
||||
done = time.time() + timeout
|
||||
print currentlog
|
||||
if 'INFO SimpleTest FINISHED' in currentlog:
|
||||
if hasattr(self, 'logFinish') and self.logFinish in currentlog:
|
||||
return 0
|
||||
else:
|
||||
if time.time() > done:
|
||||
@ -162,6 +165,8 @@ class B2GRemoteAutomation(Automation):
|
||||
return (serial, status)
|
||||
|
||||
def restartB2G(self):
|
||||
# TODO hangs in subprocess.Popen without this delay
|
||||
time.sleep(5)
|
||||
self._devicemanager.checkCmd(['shell', 'stop', 'b2g'])
|
||||
# Wait for a bit to make sure B2G has completely shut down.
|
||||
time.sleep(10)
|
||||
@ -194,7 +199,7 @@ class B2GRemoteAutomation(Automation):
|
||||
|
||||
def Process(self, cmd, stdout=None, stderr=None, env=None, cwd=None):
|
||||
# On a desktop or fennec run, the Process method invokes a gecko
|
||||
# process in which to run mochitests. For B2G, we simply
|
||||
# process in which to the tests. For B2G, we simply
|
||||
# reboot the device (which was configured with a test profile
|
||||
# already), wait for B2G to start up, and then navigate to the
|
||||
# test url using Marionette. There doesn't seem to be any way
|
||||
@ -239,11 +244,27 @@ class B2GRemoteAutomation(Automation):
|
||||
if 'b2g' not in session:
|
||||
raise Exception("bad session value %s returned by start_session" % session)
|
||||
|
||||
if self.context_chrome:
|
||||
self.marionette.set_context(self.marionette.CONTEXT_CHROME)
|
||||
|
||||
# start the tests
|
||||
if hasattr(self, 'testURL'):
|
||||
# Start the tests by navigating to the mochitest url, by setting it
|
||||
# as the 'src' attribute to the homescreen mozbrowser element
|
||||
# provided by B2G's shell.js.
|
||||
self.marionette.set_context("chrome")
|
||||
self.marionette.execute_script("document.getElementById('homescreen').src='%s';" % self.testURL)
|
||||
# run the script that starts the tests
|
||||
elif hasattr(self, 'testScript'):
|
||||
if os.path.isfile(self.testScript):
|
||||
script = open(self.testScript, 'r')
|
||||
self.marionette.execute_script(script.read())
|
||||
script.close()
|
||||
else:
|
||||
# assume testScript is a string
|
||||
self.marionette.execute_script(self.testScript)
|
||||
else:
|
||||
# assumes the tests are started on startup automatically
|
||||
pass
|
||||
|
||||
return instance
|
||||
|
||||
|
@ -43,7 +43,7 @@ public interface Actions {
|
||||
*
|
||||
* @param geckoEvent The geckoEvent JSONObject's type
|
||||
*/
|
||||
EventExpecter expectGeckoEvent(String geckoEvent);
|
||||
RepeatedEventExpecter expectGeckoEvent(String geckoEvent);
|
||||
|
||||
/**
|
||||
* Listens for a paint event. Note that calling expectPaint() will
|
||||
|
@ -10,8 +10,8 @@ public interface Assert {
|
||||
void dumpLog(String message, Throwable t);
|
||||
void setLogFile(String filename);
|
||||
void setTestName(String testName);
|
||||
void endTest();
|
||||
|
||||
void finalize();
|
||||
void ok(boolean condition, String name, String diag);
|
||||
void is(Object a, Object b, String name);
|
||||
void isnot(Object a, Object b, String name);
|
||||
|
@ -108,8 +108,7 @@ public class FennecMochitestAssert implements Assert {
|
||||
}
|
||||
}
|
||||
|
||||
public void finalize() {
|
||||
// It appears that we call finalize during cleanup, this might be an invalid assertion.
|
||||
public void endTest() {
|
||||
String message;
|
||||
|
||||
if (mLogTestName != "") {
|
||||
|
@ -65,8 +65,8 @@ public class FennecNativeActions implements Actions {
|
||||
Class [] parameters = new Class[2];
|
||||
parameters[0] = String.class;
|
||||
parameters[1] = mGel;
|
||||
mRegisterGEL = mGas.getMethod("registerGeckoEventListener", parameters);
|
||||
mUnregisterGEL = mGas.getMethod("unregisterGeckoEventListener", parameters);
|
||||
mRegisterGEL = mGas.getMethod("registerEventListener", parameters);
|
||||
mUnregisterGEL = mGas.getMethod("unregisterEventListener", parameters);
|
||||
parameters = new Class[1];
|
||||
parameters[0] = mGe;
|
||||
mSendGE = mGas.getMethod("sendEventToGecko", parameters);
|
||||
@ -115,7 +115,7 @@ public class FennecNativeActions implements Actions {
|
||||
}
|
||||
}
|
||||
|
||||
class GeckoEventExpecter implements EventExpecter {
|
||||
class GeckoEventExpecter implements RepeatedEventExpecter {
|
||||
private final String mGeckoEvent;
|
||||
private final Object[] mRegistrationParams;
|
||||
private boolean mEventReceived;
|
||||
@ -143,6 +143,61 @@ public class FennecNativeActions implements Actions {
|
||||
return;
|
||||
}
|
||||
}
|
||||
try {
|
||||
mUnregisterGEL.invoke(null, mRegistrationParams);
|
||||
} catch (IllegalAccessException e) {
|
||||
FennecNativeDriver.log(LogLevel.ERROR, e);
|
||||
} catch (InvocationTargetException e) {
|
||||
FennecNativeDriver.log(LogLevel.ERROR, e);
|
||||
}
|
||||
FennecNativeDriver.log(FennecNativeDriver.LogLevel.DEBUG,
|
||||
"unblocked on expecter for " + mGeckoEvent);
|
||||
}
|
||||
|
||||
public synchronized void blockUntilClear(long millis) {
|
||||
if (millis <= 0) {
|
||||
throw new IllegalArgumentException("millis must be > 0");
|
||||
}
|
||||
// wait for at least one event
|
||||
long startTime = SystemClock.uptimeMillis();
|
||||
long endTime = 0;
|
||||
while (!mEventReceived) {
|
||||
try {
|
||||
this.wait(MAX_WAIT_MS);
|
||||
} catch (InterruptedException ie) {
|
||||
FennecNativeDriver.log(LogLevel.ERROR, ie);
|
||||
break;
|
||||
}
|
||||
endTime = SystemClock.uptimeMillis();
|
||||
if (!mEventReceived && (endTime - startTime >= MAX_WAIT_MS)) {
|
||||
mAsserter.ok(false, "GeckoEventExpecter", "blockUtilClear timeout");
|
||||
return;
|
||||
}
|
||||
}
|
||||
// now wait for a period of millis where we don't get an event
|
||||
startTime = SystemClock.uptimeMillis();
|
||||
while (true) {
|
||||
try {
|
||||
this.wait(millis);
|
||||
} catch (InterruptedException ie) {
|
||||
FennecNativeDriver.log(LogLevel.ERROR, ie);
|
||||
break;
|
||||
}
|
||||
endTime = SystemClock.uptimeMillis();
|
||||
if (endTime - startTime >= millis) {
|
||||
// success
|
||||
break;
|
||||
}
|
||||
// we got a notify() before we could wait long enough, so we need to start over
|
||||
startTime = endTime;
|
||||
}
|
||||
try {
|
||||
mUnregisterGEL.invoke(null, mRegistrationParams);
|
||||
} catch (IllegalAccessException e) {
|
||||
FennecNativeDriver.log(LogLevel.ERROR, e);
|
||||
} catch (InvocationTargetException e) {
|
||||
FennecNativeDriver.log(LogLevel.ERROR, e);
|
||||
}
|
||||
FennecNativeDriver.log(FennecNativeDriver.LogLevel.DEBUG,
|
||||
"unblocked on expecter for " + mGeckoEvent);
|
||||
}
|
||||
@ -152,13 +207,6 @@ public class FennecNativeActions implements Actions {
|
||||
}
|
||||
|
||||
void notifyOfEvent() {
|
||||
try {
|
||||
mUnregisterGEL.invoke(null, mRegistrationParams);
|
||||
} catch (IllegalAccessException e) {
|
||||
FennecNativeDriver.log(LogLevel.ERROR, e);
|
||||
} catch (InvocationTargetException e) {
|
||||
FennecNativeDriver.log(LogLevel.ERROR, e);
|
||||
}
|
||||
FennecNativeDriver.log(FennecNativeDriver.LogLevel.DEBUG,
|
||||
"received event " + mGeckoEvent);
|
||||
synchronized (this) {
|
||||
@ -168,7 +216,7 @@ public class FennecNativeActions implements Actions {
|
||||
}
|
||||
}
|
||||
|
||||
public EventExpecter expectGeckoEvent(String geckoEvent) {
|
||||
public RepeatedEventExpecter expectGeckoEvent(String geckoEvent) {
|
||||
FennecNativeDriver.log(FennecNativeDriver.LogLevel.DEBUG,
|
||||
"waiting for "+geckoEvent);
|
||||
try {
|
||||
|
@ -94,8 +94,8 @@ public class FennecNativeDriver implements Driver {
|
||||
Class [] parameters = new Class[2];
|
||||
parameters[0] = String.class;
|
||||
parameters[1] = mGel;
|
||||
mRegisterGEL = mGas.getMethod("registerGeckoEventListener", parameters);
|
||||
mUnregisterGEL = mGas.getMethod("unregisterGeckoEventListener", parameters);
|
||||
mRegisterGEL = mGas.getMethod("registerEventListener", parameters);
|
||||
mUnregisterGEL = mGas.getMethod("unregisterEventListener", parameters);
|
||||
parameters = new Class[1];
|
||||
parameters[0] = mGe;
|
||||
mSendGE = mGas.getMethod("sendEventToGecko", parameters);
|
||||
|
@ -31,7 +31,7 @@ public class FennecTalosAssert implements Assert {
|
||||
|
||||
public void setTestName(String testName) { }
|
||||
|
||||
public void finalize() { }
|
||||
public void endTest() { }
|
||||
|
||||
public void ok(boolean condition, String name, String diag) {
|
||||
if (!condition) {
|
||||
|
@ -789,9 +789,12 @@ public class SUTAgentAndroid extends Activity
|
||||
Log.e("SUTAgentAndroid", "exception with file writer on: " + logFile);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (pw != null)
|
||||
{
|
||||
pw.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -38,7 +38,8 @@ endif
|
||||
CSRCS := \
|
||||
inject/$(CPU).c \
|
||||
inject/$(CPU)-noinit.c \
|
||||
test.c \
|
||||
test-ctors.c \
|
||||
test-array.c \
|
||||
$(NULL)
|
||||
|
||||
ifndef CROSS_COMPILE
|
||||
@ -53,33 +54,39 @@ OS_CXXFLAGS := $(filter-out -pedantic,$(OS_CXXFLAGS))
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
test$(DLL_SUFFIX): test.$(OBJ_SUFFIX) elfhack $(CSRCS:.c=.$(OBJ_SUFFIX))
|
||||
$(MKSHLIB) $(LDFLAGS) $<
|
||||
test-array$(DLL_SUFFIX) test-ctors$(DLL_SUFFIX): %$(DLL_SUFFIX): %.$(OBJ_SUFFIX) elfhack $(filter inject/%,$(CSRCS:.c=.$(OBJ_SUFFIX)))
|
||||
$(MKSHLIB) $(LDFLAGS) $< -nostartfiles
|
||||
@echo ===
|
||||
@echo === If you get failures below, please file a bug describing the error
|
||||
@echo === and your environment \(compiler and linker versions\), and use
|
||||
@echo === --disable-elf-hack until this is fixed.
|
||||
@echo ===
|
||||
# Fail if the library doesn't have $(DT_TYPE) .dynamic info
|
||||
$(TOOLCHAIN_PREFIX)readelf -d $@ | grep '($(DT_TYPE))'
|
||||
@rm -f $@.bak
|
||||
$(CURDIR)/elfhack -b -f $@
|
||||
# Fail if the backup file doesn't exist
|
||||
[ -f "$@.bak" ]
|
||||
# Fail if the new library doesn't contain less relocations
|
||||
[ $$(objdump -R $@.bak | wc -l) -gt $$(objdump -R $@ | wc -l) ]
|
||||
[ $$($(TOOLCHAIN_PREFIX)objdump -R $@.bak | wc -l) -gt $$(objdump -R $@ | wc -l) ]
|
||||
|
||||
.PRECIOUS: test$(DLL_SUFFIX)
|
||||
test-array$(DLL_SUFFIX): DT_TYPE=INIT_ARRAY
|
||||
test-ctors$(DLL_SUFFIX): DT_TYPE=INIT
|
||||
|
||||
GARBAGE += test$(DLL_SUFFIX) test$(DLL_SUFFIX).bak
|
||||
.PRECIOUS: test-array$(DLL_SUFFIX) test-ctors$(DLL_SUFFIX)
|
||||
|
||||
libs:: test$(DLL_SUFFIX)
|
||||
GARBAGE += test-array$(DLL_SUFFIX) test-ctors$(DLL_SUFFIX) test-array$(DLL_SUFFIX).bak test-ctors$(DLL_SUFFIX).bak
|
||||
|
||||
libs:: test-array$(DLL_SUFFIX) test-ctors$(DLL_SUFFIX)
|
||||
|
||||
ifndef CROSS_COMPILE
|
||||
dummy: dummy.$(OBJ_SUFFIX) test$(DLL_SUFFIX)
|
||||
dummy: dummy.$(OBJ_SUFFIX)
|
||||
$(CC) -o $@ $^ $(LDFLAGS)
|
||||
|
||||
libs:: dummy
|
||||
# Will either crash or return exit code 1 if elfhack is broken
|
||||
LD_LIBRARY_PATH=$(CURDIR) $(CURDIR)/dummy
|
||||
LD_PRELOAD=$(CURDIR)/test-array$(DLL_SUFFIX) $(CURDIR)/dummy
|
||||
LD_PRELOAD=$(CURDIR)/test-ctors$(DLL_SUFFIX) $(CURDIR)/dummy
|
||||
|
||||
GARBAGE += dummy
|
||||
endif
|
||||
@ -87,7 +94,7 @@ endif
|
||||
inject:
|
||||
$(NSINSTALL) -D $@
|
||||
|
||||
inject/%.c: inject.c | inject
|
||||
inject/%.c: inject.c $(call mkdir_deps,inject)
|
||||
cp $< $@
|
||||
|
||||
GARBAGE_DIRS += inject
|
||||
|
@ -2,7 +2,7 @@
|
||||
* 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/. */
|
||||
|
||||
extern __attribute__((visibility("default"))) int print_status();
|
||||
extern __attribute__((visibility("default"), weak)) int print_status();
|
||||
|
||||
int main() {
|
||||
return print_status();
|
||||
|
@ -347,7 +347,7 @@ ElfDynamic_Section *Elf::getDynSection()
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void Elf::write(std::ofstream &file)
|
||||
void Elf::normalize()
|
||||
{
|
||||
// fixup section headers sh_name; TODO: that should be done by sections
|
||||
// themselves
|
||||
@ -387,6 +387,11 @@ void Elf::write(std::ofstream &file)
|
||||
ehdr->e_shoff = shdr_section->getOffset();
|
||||
ehdr->e_entry = eh_entry.getValue();
|
||||
ehdr->e_shstrndx = eh_shstrndx->getIndex();
|
||||
}
|
||||
|
||||
void Elf::write(std::ofstream &file)
|
||||
{
|
||||
normalize();
|
||||
for (ElfSection *section = ehdr;
|
||||
section != NULL; section = section->getNext()) {
|
||||
file.seekp(section->getOffset());
|
||||
@ -642,34 +647,25 @@ ElfSection *ElfDynamic_Section::getSectionForType(unsigned int tag)
|
||||
return value ? value->getSection() : NULL;
|
||||
}
|
||||
|
||||
void ElfDynamic_Section::setValueForType(unsigned int tag, ElfValue *val)
|
||||
bool ElfDynamic_Section::setValueForType(unsigned int tag, ElfValue *val)
|
||||
{
|
||||
unsigned int i;
|
||||
for (i = 0; (i < shdr.sh_size / shdr.sh_entsize) && (dyns[i].tag != DT_NULL); i++)
|
||||
unsigned int shnum = shdr.sh_size / shdr.sh_entsize;
|
||||
for (i = 0; (i < shnum) && (dyns[i].tag != DT_NULL); i++)
|
||||
if (dyns[i].tag == tag) {
|
||||
delete dyns[i].value;
|
||||
dyns[i].value = val;
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
// This should never happen, as the last entry is always tagged DT_NULL
|
||||
assert(i < shdr.sh_size / shdr.sh_entsize);
|
||||
// If we get here, this means we didn't match for the given tag
|
||||
// Most of the time, there are a few DT_NULL entries, that we can
|
||||
// use to add our value, but if we are on the last entry, we can't.
|
||||
if (i >= shnum - 1)
|
||||
return false;
|
||||
|
||||
dyns[i].tag = tag;
|
||||
dyns[i++].value = val;
|
||||
|
||||
// If we were on the last entry, we need to grow the section.
|
||||
// Most of the time, though, there are a few DT_NULL entries.
|
||||
if (i < shdr.sh_size / shdr.sh_entsize)
|
||||
return;
|
||||
|
||||
Elf_DynValue value;
|
||||
value.tag = DT_NULL;
|
||||
value.value = NULL;
|
||||
dyns.push_back(value);
|
||||
// Resize the section accordingly
|
||||
shdr.sh_size += shdr.sh_entsize;
|
||||
if (getNext() != NULL)
|
||||
getNext()->markDirty();
|
||||
dyns[i].value = val;
|
||||
return true;
|
||||
}
|
||||
|
||||
ElfDynamic_Section::ElfDynamic_Section(Elf_Shdr &s, std::ifstream *file, Elf *parent)
|
||||
|
@ -38,6 +38,8 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
typedef serializable<Elf_Addr_Traits> Elf_Addr;
|
||||
|
||||
class Elf_RelHack_Traits {
|
||||
public:
|
||||
typedef Elf32_Rel Type32;
|
||||
@ -81,10 +83,9 @@ private:
|
||||
|
||||
class ElfRelHackCode_Section: public ElfSection {
|
||||
public:
|
||||
ElfRelHackCode_Section(Elf_Shdr &s, Elf &e)
|
||||
: ElfSection(s, NULL, NULL), parent(e) {
|
||||
ElfRelHackCode_Section(Elf_Shdr &s, Elf &e, unsigned int init)
|
||||
: ElfSection(s, NULL, NULL), parent(e), init(init) {
|
||||
std::string file(rundir);
|
||||
init = parent.getDynSection()->getSectionForType(DT_INIT);
|
||||
file += "/inject/";
|
||||
switch (parent.getMachine()) {
|
||||
case EM_386:
|
||||
@ -99,7 +100,7 @@ public:
|
||||
default:
|
||||
throw std::runtime_error("unsupported architecture");
|
||||
}
|
||||
if (init == NULL)
|
||||
if (!init)
|
||||
file += "-noinit";
|
||||
file += ".o";
|
||||
std::ifstream inject(file.c_str(), std::ios::in|std::ios::binary);
|
||||
@ -224,17 +225,17 @@ private:
|
||||
Elf32_Addr operator()(unsigned int base_addr, Elf32_Off offset,
|
||||
Elf32_Word addend, unsigned int addr)
|
||||
{
|
||||
/* Follows description of b.w instructions as per
|
||||
/* Follows description of b.w and bl instructions as per
|
||||
ARM Architecture Reference Manual ARM® v7-A and ARM® v7-R edition, A8.6.16
|
||||
We limit ourselves to Encoding T3.
|
||||
We limit ourselves to Encoding T4 of b.w and Encoding T1 of bl.
|
||||
We don't care about sign_extend because the only case where this is
|
||||
going to be used only jumps forward. */
|
||||
Elf32_Addr tmp = (Elf32_Addr) (addr - offset - base_addr);
|
||||
unsigned int word0 = addend & 0xffff,
|
||||
word1 = addend >> 16;
|
||||
|
||||
if (((word0 & 0xf800) != 0xf000) || ((word1 & 0xd000) != 0x9000))
|
||||
throw std::runtime_error("R_ARM_THM_JUMP24 relocation only supported for B.W <label>");
|
||||
if (((word0 & 0xf800) != 0xf000) || ((word1 & 0x9000) != 0x9000))
|
||||
throw std::runtime_error("R_ARM_THM_JUMP24/R_ARM_THM_CALL relocation only supported for B.W <label> and BL <label>");
|
||||
|
||||
unsigned int s = (word0 & (1 << 10)) >> 10;
|
||||
unsigned int j1 = (word1 & (1 << 13)) >> 13;
|
||||
@ -249,7 +250,7 @@ private:
|
||||
j2 = ((tmp & (1 << 22)) >> 22) ^ !s;
|
||||
|
||||
return 0xf000 | (s << 10) | ((tmp & (0x3ff << 12)) >> 12) |
|
||||
(0x9000 << 16) | (j1 << 29) | (j2 << 27) | ((tmp & 0xffe) << 15);
|
||||
((word1 & 0xd000) << 16) | (j1 << 29) | (j2 << 27) | ((tmp & 0xffe) << 15);
|
||||
}
|
||||
};
|
||||
|
||||
@ -299,7 +300,7 @@ private:
|
||||
ElfSection *ehdr = parent.getSection(1)->getPrevious()->getPrevious();
|
||||
addr = ehdr->getAddr();
|
||||
} else if (strcmp(name, "original_init") == 0) {
|
||||
addr = init->getAddr();
|
||||
addr = init;
|
||||
} else if (strcmp(name, "_GLOBAL_OFFSET_TABLE_") == 0) {
|
||||
// We actually don't need a GOT, but need it as a reference for
|
||||
// GOTOFF relocations. We'll just use the start of the ELF file
|
||||
@ -328,6 +329,7 @@ private:
|
||||
case REL(ARM, PLT32):
|
||||
apply_relocation<arm_plt32_relocation>(the_code, buf, &*r, addr);
|
||||
break;
|
||||
case REL(ARM, THM_PC22 /* THM_CALL */):
|
||||
case REL(ARM, THM_JUMP24):
|
||||
apply_relocation<arm_thm_jump24_relocation>(the_code, buf, &*r, addr);
|
||||
break;
|
||||
@ -346,12 +348,36 @@ private:
|
||||
|
||||
Elf *elf, &parent;
|
||||
std::vector<ElfSection *> code;
|
||||
ElfSection *init;
|
||||
unsigned int init;
|
||||
int entry_point;
|
||||
};
|
||||
|
||||
unsigned int get_addend(Elf_Rel *rel, Elf *elf) {
|
||||
ElfLocation loc(rel->r_offset, elf);
|
||||
Elf_Addr addr(loc.getBuffer(), Elf_Addr::size(elf->getClass()), elf->getClass(), elf->getData());
|
||||
return addr.value;
|
||||
}
|
||||
|
||||
unsigned int get_addend(Elf_Rela *rel, Elf *elf) {
|
||||
return rel->r_addend;
|
||||
}
|
||||
|
||||
void set_relative_reloc(Elf_Rel *rel, Elf *elf, unsigned int value) {
|
||||
ElfLocation loc(rel->r_offset, elf);
|
||||
Elf_Addr addr;
|
||||
addr.value = value;
|
||||
addr.serialize(const_cast<char *>(loc.getBuffer()), Elf_Addr::size(elf->getClass()), elf->getClass(), elf->getData());
|
||||
}
|
||||
|
||||
void set_relative_reloc(Elf_Rela *rel, Elf *elf, unsigned int value) {
|
||||
// ld puts the value of relocated relocations both in the addend and
|
||||
// at r_offset. For consistency, keep it that way.
|
||||
set_relative_reloc((Elf_Rel *)rel, elf, value);
|
||||
rel->r_addend = value;
|
||||
}
|
||||
|
||||
template <typename Rel_Type>
|
||||
int do_relocation_section(Elf *elf, unsigned int rel_type, unsigned int rel_type2)
|
||||
int do_relocation_section(Elf *elf, unsigned int rel_type, unsigned int rel_type2, bool force)
|
||||
{
|
||||
ElfDynamic_Section *dyn = elf->getDynSection();
|
||||
if (dyn ==NULL) {
|
||||
@ -370,10 +396,35 @@ int do_relocation_section(Elf *elf, unsigned int rel_type, unsigned int rel_type
|
||||
Elf32_Shdr relhackcode32_section =
|
||||
{ 0, SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR, 0, (Elf32_Off)-1, 0,
|
||||
SHN_UNDEF, 0, 1, 0 };
|
||||
|
||||
unsigned int entry_sz = Elf_Addr::size(elf->getClass());
|
||||
|
||||
// The injected code needs to be executed before any init code in the
|
||||
// binary. There are three possible cases:
|
||||
// - The binary has no init code at all. In this case, we will add a
|
||||
// DT_INIT entry pointing to the injected code.
|
||||
// - The binary has a DT_INIT entry. In this case, we will interpose:
|
||||
// we change DT_INIT to point to the injected code, and have the
|
||||
// injected code call the original DT_INIT entry point.
|
||||
// - The binary has no DT_INIT entry, but has a DT_INIT_ARRAY. In this
|
||||
// case, we interpose as well, by replacing the first entry in the
|
||||
// array to point to the injected code, and have the injected code
|
||||
// call the original first entry.
|
||||
// The binary may have .ctors instead of DT_INIT_ARRAY, for its init
|
||||
// functions, but this falls into the second case above, since .ctors
|
||||
// are actually run by DT_INIT code.
|
||||
ElfValue *value = dyn->getValueForType(DT_INIT);
|
||||
unsigned int original_init = value ? value->getValue() : 0;
|
||||
ElfSection *init_array = NULL;
|
||||
if (!value || !value->getValue()) {
|
||||
value = dyn->getValueForType(DT_INIT_ARRAYSZ);
|
||||
if (value && value->getValue() >= entry_sz)
|
||||
init_array = dyn->getSectionForType(DT_INIT_ARRAY);
|
||||
}
|
||||
|
||||
Elf_Shdr relhack_section(relhack32_section);
|
||||
Elf_Shdr relhackcode_section(relhackcode32_section);
|
||||
ElfRelHack_Section *relhack = new ElfRelHack_Section(relhack_section);
|
||||
ElfRelHackCode_Section *relhackcode = new ElfRelHackCode_Section(relhackcode_section, *elf);
|
||||
|
||||
ElfSymtab_Section *symtab = (ElfSymtab_Section *) section->getLink();
|
||||
Elf_SymValue *sym = symtab->lookup("__cxa_pure_virtual");
|
||||
@ -381,13 +432,13 @@ int do_relocation_section(Elf *elf, unsigned int rel_type, unsigned int rel_type
|
||||
std::vector<Rel_Type> new_rels;
|
||||
Elf_RelHack relhack_entry;
|
||||
relhack_entry.r_offset = relhack_entry.r_info = 0;
|
||||
int entry_sz = (elf->getClass() == ELFCLASS32) ? 4 : 8;
|
||||
size_t init_array_reloc = 0;
|
||||
for (typename std::vector<Rel_Type>::iterator i = section->rels.begin();
|
||||
i != section->rels.end(); i++) {
|
||||
// We don't need to keep R_*_NONE relocations
|
||||
if (!ELF32_R_TYPE(i->r_info))
|
||||
continue;
|
||||
ElfSection *section = elf->getSectionAt(i->r_offset);
|
||||
ElfLocation loc(i->r_offset, elf);
|
||||
// __cxa_pure_virtual is a function used in vtables to point at pure
|
||||
// virtual methods. The __cxa_pure_virtual function usually abort()s.
|
||||
// These functions are however normally never called. In the case
|
||||
@ -401,9 +452,9 @@ int do_relocation_section(Elf *elf, unsigned int rel_type, unsigned int rel_type
|
||||
// __cxa_pure_virtual symbol is defined in our lib, and we
|
||||
// have relative relocations (rel_type) for it.
|
||||
if (ELF32_R_TYPE(i->r_info) == rel_type) {
|
||||
serializable<Elf_Addr_Traits> addr(§ion->getData()[i->r_offset - section->getAddr()], entry_sz, elf->getClass(), elf->getData());
|
||||
Elf_Addr addr(loc.getBuffer(), entry_sz, elf->getClass(), elf->getData());
|
||||
if (addr.value == sym->value.getValue()) {
|
||||
memset((char *)§ion->getData()[i->r_offset - section->getAddr()], 0, entry_sz);
|
||||
memset((char *)loc.getBuffer(), 0, entry_sz);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -413,18 +464,26 @@ int do_relocation_section(Elf *elf, unsigned int rel_type, unsigned int rel_type
|
||||
// have absolute relocations (rel_type2) for it.
|
||||
if ((ELF32_R_TYPE(i->r_info) == rel_type2) &&
|
||||
(sym == &symtab->syms[ELF32_R_SYM(i->r_info)])) {
|
||||
memset((char *)§ion->getData()[i->r_offset - section->getAddr()], 0, entry_sz);
|
||||
memset((char *)loc.getBuffer(), 0, entry_sz);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Keep track of the relocation associated with the first init_array entry.
|
||||
if (init_array && i->r_offset == init_array->getAddr()) {
|
||||
if (init_array_reloc) {
|
||||
fprintf(stderr, "Found multiple relocations for the first init_array entry. Skipping\n");
|
||||
return -1;
|
||||
}
|
||||
new_rels.push_back(*i);
|
||||
init_array_reloc = new_rels.size();
|
||||
} else if (!(loc.getSection()->getFlags() & SHF_WRITE) || (ELF32_R_TYPE(i->r_info) != rel_type) ||
|
||||
(relro && (i->r_offset >= relro->getAddr()) &&
|
||||
(i->r_offset < relro->getAddr() + relro->getMemSize()))) {
|
||||
// Don't pack relocations happening in non writable sections.
|
||||
// Our injected code is likely not to be allowed to write there.
|
||||
if (!(section->getFlags() & SHF_WRITE) || (ELF32_R_TYPE(i->r_info) != rel_type) ||
|
||||
(relro && (i->r_offset >= relro->getAddr()) &&
|
||||
(i->r_offset < relro->getAddr() + relro->getMemSize())))
|
||||
new_rels.push_back(*i);
|
||||
else {
|
||||
} else {
|
||||
// TODO: check that i->r_addend == *i->r_offset
|
||||
if (i->r_offset == relhack_entry.r_offset + relhack_entry.r_info * entry_sz) {
|
||||
relhack_entry.r_info++;
|
||||
@ -444,21 +503,54 @@ int do_relocation_section(Elf *elf, unsigned int rel_type, unsigned int rel_type
|
||||
|
||||
unsigned int old_end = section->getOffset() + section->getSize();
|
||||
|
||||
if (init_array) {
|
||||
if (! init_array_reloc) {
|
||||
fprintf(stderr, "Didn't find relocation for DT_INIT_ARRAY's first entry. Skipping\n");
|
||||
return -1;
|
||||
}
|
||||
Rel_Type *rel = &new_rels[init_array_reloc - 1];
|
||||
unsigned int addend = get_addend(rel, elf);
|
||||
// Use relocated value of DT_INIT_ARRAY's first entry for the
|
||||
// function to be called by the injected code.
|
||||
if (ELF32_R_TYPE(rel->r_info) == rel_type) {
|
||||
original_init = addend;
|
||||
} else if (ELF32_R_TYPE(rel->r_info) == rel_type2) {
|
||||
ElfSymtab_Section *symtab = (ElfSymtab_Section *)section->getLink();
|
||||
original_init = symtab->syms[ELF32_R_SYM(rel->r_info)].value.getValue() + addend;
|
||||
} else {
|
||||
fprintf(stderr, "Unsupported relocation type for DT_INIT_ARRAY's first entry. Skipping\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
ElfRelHackCode_Section *relhackcode = new ElfRelHackCode_Section(relhackcode_section, *elf, original_init);
|
||||
relhackcode->insertBefore(section);
|
||||
relhack->insertAfter(relhackcode);
|
||||
|
||||
section->rels.assign(new_rels.begin(), new_rels.end());
|
||||
section->shrink(new_rels.size() * section->getEntSize());
|
||||
ElfLocation *init = new ElfLocation(relhackcode, relhackcode->getEntryPoint());
|
||||
dyn->setValueForType(DT_INIT, init);
|
||||
// TODO: adjust the value according to the remaining number of relative relocations
|
||||
if (dyn->getValueForType(Rel_Type::d_tag_count))
|
||||
dyn->setValueForType(Rel_Type::d_tag_count, new ElfPlainValue(0));
|
||||
|
||||
if (section->getOffset() + section->getSize() >= old_end) {
|
||||
fprintf(stderr, "No gain. Skipping\n");
|
||||
return -1;
|
||||
}
|
||||
// Ensure Elf sections will be at their final location.
|
||||
elf->normalize();
|
||||
ElfLocation *init = new ElfLocation(relhackcode, relhackcode->getEntryPoint());
|
||||
if (init_array) {
|
||||
// Adjust the first DT_INIT_ARRAY entry to point at the injected code
|
||||
// by transforming its relocation into a relative one pointing to the
|
||||
// address of the injected code.
|
||||
Rel_Type *rel = §ion->rels[init_array_reloc - 1];
|
||||
rel->r_info = ELF32_R_INFO(0, rel_type); // Set as a relative relocation
|
||||
set_relative_reloc(§ion->rels[init_array_reloc - 1], elf, init->getValue());
|
||||
} else if (!dyn->setValueForType(DT_INIT, init)) {
|
||||
fprintf(stderr, "Can't grow .dynamic section to set DT_INIT. Skipping\n");
|
||||
return -1;
|
||||
}
|
||||
// TODO: adjust the value according to the remaining number of relative relocations
|
||||
if (dyn->getValueForType(Rel_Type::d_tag_count))
|
||||
dyn->setValueForType(Rel_Type::d_tag_count, new ElfPlainValue(0));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -494,13 +586,13 @@ void do_file(const char *name, bool backup = false, bool force = false)
|
||||
int exit = -1;
|
||||
switch (elf->getMachine()) {
|
||||
case EM_386:
|
||||
exit = do_relocation_section<Elf_Rel>(elf, R_386_RELATIVE, R_386_32);
|
||||
exit = do_relocation_section<Elf_Rel>(elf, R_386_RELATIVE, R_386_32, force);
|
||||
break;
|
||||
case EM_X86_64:
|
||||
exit = do_relocation_section<Elf_Rela>(elf, R_X86_64_RELATIVE, R_X86_64_64);
|
||||
exit = do_relocation_section<Elf_Rela>(elf, R_X86_64_RELATIVE, R_X86_64_64, force);
|
||||
break;
|
||||
case EM_ARM:
|
||||
exit = do_relocation_section<Elf_Rel>(elf, R_ARM_RELATIVE, R_ARM_ABS32);
|
||||
exit = do_relocation_section<Elf_Rel>(elf, R_ARM_RELATIVE, R_ARM_ABS32, force);
|
||||
break;
|
||||
}
|
||||
if (exit == 0) {
|
||||
|
@ -135,6 +135,7 @@ public:
|
||||
ElfLocation(unsigned int location, Elf *elf);
|
||||
unsigned int getValue();
|
||||
ElfSection *getSection() { return section; }
|
||||
const char *getBuffer();
|
||||
};
|
||||
|
||||
class ElfSize: public ElfValue {
|
||||
@ -164,7 +165,7 @@ private:
|
||||
void init(const char *buf, size_t len, char ei_data)
|
||||
{
|
||||
R e;
|
||||
assert(len <= sizeof(e));
|
||||
assert(len >= sizeof(e));
|
||||
memcpy(&e, buf, sizeof(e));
|
||||
if (ei_data == ELFDATA2LSB) {
|
||||
T::template swap<little_endian>(e, *this);
|
||||
@ -176,6 +177,20 @@ private:
|
||||
throw std::runtime_error("Unsupported ELF data encoding");
|
||||
}
|
||||
|
||||
template <typename R>
|
||||
void serialize(const char *buf, size_t len, char ei_data)
|
||||
{
|
||||
assert(len >= sizeof(R));
|
||||
if (ei_data == ELFDATA2LSB) {
|
||||
T::template swap<little_endian>(*this, *(R *)buf);
|
||||
return;
|
||||
} else if (ei_data == ELFDATA2MSB) {
|
||||
T::template swap<big_endian>(*this, *(R *)buf);
|
||||
return;
|
||||
}
|
||||
throw std::runtime_error("Unsupported ELF data encoding");
|
||||
}
|
||||
|
||||
public:
|
||||
serializable(const char *buf, size_t len, char ei_class, char ei_data)
|
||||
{
|
||||
@ -194,23 +209,13 @@ public:
|
||||
if (ei_class == ELFCLASS32) {
|
||||
typename T::Type32 e;
|
||||
file.read((char *)&e, sizeof(e));
|
||||
if (ei_data == ELFDATA2LSB) {
|
||||
T::template swap<little_endian>(e, *this);
|
||||
init<typename T::Type32>((char *)&e, sizeof(e), ei_data);
|
||||
return;
|
||||
} else if (ei_data == ELFDATA2MSB) {
|
||||
T::template swap<big_endian>(e, *this);
|
||||
return;
|
||||
}
|
||||
} else if (ei_class == ELFCLASS64) {
|
||||
typename T::Type64 e;
|
||||
file.read((char *)&e, sizeof(e));
|
||||
if (ei_data == ELFDATA2LSB) {
|
||||
T::template swap<little_endian>(e, *this);
|
||||
init<typename T::Type64>((char *)&e, sizeof(e), ei_data);
|
||||
return;
|
||||
} else if (ei_data == ELFDATA2MSB) {
|
||||
T::template swap<big_endian>(e, *this);
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw std::runtime_error("Unsupported ELF class or data encoding");
|
||||
}
|
||||
@ -219,30 +224,30 @@ public:
|
||||
{
|
||||
if (ei_class == ELFCLASS32) {
|
||||
typename T::Type32 e;
|
||||
if (ei_data == ELFDATA2LSB) {
|
||||
T::template swap<little_endian>(*this, e);
|
||||
serialize<typename T::Type32>((char *)&e, sizeof(e), ei_data);
|
||||
file.write((char *)&e, sizeof(e));
|
||||
return;
|
||||
} else if (ei_data == ELFDATA2MSB) {
|
||||
T::template swap<big_endian>(*this, e);
|
||||
file.write((char *)&e, sizeof(e));
|
||||
return;
|
||||
}
|
||||
} else if (ei_class == ELFCLASS64) {
|
||||
typename T::Type64 e;
|
||||
if (ei_data == ELFDATA2LSB) {
|
||||
T::template swap<little_endian>(*this, e);
|
||||
serialize<typename T::Type64>((char *)&e, sizeof(e), ei_data);
|
||||
file.write((char *)&e, sizeof(e));
|
||||
return;
|
||||
} else if (ei_data == ELFDATA2MSB) {
|
||||
T::template swap<big_endian>(*this, e);
|
||||
file.write((char *)&e, sizeof(e));
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw std::runtime_error("Unsupported ELF class or data encoding");
|
||||
}
|
||||
|
||||
void serialize(char *buf, size_t len, char ei_class, char ei_data)
|
||||
{
|
||||
if (ei_class == ELFCLASS32) {
|
||||
serialize<typename T::Type32>(buf, len, ei_data);
|
||||
return;
|
||||
} else if (ei_class == ELFCLASS64) {
|
||||
serialize<typename T::Type64>(buf, len, ei_data);
|
||||
return;
|
||||
}
|
||||
throw std::runtime_error("Unsupported ELF class");
|
||||
}
|
||||
|
||||
static inline unsigned int size(char ei_class)
|
||||
{
|
||||
if (ei_class == ELFCLASS32)
|
||||
@ -269,6 +274,7 @@ public:
|
||||
|
||||
ElfDynamic_Section *getDynSection();
|
||||
|
||||
void normalize();
|
||||
void write(std::ofstream &file);
|
||||
|
||||
char getClass();
|
||||
@ -505,7 +511,7 @@ public:
|
||||
|
||||
ElfValue *getValueForType(unsigned int tag);
|
||||
ElfSection *getSectionForType(unsigned int tag);
|
||||
void setValueForType(unsigned int tag, ElfValue *val);
|
||||
bool setValueForType(unsigned int tag, ElfValue *val);
|
||||
private:
|
||||
std::vector<Elf_DynValue> dyns;
|
||||
};
|
||||
@ -661,6 +667,10 @@ inline unsigned int ElfLocation::getValue() {
|
||||
return (section ? section->getAddr() : 0) + offset;
|
||||
}
|
||||
|
||||
inline const char *ElfLocation::getBuffer() {
|
||||
return section ? section->getData() + offset : NULL;
|
||||
}
|
||||
|
||||
inline unsigned int ElfSize::getValue() {
|
||||
return section->getSize();
|
||||
}
|
||||
|
8
build/unix/elfhack/test-array.c
Normal file
8
build/unix/elfhack/test-array.c
Normal file
@ -0,0 +1,8 @@
|
||||
/* 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 "test.c"
|
||||
|
||||
__attribute__((section(".init_array"), used))
|
||||
static void (*init_array[])() = { end_test, test };
|
17
build/unix/elfhack/test-ctors.c
Normal file
17
build/unix/elfhack/test-ctors.c
Normal file
@ -0,0 +1,17 @@
|
||||
/* 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 "test.c"
|
||||
|
||||
/* Recent binutils would put .ctors content into a .init_array section */
|
||||
__attribute__((section(".manual_ctors"), used))
|
||||
static void (*ctors[])() = { (void (*)())-1, end_test, test, NULL };
|
||||
|
||||
__attribute__((section(".init")))
|
||||
void _init() {
|
||||
void (**func)() = &ctors[sizeof(ctors) / sizeof(void (*)()) - 1];
|
||||
while (*(--func) != (void (*)())-1) {
|
||||
(*func)();
|
||||
}
|
||||
}
|
@ -125,14 +125,14 @@ int print_status() {
|
||||
* following sections as part of the PT_TLS segment. */
|
||||
__thread int foo[1024];
|
||||
|
||||
__attribute__((constructor)) void end_test() {
|
||||
void end_test() {
|
||||
static int count = 0;
|
||||
/* Only exit when both constructors have been called */
|
||||
if (++count == 2)
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
__attribute__((constructor)) void test() {
|
||||
void test() {
|
||||
int i = 0, j = 0;
|
||||
#define DEF_(a,i,w) \
|
||||
if (a[i++] != str_ ## w) return;
|
||||
|
48
configure.in
48
configure.in
@ -4150,7 +4150,6 @@ MOZ_SPEEX_RESAMPLER=1
|
||||
MOZ_CUBEB=
|
||||
MOZ_VORBIS=
|
||||
MOZ_TREMOR=
|
||||
MOZ_FLOATING_POINT_AUDIO=
|
||||
MOZ_WAVE=1
|
||||
MOZ_MEDIA=
|
||||
MOZ_OPUS=1
|
||||
@ -5200,24 +5199,6 @@ fi
|
||||
|
||||
AC_SUBST(MOZ_WEBRTC)
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Disable floating point audio.
|
||||
dnl ========================================================
|
||||
MOZ_ARG_DISABLE_BOOL(floating-point,
|
||||
[ --disable-floating-point Disable floating point audio],
|
||||
MOZ_FLOATING_POINT_AUDIO=,
|
||||
MOZ_FLOATING_POINT_AUDIO=1)
|
||||
|
||||
|
||||
case "$target_cpu" in
|
||||
arm*)
|
||||
;;
|
||||
*)
|
||||
AC_DEFINE(MOZ_FLOATING_POINT_AUDIO)
|
||||
MOZ_FLOATING_POINT_AUDIO=1
|
||||
;;
|
||||
esac
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Enable Raw Codecs
|
||||
dnl ========================================================
|
||||
@ -5246,6 +5227,14 @@ if test -n "$MOZ_OGG"; then
|
||||
MOZ_SYDNEYAUDIO=1
|
||||
MOZ_CUBEB=1
|
||||
MOZ_MEDIA=1
|
||||
case "$target_cpu" in
|
||||
arm*)
|
||||
MOZ_TREMOR=1
|
||||
;;
|
||||
*)
|
||||
MOZ_VORBIS=1
|
||||
;;
|
||||
esac
|
||||
|
||||
dnl Checks for __attribute__(aligned()) directive
|
||||
AC_CACHE_CHECK([__attribute__ ((aligned ())) support],
|
||||
@ -5315,7 +5304,7 @@ if test -n "$MOZ_MEDIA_NAVIGATOR"; then
|
||||
fi
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Enable building OMX media plugin (B2G)
|
||||
dnl = Enable building OMX media plugin (B2G or Android)
|
||||
dnl ========================================================
|
||||
MOZ_ARG_ENABLE_BOOL(omx-plugin,
|
||||
[ --enable-omx-plugin Enable building OMX plugin (B2G)],
|
||||
@ -5323,12 +5312,12 @@ MOZ_ARG_ENABLE_BOOL(omx-plugin,
|
||||
MOZ_OMX_PLUGIN=)
|
||||
|
||||
if test -n "$MOZ_OMX_PLUGIN"; then
|
||||
if test "$OS_TARGET" = "Android" -a -n "$gonkdir"; then
|
||||
dnl Only allow building OMX plugin on Gonk (B2G)
|
||||
if test "$OS_TARGET" = "Android"; then
|
||||
dnl Only allow building OMX plugin on Gonk (B2G) or Android
|
||||
AC_DEFINE(MOZ_OMX_PLUGIN)
|
||||
else
|
||||
dnl fail if we're not building on Gonk
|
||||
AC_MSG_ERROR([OMX media plugin can only be built on B2G])
|
||||
dnl fail if we're not building on Gonk or Android
|
||||
AC_MSG_ERROR([OMX media plugin can only be built on B2G or Android])
|
||||
fi
|
||||
fi
|
||||
|
||||
@ -5375,11 +5364,14 @@ if test "$MOZ_WEBM"; then
|
||||
MOZ_SYDNEYAUDIO=1
|
||||
MOZ_CUBEB=1
|
||||
MOZ_MEDIA=1
|
||||
if test -n "$MOZ_FLOATING_POINT_AUDIO"; then
|
||||
MOZ_VORBIS=1
|
||||
else
|
||||
case "$target_cpu" in
|
||||
arm*)
|
||||
MOZ_TREMOR=1
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
MOZ_VORBIS=1
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if test -n "$MOZ_VP8" -a -z "$MOZ_NATIVE_LIBVPX"; then
|
||||
|
55
content/base/public/DirectionalityUtils.h
Normal file
55
content/base/public/DirectionalityUtils.h
Normal file
@ -0,0 +1,55 @@
|
||||
/* -*- 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 DirectionalityUtils_h___
|
||||
#define DirectionalityUtils_h___
|
||||
|
||||
class nsIContent;
|
||||
class nsIDocument;
|
||||
class nsINode;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class Element;
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace directionality {
|
||||
|
||||
enum Directionality {
|
||||
eDir_NotSet = 0,
|
||||
eDir_RTL = 1,
|
||||
eDir_LTR = 2
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the directionality of an element according to the algorithm defined at
|
||||
* http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#the-directionality,
|
||||
* not including elements with auto direction.
|
||||
*
|
||||
* @return the directionality that the element was set to
|
||||
*/
|
||||
Directionality RecomputeDirectionality(mozilla::dom::Element* aElement,
|
||||
bool aNotify = true);
|
||||
|
||||
/**
|
||||
* Set the directionality of any descendants of a node that do not themselves
|
||||
* have a dir attribute.
|
||||
* For performance reasons we walk down the descendant tree in the rare case
|
||||
* of setting the dir attribute, rather than walking up the ancestor tree in
|
||||
* the much more common case of getting the element's directionality.
|
||||
*/
|
||||
void SetDirectionalityOnDescendants(mozilla::dom::Element* aElement,
|
||||
Directionality aDir,
|
||||
bool aNotify = true);
|
||||
|
||||
} // end namespace directionality
|
||||
|
||||
} // end namespace mozilla
|
||||
|
||||
#endif /* DirectionalityUtils_h___ */
|
@ -10,6 +10,7 @@
|
||||
#include "mozilla/dom/FragmentOrElement.h" // for base class
|
||||
#include "nsChangeHint.h" // for enum
|
||||
#include "nsEventStates.h" // for member
|
||||
#include "mozilla/dom/DirectionalityUtils.h"
|
||||
|
||||
class nsEventStateManager;
|
||||
class nsFocusManager;
|
||||
@ -216,6 +217,54 @@ public:
|
||||
*/
|
||||
virtual nsIAtom *GetClassAttributeName() const = 0;
|
||||
|
||||
inline mozilla::directionality::Directionality GetDirectionality() const {
|
||||
if (HasFlag(NODE_HAS_DIRECTION_RTL)) {
|
||||
return mozilla::directionality::eDir_RTL;
|
||||
}
|
||||
|
||||
if (HasFlag(NODE_HAS_DIRECTION_LTR)) {
|
||||
return mozilla::directionality::eDir_LTR;
|
||||
}
|
||||
|
||||
return mozilla::directionality::eDir_NotSet;
|
||||
}
|
||||
|
||||
inline void SetDirectionality(mozilla::directionality::Directionality aDir,
|
||||
bool aNotify) {
|
||||
UnsetFlags(NODE_ALL_DIRECTION_FLAGS);
|
||||
if (!aNotify) {
|
||||
RemoveStatesSilently(DIRECTION_STATES);
|
||||
}
|
||||
|
||||
switch (aDir) {
|
||||
case (mozilla::directionality::eDir_RTL):
|
||||
SetFlags(NODE_HAS_DIRECTION_RTL);
|
||||
if (!aNotify) {
|
||||
AddStatesSilently(NS_EVENT_STATE_RTL);
|
||||
}
|
||||
break;
|
||||
|
||||
case(mozilla::directionality::eDir_LTR):
|
||||
SetFlags(NODE_HAS_DIRECTION_LTR);
|
||||
if (!aNotify) {
|
||||
AddStatesSilently(NS_EVENT_STATE_LTR);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Only call UpdateState if we need to notify, because we call
|
||||
* SetDirectionality for every element, and UpdateState is very very slow
|
||||
* for some elements.
|
||||
*/
|
||||
if (aNotify) {
|
||||
UpdateState(true);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Method to get the _intrinsic_ content state of this element. This is the
|
||||
|
@ -48,6 +48,7 @@ $(NULL)
|
||||
EXPORTS_NAMESPACES = mozilla/dom mozilla
|
||||
|
||||
EXPORTS_mozilla/dom = \
|
||||
DirectionalityUtils.h \
|
||||
Element.h \
|
||||
FragmentOrElement.h \
|
||||
FromParser.h \
|
||||
|
@ -21,7 +21,7 @@
|
||||
//A trick to handle IEEE floating point exceptions on FreeBSD - E.D.
|
||||
#ifdef __FreeBSD__
|
||||
#include <ieeefp.h>
|
||||
#ifdef __alpha__
|
||||
#if !defined(__i386__) && !defined(__x86_64__)
|
||||
static fp_except_t allmask = FP_X_INV|FP_X_OFL|FP_X_UFL|FP_X_DZ|FP_X_IMP;
|
||||
#else
|
||||
static fp_except_t allmask = FP_X_INV|FP_X_OFL|FP_X_UFL|FP_X_DZ|FP_X_IMP|FP_X_DNML;
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "nsPIDOMWindow.h" // for use in inline functions
|
||||
#include "nsPropertyTable.h" // for member
|
||||
#include "nsTHashtable.h" // for member
|
||||
#include "mozilla/dom/DirectionalityUtils.h"
|
||||
|
||||
class imgIRequest;
|
||||
class nsAString;
|
||||
@ -398,6 +399,10 @@ public:
|
||||
mBidiOptions = aBidiOptions;
|
||||
}
|
||||
|
||||
inline mozilla::directionality::Directionality GetDocumentDirectionality() {
|
||||
return mDirectionality;
|
||||
}
|
||||
|
||||
/**
|
||||
* Access HTTP header data (this may also get set from other
|
||||
* sources, like HTML META tags).
|
||||
@ -1853,6 +1858,9 @@ protected:
|
||||
// defined in nsBidiUtils.h
|
||||
PRUint32 mBidiOptions;
|
||||
|
||||
// The root directionality of this document.
|
||||
mozilla::directionality::Directionality mDirectionality;
|
||||
|
||||
nsCString mContentLanguage;
|
||||
private:
|
||||
nsCString mContentType;
|
||||
|
@ -145,8 +145,16 @@ enum {
|
||||
// Set if the node has had :hover selectors matched against it
|
||||
NODE_HAS_RELEVANT_HOVER_RULES = 0x00080000U,
|
||||
|
||||
// Set if the node has right-to-left directionality
|
||||
NODE_HAS_DIRECTION_RTL = 0x00100000U,
|
||||
|
||||
// Set if the node has left-to-right directionality
|
||||
NODE_HAS_DIRECTION_LTR = 0x00200000U,
|
||||
|
||||
NODE_ALL_DIRECTION_FLAGS = NODE_HAS_DIRECTION_LTR | NODE_HAS_DIRECTION_RTL,
|
||||
|
||||
// Remaining bits are node type specific.
|
||||
NODE_TYPE_SPECIFIC_BITS_OFFSET = 20
|
||||
NODE_TYPE_SPECIFIC_BITS_OFFSET = 22
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1279,6 +1287,8 @@ private:
|
||||
NodeIsContent,
|
||||
// Set if the node has animations or transitions
|
||||
ElementHasAnimations,
|
||||
// Set if node has a dir attribute with a valid value (ltr or rtl)
|
||||
NodeHasValidDirAttribute,
|
||||
// Guard value
|
||||
BooleanFlagCount
|
||||
};
|
||||
@ -1346,6 +1356,9 @@ public:
|
||||
void ClearPointerLock() { ClearBoolFlag(ElementHasPointerLock); }
|
||||
bool MayHaveAnimations() { return GetBoolFlag(ElementHasAnimations); }
|
||||
void SetMayHaveAnimations() { SetBoolFlag(ElementHasAnimations); }
|
||||
void SetHasValidDir() { SetBoolFlag(NodeHasValidDirAttribute); }
|
||||
void ClearHasValidDir() { ClearBoolFlag(NodeHasValidDirAttribute); }
|
||||
bool HasValidDir() const { return GetBoolFlag(NodeHasValidDirAttribute); }
|
||||
protected:
|
||||
void SetParentIsContent(bool aValue) { SetBoolFlag(ParentIsContent, aValue); }
|
||||
void SetInDocument() { SetBoolFlag(IsInDocument); }
|
||||
|
78
content/base/src/DirectionalityUtils.cpp
Normal file
78
content/base/src/DirectionalityUtils.cpp
Normal file
@ -0,0 +1,78 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 sw=2 et tw=78: */
|
||||
/* 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/DirectionalityUtils.h"
|
||||
#include "nsINode.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "nsIDOMNodeFilter.h"
|
||||
#include "nsTreeWalker.h"
|
||||
#include "nsIDOMHTMLDocument.h"
|
||||
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace directionality {
|
||||
|
||||
typedef mozilla::dom::Element Element;
|
||||
|
||||
Directionality
|
||||
RecomputeDirectionality(Element* aElement, bool aNotify)
|
||||
{
|
||||
Directionality dir = eDir_LTR;
|
||||
|
||||
if (aElement->HasValidDir()) {
|
||||
dir = aElement->GetDirectionality();
|
||||
} else {
|
||||
Element* parent = aElement->GetElementParent();
|
||||
if (parent) {
|
||||
// If the element doesn't have an explicit dir attribute with a valid
|
||||
// value, the directionality is the same as the parent element (but
|
||||
// don't propagate the parent directionality if it isn't set yet).
|
||||
Directionality parentDir = parent->GetDirectionality();
|
||||
if (parentDir != eDir_NotSet) {
|
||||
dir = parentDir;
|
||||
}
|
||||
} else {
|
||||
// If there is no parent element, the directionality is the same as the
|
||||
// document direction.
|
||||
Directionality documentDir =
|
||||
aElement->OwnerDoc()->GetDocumentDirectionality();
|
||||
if (documentDir != eDir_NotSet) {
|
||||
dir = documentDir;
|
||||
}
|
||||
}
|
||||
|
||||
aElement->SetDirectionality(dir, aNotify);
|
||||
}
|
||||
return dir;
|
||||
}
|
||||
|
||||
void
|
||||
SetDirectionalityOnDescendants(Element* aElement, Directionality aDir,
|
||||
bool aNotify)
|
||||
{
|
||||
for (nsIContent* child = aElement->GetFirstChild(); child; ) {
|
||||
if (!child->IsElement()) {
|
||||
child = child->GetNextNode(aElement);
|
||||
continue;
|
||||
}
|
||||
|
||||
Element* element = child->AsElement();
|
||||
if (element->HasValidDir()) {
|
||||
child = child->GetNextNonChildNode(aElement);
|
||||
continue;
|
||||
}
|
||||
element->SetDirectionality(aDir, aNotify);
|
||||
child = child->GetNextNode(aElement);
|
||||
}
|
||||
}
|
||||
|
||||
} // end namespace directionality
|
||||
|
||||
} // end namespace mozilla
|
||||
|
@ -15,7 +15,6 @@ LIBRARY_NAME = gkconbase_s
|
||||
LIBXUL_LIBRARY = 1
|
||||
|
||||
|
||||
|
||||
EXPORTS = \
|
||||
nsAtomListUtils.h \
|
||||
nsAttrName.h \
|
||||
@ -53,6 +52,7 @@ LOCAL_INCLUDES = \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = \
|
||||
DirectionalityUtils.cpp \
|
||||
nsAtomListUtils.cpp \
|
||||
nsAttrAndChildArray.cpp \
|
||||
nsAttrValue.cpp \
|
||||
|
@ -1199,8 +1199,8 @@ nsContentSubtreeIterator::Init(nsIDOMRange* aRange)
|
||||
PRInt32 endOffset = mRange->EndOffset();
|
||||
MOZ_ASSERT(mCommonParent && startParent && endParent);
|
||||
// Bug 767169
|
||||
MOZ_ASSERT(startOffset <= startParent->Length() &&
|
||||
endOffset <= endParent->Length());
|
||||
MOZ_ASSERT(PRUint32(startOffset) <= startParent->Length() &&
|
||||
PRUint32(endOffset) <= endParent->Length());
|
||||
|
||||
// short circuit when start node == end node
|
||||
if (startParent == endParent) {
|
||||
|
@ -57,7 +57,6 @@ private:
|
||||
nsCOMPtr<nsIURI> mBaseURI;
|
||||
nsWeakPtr mScriptHandlingObject;
|
||||
|
||||
bool mLoopingForSyncLoad;
|
||||
bool mAttemptedInit;
|
||||
};
|
||||
|
||||
|
@ -91,6 +91,7 @@
|
||||
#include "nsXMLEventsManager.h"
|
||||
|
||||
#include "nsBidiUtils.h"
|
||||
#include "mozilla/dom/DirectionalityUtils.h"
|
||||
|
||||
#include "nsIDOMUserDataHandler.h"
|
||||
#include "nsIDOMXPathEvaluator.h"
|
||||
@ -170,6 +171,7 @@
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla::directionality;
|
||||
|
||||
typedef nsTArray<Link*> LinkArray;
|
||||
|
||||
@ -1510,6 +1512,7 @@ nsIDocument::nsIDocument()
|
||||
mAllowDNSPrefetch(true),
|
||||
mIsBeingUsedAsImage(false),
|
||||
mHasLinksToUpdate(false),
|
||||
mDirectionality(eDir_LTR),
|
||||
mPartID(0)
|
||||
{
|
||||
SetInDocument();
|
||||
@ -5583,6 +5586,15 @@ nsDocument::SetDir(const nsAString& aDirection)
|
||||
// No presentation; just set it on ourselves
|
||||
SetBidiOptions(options);
|
||||
}
|
||||
Directionality dir = elt->mValue == IBMBIDI_TEXTDIRECTION_RTL ?
|
||||
eDir_RTL : eDir_LTR;
|
||||
SetDocumentDirectionality(dir);
|
||||
// Set the directionality of the root element and its descendants, if any
|
||||
Element* rootElement = GetRootElement();
|
||||
if (rootElement) {
|
||||
rootElement->SetDirectionality(dir, true);
|
||||
SetDirectionalityOnDescendants(rootElement, dir);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -1048,6 +1048,12 @@ protected:
|
||||
nsIContent* GetFirstBaseNodeWithHref();
|
||||
nsresult SetFirstBaseNodeWithHref(nsIContent *node);
|
||||
|
||||
inline void
|
||||
SetDocumentDirectionality(mozilla::directionality::Directionality aDir)
|
||||
{
|
||||
mDirectionality = aDir;
|
||||
}
|
||||
|
||||
// Get the first <title> element with the given IsNodeOfType type, or
|
||||
// return null if there isn't one
|
||||
nsIContent* GetTitleContent(PRUint32 aNodeType);
|
||||
|
@ -808,9 +808,13 @@ nsFrameScriptExecutor::LoadFrameScriptInternal(const nsAString& aURL)
|
||||
nsCOMPtr<nsIInputStream> input;
|
||||
channel->Open(getter_AddRefs(input));
|
||||
nsString dataString;
|
||||
PRUint32 avail = 0;
|
||||
if (input && NS_SUCCEEDED(input->Available(&avail)) && avail) {
|
||||
PRUint64 avail64 = 0;
|
||||
if (input && NS_SUCCEEDED(input->Available(&avail64)) && avail64) {
|
||||
if (avail64 > PR_UINT32_MAX) {
|
||||
return;
|
||||
}
|
||||
nsCString buffer;
|
||||
PRUint32 avail = (PRUint32)NS_MIN(avail64, (PRUint64)PR_UINT32_MAX);
|
||||
if (NS_FAILED(NS_ReadInputStreamToString(input, buffer, avail))) {
|
||||
return;
|
||||
}
|
||||
|
@ -51,6 +51,7 @@
|
||||
#include "nsIDOMMutationEvent.h"
|
||||
#include "nsMutationEvent.h"
|
||||
#include "nsNodeUtils.h"
|
||||
#include "mozilla/dom/DirectionalityUtils.h"
|
||||
#include "nsDocument.h"
|
||||
#include "nsAttrValueOrString.h"
|
||||
#ifdef MOZ_XUL
|
||||
@ -128,6 +129,7 @@
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla::directionality;
|
||||
|
||||
nsEventStates
|
||||
Element::IntrinsicState() const
|
||||
@ -1358,6 +1360,13 @@ nsGenericElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
SetSubtreeRootPointer(aParent->SubtreeRoot());
|
||||
}
|
||||
|
||||
// This has to be here, rather than in nsGenericHTMLElement::BindToTree,
|
||||
// because it has to happen after updating the parent pointer, but before
|
||||
// recursively binding the kids.
|
||||
if (IsHTML()) {
|
||||
RecomputeDirectionality(this, false);
|
||||
}
|
||||
|
||||
// If NODE_FORCE_XBL_BINDINGS was set we might have anonymous children
|
||||
// that also need to be told that they are moving.
|
||||
nsresult rv;
|
||||
@ -1543,6 +1552,13 @@ nsGenericElement::UnbindFromTree(bool aDeep, bool aNullParent)
|
||||
}
|
||||
}
|
||||
|
||||
// This has to be here, rather than in nsGenericHTMLElement::UnbindFromTree,
|
||||
// because it has to happen after unsetting the parent pointer, but before
|
||||
// recursively unbinding the kids.
|
||||
if (IsHTML()) {
|
||||
RecomputeDirectionality(this, false);
|
||||
}
|
||||
|
||||
if (aDeep) {
|
||||
// Do the kids. Don't call GetChildCount() here since that'll force
|
||||
// XUL to generate template children, which there is no need for since
|
||||
|
@ -270,6 +270,7 @@ GK_ATOM(dialog, "dialog")
|
||||
GK_ATOM(difference, "difference")
|
||||
GK_ATOM(digit, "digit")
|
||||
GK_ATOM(dir, "dir")
|
||||
GK_ATOM(directionality, "directionality")
|
||||
GK_ATOM(disableOutputEscaping, "disable-output-escaping")
|
||||
GK_ATOM(disabled, "disabled")
|
||||
GK_ATOM(display, "display")
|
||||
@ -719,6 +720,7 @@ GK_ATOM(ontransitionend, "ontransitionend")
|
||||
GK_ATOM(onunderflow, "onunderflow")
|
||||
GK_ATOM(onunload, "onunload")
|
||||
GK_ATOM(onupgradeneeded, "onupgradeneeded")
|
||||
GK_ATOM(onwheel, "onwheel")
|
||||
GK_ATOM(open, "open")
|
||||
GK_ATOM(optgroup, "optgroup")
|
||||
GK_ATOM(optimum, "optimum")
|
||||
|
@ -81,6 +81,16 @@ static PRLogModuleInfo* gObjectLog = PR_NewLogModule("objlc");
|
||||
#define LOG(args) PR_LOG(gObjectLog, PR_LOG_DEBUG, args)
|
||||
#define LOG_ENABLED() PR_LOG_TEST(gObjectLog, PR_LOG_DEBUG)
|
||||
|
||||
static bool
|
||||
InActiveDocument(nsIContent *aContent)
|
||||
{
|
||||
if (!aContent->IsInDoc()) {
|
||||
return false;
|
||||
}
|
||||
nsIDocument *doc = aContent->OwnerDoc();
|
||||
return (doc && doc->IsActive());
|
||||
}
|
||||
|
||||
///
|
||||
/// Runnables and helper classes
|
||||
///
|
||||
@ -137,7 +147,7 @@ InDocCheckEvent::Run()
|
||||
nsCOMPtr<nsIContent> content =
|
||||
do_QueryInterface(static_cast<nsIImageLoadingContent *>(objLC));
|
||||
|
||||
if (!content->IsInDoc()) {
|
||||
if (!InActiveDocument(content)) {
|
||||
nsObjectLoadingContent *objLC =
|
||||
static_cast<nsObjectLoadingContent *>(mContent.get());
|
||||
objLC->UnloadObject();
|
||||
@ -556,21 +566,30 @@ nsObjectLoadingContent::IsSupportedDocument(const nsCString& aMimeType)
|
||||
do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
|
||||
NS_ASSERTION(thisContent, "must be a content");
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIWebNavigationInfo> info(
|
||||
do_GetService(NS_WEBNAVIGATION_INFO_CONTRACTID, &rv));
|
||||
PRUint32 supported;
|
||||
if (info) {
|
||||
do_GetService(NS_WEBNAVIGATION_INFO_CONTRACTID));
|
||||
if (!info) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIWebNavigation> webNav;
|
||||
nsIDocument* currentDoc = thisContent->GetCurrentDoc();
|
||||
if (currentDoc) {
|
||||
webNav = do_GetInterface(currentDoc->GetScriptGlobalObject());
|
||||
}
|
||||
rv = info->IsTypeSupported(aMimeType, webNav, &supported);
|
||||
|
||||
PRUint32 supported;
|
||||
nsresult rv = info->IsTypeSupported(aMimeType, webNav, &supported);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (supported != nsIWebNavigationInfo::UNSUPPORTED) {
|
||||
// Don't want to support plugins as documents
|
||||
return supported != nsIWebNavigationInfo::PLUGIN;
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
if (supported == nsIWebNavigationInfo::UNSUPPORTED) {
|
||||
// Try a stream converter
|
||||
// NOTE: We treat any type we can convert from as a supported type. If a
|
||||
// type is not actually supported, the URI loader will detect that and
|
||||
@ -584,13 +603,6 @@ nsObjectLoadingContent::IsSupportedDocument(const nsCString& aMimeType)
|
||||
return NS_SUCCEEDED(rv) && canConvert;
|
||||
}
|
||||
|
||||
// Don't want to support plugins as documents
|
||||
return supported != nsIWebNavigationInfo::PLUGIN;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsObjectLoadingContent::BindToTree(nsIDocument* aDocument,
|
||||
nsIContent* /*aParent*/,
|
||||
@ -612,7 +624,7 @@ nsObjectLoadingContent::UnbindFromTree(bool /*aDeep*/, bool /*aNullParent*/)
|
||||
nsIDocument* ownerDoc = thisContent->OwnerDoc();
|
||||
ownerDoc->RemovePlugin(this);
|
||||
|
||||
if (mType == eType_Plugin) {
|
||||
if (mType == eType_Plugin && mInstanceOwner) {
|
||||
// we'll let the plugin continue to run at least until we get back to
|
||||
// the event loop. If we get back to the event loop and the node
|
||||
// has still not been added back to the document then we tear down the
|
||||
@ -624,6 +636,7 @@ nsObjectLoadingContent::UnbindFromTree(bool /*aDeep*/, bool /*aNullParent*/)
|
||||
appShell->RunInStableState(event);
|
||||
}
|
||||
} else {
|
||||
// Reset state and clear pending events
|
||||
/// XXX(johns): The implementation for GenericFrame notes that ideally we
|
||||
/// would keep the docshell around, but trash the frameloader
|
||||
UnloadObject();
|
||||
@ -694,7 +707,7 @@ nsObjectLoadingContent::InstantiatePluginInstance()
|
||||
if (!doc) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
if (!doc->IsActive()) {
|
||||
if (!InActiveDocument(thisContent)) {
|
||||
NS_ERROR("Shouldn't be calling "
|
||||
"InstantiatePluginInstance in an inactive document");
|
||||
return NS_ERROR_FAILURE;
|
||||
@ -1471,6 +1484,12 @@ nsObjectLoadingContent::LoadObject(bool aNotify,
|
||||
nsIDocument* doc = thisContent->OwnerDoc();
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
// Sanity check
|
||||
if (!InActiveDocument(thisContent)) {
|
||||
NS_NOTREACHED("LoadObject called while not bound to an active document");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
// XXX(johns): In these cases, we refuse to touch our content and just
|
||||
// remain unloaded, as per legacy behavior. It would make more sense to
|
||||
// load fallback content initially and refuse to ever change state again.
|
||||
@ -1478,12 +1497,6 @@ nsObjectLoadingContent::LoadObject(bool aNotify,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Sanity check
|
||||
if (!thisContent->IsInDoc()) {
|
||||
NS_NOTREACHED("LoadObject called while not bound to a document");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
LOG(("OBJLC [%p]: LoadObject called, notify %u, forceload %u, channel %p",
|
||||
this, aNotify, aForceLoad, aLoadingChannel));
|
||||
|
||||
@ -1970,7 +1983,7 @@ nsObjectLoadingContent::NotifyStateChanged(ObjectType aOldType,
|
||||
|
||||
if (newState != aOldState) {
|
||||
// This will trigger frame construction
|
||||
NS_ASSERTION(thisContent->IsInDoc(), "Something is confused");
|
||||
NS_ASSERTION(InActiveDocument(thisContent), "Something is confused");
|
||||
nsEventStates changedBits = aOldState ^ newState;
|
||||
|
||||
{
|
||||
@ -2151,10 +2164,10 @@ nsObjectLoadingContent::SyncStartPluginInstance()
|
||||
"Must be able to run script in order to instantiate a plugin instance!");
|
||||
|
||||
// Don't even attempt to start an instance unless the content is in
|
||||
// the document.
|
||||
// the document and active
|
||||
nsCOMPtr<nsIContent> thisContent =
|
||||
do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
|
||||
if (!thisContent->IsInDoc()) {
|
||||
if (!InActiveDocument(thisContent)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -352,9 +352,9 @@ nsSyncLoadService::PushSyncStreamToListener(nsIInputStream* aIn,
|
||||
// Load
|
||||
rv = aListener->OnStartRequest(aChannel, nullptr);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
PRUint32 sourceOffset = 0;
|
||||
PRUint64 sourceOffset = 0;
|
||||
while (1) {
|
||||
PRUint32 readCount = 0;
|
||||
PRUint64 readCount = 0;
|
||||
rv = aIn->Available(&readCount);
|
||||
if (NS_FAILED(rv) || !readCount) {
|
||||
if (rv == NS_BASE_STREAM_CLOSED) {
|
||||
@ -364,8 +364,12 @@ nsSyncLoadService::PushSyncStreamToListener(nsIInputStream* aIn,
|
||||
break;
|
||||
}
|
||||
|
||||
if (readCount > PR_UINT32_MAX)
|
||||
readCount = PR_UINT32_MAX;
|
||||
|
||||
rv = aListener->OnDataAvailable(aChannel, nullptr, aIn,
|
||||
sourceOffset, readCount);
|
||||
(PRUint32)NS_MIN(sourceOffset, (PRUint64)PR_UINT32_MAX),
|
||||
(PRUint32)readCount);
|
||||
if (NS_FAILED(rv)) {
|
||||
break;
|
||||
}
|
||||
|
@ -2962,7 +2962,7 @@ nsXMLHttpRequest::Send(nsIVariant* aVariant, const Nullable<RequestBody>& aBody)
|
||||
}
|
||||
|
||||
mUploadComplete = false;
|
||||
PRUint32 uploadTotal = 0;
|
||||
PRUint64 uploadTotal = 0;
|
||||
postDataStream->Available(&uploadTotal);
|
||||
mUploadTotal = uploadTotal;
|
||||
|
||||
|
@ -381,6 +381,8 @@ MOCHITEST_FILES_B = \
|
||||
test_bug562652.html \
|
||||
test_bug562137.html \
|
||||
file_bug562137.txt \
|
||||
test_bug562169-1.html \
|
||||
test_bug562169-2.html \
|
||||
test_bug548193.html \
|
||||
file_bug548193.sjs \
|
||||
test_html_colors_quirks.html \
|
||||
|
44
content/base/test/test_bug562169-1.html
Normal file
44
content/base/test/test_bug562169-1.html
Normal file
@ -0,0 +1,44 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=562169
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 562169</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=562169">Mozilla Bug 562169</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
<div dir="rtl" id="z"></div>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 562169 **/
|
||||
/** Test that adding an child to an element with dir="rtl" makes the
|
||||
child have rtl directionality, and removing the child makes it
|
||||
go back to ltr directionality **/
|
||||
|
||||
function checkSelector(element, expectedDir, expectedChild)
|
||||
{
|
||||
ok(element.querySelector(":dir("+expectedDir+")") == expectedChild,
|
||||
"direction should be " + expectedDir);
|
||||
}
|
||||
|
||||
var x = document.createElement("div");
|
||||
var y = document.createElement("div");
|
||||
x.appendChild(y);
|
||||
checkSelector(x, "ltr", y);
|
||||
$(z).appendChild(x);
|
||||
checkSelector(x, "rtl", y);
|
||||
$(z).removeChild(x);
|
||||
checkSelector(x, "ltr", y);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
29
content/base/test/test_bug562169-2.html
Normal file
29
content/base/test/test_bug562169-2.html
Normal file
@ -0,0 +1,29 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=562169
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 562169</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=562169">Mozilla Bug 562169</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 562169 **/
|
||||
/** Test that a newly created element has ltr directionality **/
|
||||
|
||||
ok(document.createElement("div").mozMatchesSelector(":dir(ltr)"),
|
||||
"Element should be ltr on creation");
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -1099,6 +1099,7 @@ protected:
|
||||
bool mMinCapability;
|
||||
bool mDisableExtensions;
|
||||
bool mHasRobustness;
|
||||
bool mIsMesa;
|
||||
|
||||
template<typename WebGLObjectType>
|
||||
void DeleteWebGLObjectsArray(nsTArray<WebGLObjectType>& array);
|
||||
@ -2324,6 +2325,24 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t UpperBoundNumSamplerUniforms() {
|
||||
size_t numSamplerUniforms = 0;
|
||||
for (size_t i = 0; i < mAttachedShaders.Length(); ++i) {
|
||||
const WebGLShader *shader = mAttachedShaders[i];
|
||||
if (!shader)
|
||||
continue;
|
||||
for (size_t j = 0; j < shader->mUniformInfos.Length(); ++j) {
|
||||
WebGLUniformInfo u = shader->mUniformInfos[j];
|
||||
if (u.type == SH_SAMPLER_2D ||
|
||||
u.type == SH_SAMPLER_CUBE)
|
||||
{
|
||||
numSamplerUniforms += u.arraySize;
|
||||
}
|
||||
}
|
||||
}
|
||||
return numSamplerUniforms;
|
||||
}
|
||||
|
||||
bool NextGeneration()
|
||||
{
|
||||
if (!(mGeneration + 1).isValid())
|
||||
|
@ -3706,6 +3706,17 @@ WebGLContext::LinkProgram(WebGLProgram *program, ErrorResult& rv)
|
||||
return;
|
||||
}
|
||||
|
||||
// bug 777028
|
||||
// Mesa can't handle more than 16 samplers per program, counting each array entry.
|
||||
if (mIsMesa) {
|
||||
if (program->UpperBoundNumSamplerUniforms() > 16) {
|
||||
GenerateWarning("Programs with more than 16 samplers are disallowed on Mesa drivers "
|
||||
"to avoid a Mesa crasher.");
|
||||
program->SetLinkStatus(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
GLint ok;
|
||||
if (gl->WorkAroundDriverBugs() &&
|
||||
program->HasBadShaderAttached())
|
||||
@ -5029,7 +5040,6 @@ WebGLContext::CompileShader(WebGLShader *shader)
|
||||
nsAutoArrayPtr<char> uniform_name(new char[uniform_max_length+1]);
|
||||
nsAutoArrayPtr<char> mapped_name(new char[mapped_max_length+1]);
|
||||
|
||||
|
||||
for (int i = 0; i < num_uniforms; i++) {
|
||||
int length, size;
|
||||
ShDataType type;
|
||||
|
@ -771,6 +771,9 @@ WebGLContext::InitAndValidateGL()
|
||||
}
|
||||
#endif
|
||||
|
||||
// Mesa can only be detected with the GL_VERSION string, of the form "2.1 Mesa 7.11.0"
|
||||
mIsMesa = strstr((const char *)(gl->fGetString(LOCAL_GL_VERSION)), "Mesa");
|
||||
|
||||
// notice that the point of calling GetAndClearError here is not only to check for error,
|
||||
// it is also to reset the error flags so that a subsequent WebGL getError call will give the correct result.
|
||||
error = gl->GetAndClearError();
|
||||
|
@ -4316,8 +4316,11 @@ nsCanvasRenderingContext2D::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
|
||||
CanvasLayer *aOldLayer,
|
||||
LayerManager *aManager)
|
||||
{
|
||||
if (!EnsureSurface())
|
||||
// If we don't have anything to draw, don't bother.
|
||||
if (!mValid || !mSurface || mSurface->CairoStatus() || !mThebes ||
|
||||
!mSurfaceCreated) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!mResetLayer && aOldLayer) {
|
||||
CanvasRenderingContext2DUserData* userData =
|
||||
|
@ -20,7 +20,8 @@ function IsD2DEnabled() {
|
||||
}
|
||||
|
||||
function IsLinux() {
|
||||
return navigator.platform.indexOf("Linux") == 0;
|
||||
return navigator.platform.indexOf("Linux") == 0 &&
|
||||
navigator.appVersion.indexOf("Android") == -1;
|
||||
}
|
||||
|
||||
function IsMacOSX10_5orOlder() {
|
||||
|
@ -600,6 +600,10 @@ NON_IDL_EVENT(underflow,
|
||||
NS_SCROLLPORT_UNDERFLOW,
|
||||
EventNameType_XUL,
|
||||
NS_EVENT_NULL)
|
||||
NON_IDL_EVENT(wheel,
|
||||
NS_WHEEL_WHEEL,
|
||||
EventNameType_XUL,
|
||||
NS_WHEEL_EVENT)
|
||||
|
||||
// Various SVG events
|
||||
NON_IDL_EVENT(SVGLoad,
|
||||
|
@ -248,11 +248,17 @@ private:
|
||||
#define NS_EVENT_STATE_VULNERABLE_NO_UPDATE NS_DEFINE_EVENT_STATE_MACRO(41)
|
||||
// Platform does not support plugin content (some mobile platforms)
|
||||
#define NS_EVENT_STATE_TYPE_UNSUPPORTED_PLATFORM NS_DEFINE_EVENT_STATE_MACRO(42)
|
||||
// Element is ltr (for :dir pseudo-class)
|
||||
#define NS_EVENT_STATE_LTR NS_DEFINE_EVENT_STATE_MACRO(43)
|
||||
// Element is rtl (for :dir pseudo-class)
|
||||
#define NS_EVENT_STATE_RTL NS_DEFINE_EVENT_STATE_MACRO(44)
|
||||
|
||||
/**
|
||||
* NOTE: do not go over 63 without updating nsEventStates::InternalType!
|
||||
*/
|
||||
|
||||
#define DIRECTION_STATES (NS_EVENT_STATE_LTR | NS_EVENT_STATE_RTL)
|
||||
|
||||
#define ESM_MANAGED_STATES (NS_EVENT_STATE_ACTIVE | NS_EVENT_STATE_FOCUS | \
|
||||
NS_EVENT_STATE_HOVER | NS_EVENT_STATE_DRAGOVER | \
|
||||
NS_EVENT_STATE_URLTARGET | NS_EVENT_STATE_FOCUSRING | \
|
||||
|
176
content/events/src/DOMWheelEvent.cpp
Normal file
176
content/events/src/DOMWheelEvent.cpp
Normal file
@ -0,0 +1,176 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "DOMWheelEvent.h"
|
||||
#include "nsGUIEvent.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "DictionaryHelpers.h"
|
||||
#include "nsDOMClassInfoID.h"
|
||||
|
||||
DOMCI_DATA(WheelEvent, mozilla::dom::DOMWheelEvent)
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
DOMWheelEvent::DOMWheelEvent(nsPresContext* aPresContext,
|
||||
widget::WheelEvent* aWheelEvent)
|
||||
: nsDOMMouseEvent(aPresContext, aWheelEvent ? aWheelEvent :
|
||||
new widget::WheelEvent(false, 0, nullptr))
|
||||
{
|
||||
if (aWheelEvent) {
|
||||
mEventIsInternal = false;
|
||||
} else {
|
||||
mEventIsInternal = true;
|
||||
mEvent->time = PR_Now();
|
||||
mEvent->refPoint.x = mEvent->refPoint.y = 0;
|
||||
static_cast<widget::WheelEvent*>(mEvent)->inputSource =
|
||||
nsIDOMMouseEvent::MOZ_SOURCE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
DOMWheelEvent::~DOMWheelEvent()
|
||||
{
|
||||
if (mEventIsInternal && mEvent) {
|
||||
MOZ_ASSERT(mEvent->eventStructType == NS_WHEEL_EVENT,
|
||||
"The mEvent must be WheelEvent");
|
||||
delete static_cast<widget::WheelEvent*>(mEvent);
|
||||
mEvent = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(DOMWheelEvent, nsDOMMouseEvent)
|
||||
NS_IMPL_RELEASE_INHERITED(DOMWheelEvent, nsDOMMouseEvent)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(DOMWheelEvent)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMWheelEvent)
|
||||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WheelEvent)
|
||||
NS_INTERFACE_MAP_END_INHERITING(nsDOMMouseEvent)
|
||||
|
||||
NS_IMETHODIMP
|
||||
DOMWheelEvent::InitWheelEvent(const nsAString & aType,
|
||||
bool aCanBubble,
|
||||
bool aCancelable,
|
||||
nsIDOMWindow *aView,
|
||||
PRInt32 aDetail,
|
||||
PRInt32 aScreenX,
|
||||
PRInt32 aScreenY,
|
||||
PRInt32 aClientX,
|
||||
PRInt32 aClientY,
|
||||
PRUint16 aButton,
|
||||
nsIDOMEventTarget *aRelatedTarget,
|
||||
const nsAString& aModifiersList,
|
||||
double aDeltaX,
|
||||
double aDeltaY,
|
||||
double aDeltaZ,
|
||||
PRUint32 aDeltaMode)
|
||||
{
|
||||
nsresult rv =
|
||||
nsDOMMouseEvent::InitMouseEvent(aType, aCanBubble, aCancelable, aView,
|
||||
aDetail, aScreenX, aScreenY,
|
||||
aClientX, aClientY, aButton,
|
||||
aRelatedTarget, aModifiersList);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
widget::WheelEvent* wheelEvent = static_cast<widget::WheelEvent*>(mEvent);
|
||||
wheelEvent->deltaX = aDeltaX;
|
||||
wheelEvent->deltaY = aDeltaY;
|
||||
wheelEvent->deltaZ = aDeltaZ;
|
||||
wheelEvent->deltaMode = aDeltaMode;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DOMWheelEvent::GetDeltaX(double* aDeltaX)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aDeltaX);
|
||||
|
||||
*aDeltaX = static_cast<widget::WheelEvent*>(mEvent)->deltaX;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DOMWheelEvent::GetDeltaY(double* aDeltaY)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aDeltaY);
|
||||
|
||||
*aDeltaY = static_cast<widget::WheelEvent*>(mEvent)->deltaY;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DOMWheelEvent::GetDeltaZ(double* aDeltaZ)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aDeltaZ);
|
||||
|
||||
*aDeltaZ = static_cast<widget::WheelEvent*>(mEvent)->deltaZ;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DOMWheelEvent::GetDeltaMode(PRUint32* aDeltaMode)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aDeltaMode);
|
||||
|
||||
*aDeltaMode = static_cast<widget::WheelEvent*>(mEvent)->deltaMode;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
DOMWheelEvent::InitFromCtor(const nsAString& aType,
|
||||
JSContext* aCx, jsval* aVal)
|
||||
{
|
||||
WheelEventInit d;
|
||||
nsresult rv = d.Init(aCx, aVal);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsAutoString modifierList;
|
||||
if (d.ctrlKey) {
|
||||
modifierList.AppendLiteral(NS_DOM_KEYNAME_CONTROL);
|
||||
}
|
||||
if (d.shiftKey) {
|
||||
if (!modifierList.IsEmpty()) {
|
||||
modifierList.AppendLiteral(" ");
|
||||
}
|
||||
modifierList.AppendLiteral(NS_DOM_KEYNAME_SHIFT);
|
||||
}
|
||||
if (d.altKey) {
|
||||
if (!modifierList.IsEmpty()) {
|
||||
modifierList.AppendLiteral(" ");
|
||||
}
|
||||
modifierList.AppendLiteral(NS_DOM_KEYNAME_ALT);
|
||||
}
|
||||
if (d.metaKey) {
|
||||
if (!modifierList.IsEmpty()) {
|
||||
modifierList.AppendLiteral(" ");
|
||||
}
|
||||
modifierList.AppendLiteral(NS_DOM_KEYNAME_META);
|
||||
}
|
||||
|
||||
rv = InitWheelEvent(aType, d.bubbles, d.cancelable,
|
||||
d.view, d.detail, d.screenX, d.screenY,
|
||||
d.clientX, d.clientY, d.button, d.relatedTarget,
|
||||
modifierList, d.deltaX, d.deltaY, d.deltaZ, d.deltaMode);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
static_cast<widget::WheelEvent*>(mEvent)->buttons = d.buttons;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
nsresult NS_NewDOMWheelEvent(nsIDOMEvent** aInstancePtrResult,
|
||||
nsPresContext* aPresContext,
|
||||
widget::WheelEvent *aEvent)
|
||||
{
|
||||
dom::DOMWheelEvent* it = new dom::DOMWheelEvent(aPresContext, aEvent);
|
||||
return CallQueryInterface(it, aInstancePtrResult);
|
||||
}
|
39
content/events/src/DOMWheelEvent.h
Normal file
39
content/events/src/DOMWheelEvent.h
Normal file
@ -0,0 +1,39 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_DOMWheelEvent_h__
|
||||
#define mozilla_dom_DOMWheelEvent_h__
|
||||
|
||||
#include "nsIDOMWheelEvent.h"
|
||||
#include "nsDOMMouseEvent.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class DOMWheelEvent : public nsDOMMouseEvent,
|
||||
public nsIDOMWheelEvent
|
||||
{
|
||||
public:
|
||||
DOMWheelEvent(nsPresContext* aPresContext,
|
||||
widget::WheelEvent* aWheelEvent);
|
||||
virtual ~DOMWheelEvent();
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// nsIDOMWheelEvent Interface
|
||||
NS_DECL_NSIDOMWHEELEVENT
|
||||
|
||||
// Forward to base class
|
||||
NS_FORWARD_TO_NSDOMMOUSEEVENT
|
||||
|
||||
virtual nsresult InitFromCtor(const nsAString& aType,
|
||||
JSContext* aCx, jsval* aVal);
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_DOMWheelEvent_h__
|
@ -13,6 +13,7 @@ include $(DEPTH)/config/autoconf.mk
|
||||
MODULE = content
|
||||
LIBRARY_NAME = gkconevents_s
|
||||
LIBXUL_LIBRARY = 1
|
||||
FAIL_ON_WARNINGS = 1
|
||||
|
||||
EXPORTS = \
|
||||
nsEventStateManager.h \
|
||||
@ -62,6 +63,7 @@ CPPSRCS = \
|
||||
nsDOMAnimationEvent.cpp \
|
||||
nsDOMTouchEvent.cpp \
|
||||
nsDOMCompositionEvent.cpp \
|
||||
DOMWheelEvent.cpp \
|
||||
$(NULL)
|
||||
|
||||
ifdef MOZ_B2G_RIL
|
||||
|
@ -52,7 +52,7 @@ static const char* const sEventNames[] = {
|
||||
"DOMNodeRemovedFromDocument", "DOMNodeInsertedIntoDocument",
|
||||
"DOMAttrModified", "DOMCharacterDataModified",
|
||||
"DOMActivate", "DOMFocusIn", "DOMFocusOut",
|
||||
"pageshow", "pagehide", "DOMMouseScroll", "MozMousePixelScroll",
|
||||
"pageshow", "pagehide", "DOMMouseScroll", "MozMousePixelScroll", "wheel",
|
||||
"offline", "online", "copy", "cut", "paste", "open", "message", "show",
|
||||
"SVGLoad", "SVGUnload", "SVGAbort", "SVGError", "SVGResize", "SVGScroll",
|
||||
"SVGZoom",
|
||||
@ -191,6 +191,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMEvent)
|
||||
switch (tmp->mEvent->eventStructType) {
|
||||
case NS_MOUSE_EVENT:
|
||||
case NS_MOUSE_SCROLL_EVENT:
|
||||
case NS_WHEEL_EVENT:
|
||||
case NS_SIMPLE_GESTURE_EVENT:
|
||||
case NS_MOZTOUCH_EVENT:
|
||||
static_cast<nsMouseEvent_base*>(tmp->mEvent)->relatedTarget = nullptr;
|
||||
@ -218,6 +219,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMEvent)
|
||||
switch (tmp->mEvent->eventStructType) {
|
||||
case NS_MOUSE_EVENT:
|
||||
case NS_MOUSE_SCROLL_EVENT:
|
||||
case NS_WHEEL_EVENT:
|
||||
case NS_SIMPLE_GESTURE_EVENT:
|
||||
case NS_MOZTOUCH_EVENT:
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mEvent->relatedTarget");
|
||||
@ -718,11 +720,10 @@ nsDOMEvent::DuplicatePrivateData()
|
||||
{
|
||||
nsMouseScrollEvent* mouseScrollEvent =
|
||||
new nsMouseScrollEvent(false, msg, nullptr);
|
||||
NS_ENSURE_TRUE(mouseScrollEvent, NS_ERROR_OUT_OF_MEMORY);
|
||||
isInputEvent = true;
|
||||
nsMouseScrollEvent* oldMouseScrollEvent =
|
||||
static_cast<nsMouseScrollEvent*>(mEvent);
|
||||
mouseScrollEvent->scrollFlags = oldMouseScrollEvent->scrollFlags;
|
||||
mouseScrollEvent->isHorizontal = oldMouseScrollEvent->isHorizontal;
|
||||
mouseScrollEvent->delta = oldMouseScrollEvent->delta;
|
||||
mouseScrollEvent->relatedTarget = oldMouseScrollEvent->relatedTarget;
|
||||
mouseScrollEvent->button = oldMouseScrollEvent->button;
|
||||
@ -732,6 +733,33 @@ nsDOMEvent::DuplicatePrivateData()
|
||||
newEvent = mouseScrollEvent;
|
||||
break;
|
||||
}
|
||||
case NS_WHEEL_EVENT:
|
||||
{
|
||||
widget::WheelEvent* wheelEvent =
|
||||
new widget::WheelEvent(false, msg, nullptr);
|
||||
isInputEvent = true;
|
||||
widget::WheelEvent* oldWheelEvent =
|
||||
static_cast<widget::WheelEvent*>(mEvent);
|
||||
wheelEvent->deltaX = oldWheelEvent->deltaX;
|
||||
wheelEvent->deltaY = oldWheelEvent->deltaY;
|
||||
wheelEvent->deltaZ = oldWheelEvent->deltaZ;
|
||||
wheelEvent->deltaMode = oldWheelEvent->deltaMode;
|
||||
wheelEvent->relatedTarget = oldWheelEvent->relatedTarget;
|
||||
wheelEvent->button = oldWheelEvent->button;
|
||||
wheelEvent->buttons = oldWheelEvent->buttons;
|
||||
wheelEvent->modifiers = oldWheelEvent->modifiers;
|
||||
wheelEvent->inputSource = oldWheelEvent->inputSource;
|
||||
wheelEvent->customizedByUserPrefs = oldWheelEvent->customizedByUserPrefs;
|
||||
wheelEvent->isMomentum = oldWheelEvent->isMomentum;
|
||||
wheelEvent->isPixelOnlyDevice = oldWheelEvent->isPixelOnlyDevice;
|
||||
wheelEvent->lineOrPageDeltaX = oldWheelEvent->lineOrPageDeltaX;
|
||||
wheelEvent->lineOrPageDeltaY = oldWheelEvent->lineOrPageDeltaY;
|
||||
wheelEvent->scrollType = oldWheelEvent->scrollType;
|
||||
wheelEvent->overflowDeltaX = oldWheelEvent->overflowDeltaX;
|
||||
wheelEvent->overflowDeltaY = oldWheelEvent->overflowDeltaY;
|
||||
newEvent = wheelEvent;
|
||||
break;
|
||||
}
|
||||
case NS_SCROLLPORT_EVENT:
|
||||
{
|
||||
newEvent = new nsScrollPortEvent(false, msg, nullptr);
|
||||
@ -1157,6 +1185,7 @@ nsDOMEvent::GetScreenCoords(nsPresContext* aPresContext,
|
||||
(aEvent->eventStructType != NS_MOUSE_EVENT &&
|
||||
aEvent->eventStructType != NS_POPUP_EVENT &&
|
||||
aEvent->eventStructType != NS_MOUSE_SCROLL_EVENT &&
|
||||
aEvent->eventStructType != NS_WHEEL_EVENT &&
|
||||
aEvent->eventStructType != NS_MOZTOUCH_EVENT &&
|
||||
aEvent->eventStructType != NS_TOUCH_EVENT &&
|
||||
aEvent->eventStructType != NS_DRAG_EVENT &&
|
||||
@ -1216,6 +1245,7 @@ nsDOMEvent::GetClientCoords(nsPresContext* aPresContext,
|
||||
(aEvent->eventStructType != NS_MOUSE_EVENT &&
|
||||
aEvent->eventStructType != NS_POPUP_EVENT &&
|
||||
aEvent->eventStructType != NS_MOUSE_SCROLL_EVENT &&
|
||||
aEvent->eventStructType != NS_WHEEL_EVENT &&
|
||||
aEvent->eventStructType != NS_MOZTOUCH_EVENT &&
|
||||
aEvent->eventStructType != NS_TOUCH_EVENT &&
|
||||
aEvent->eventStructType != NS_DRAG_EVENT &&
|
||||
@ -1390,6 +1420,8 @@ const char* nsDOMEvent::GetEventName(PRUint32 aEventType)
|
||||
return sEventNames[eDOMEvents_DOMMouseScroll];
|
||||
case NS_MOUSE_PIXEL_SCROLL:
|
||||
return sEventNames[eDOMEvents_MozMousePixelScroll];
|
||||
case NS_WHEEL_WHEEL:
|
||||
return sEventNames[eDOMEvents_wheel];
|
||||
case NS_OFFLINE:
|
||||
return sEventNames[eDOMEvents_offline];
|
||||
case NS_ONLINE:
|
||||
|
@ -102,6 +102,7 @@ public:
|
||||
eDOMEvents_pagehide,
|
||||
eDOMEvents_DOMMouseScroll,
|
||||
eDOMEvents_MozMousePixelScroll,
|
||||
eDOMEvents_wheel,
|
||||
eDOMEvents_offline,
|
||||
eDOMEvents_online,
|
||||
eDOMEvents_copy,
|
||||
|
@ -85,6 +85,7 @@ nsDOMMouseEvent::InitMouseEvent(const nsAString & aType, bool aCanBubble, bool a
|
||||
{
|
||||
case NS_MOUSE_EVENT:
|
||||
case NS_MOUSE_SCROLL_EVENT:
|
||||
case NS_WHEEL_EVENT:
|
||||
case NS_DRAG_EVENT:
|
||||
case NS_SIMPLE_GESTURE_EVENT:
|
||||
case NS_MOZTOUCH_EVENT:
|
||||
@ -139,6 +140,7 @@ nsDOMMouseEvent::InitMouseEvent(const nsAString& aType,
|
||||
switch(mEvent->eventStructType) {
|
||||
case NS_MOUSE_EVENT:
|
||||
case NS_MOUSE_SCROLL_EVENT:
|
||||
case NS_WHEEL_EVENT:
|
||||
case NS_DRAG_EVENT:
|
||||
case NS_SIMPLE_GESTURE_EVENT:
|
||||
case NS_MOZTOUCH_EVENT:
|
||||
@ -167,6 +169,7 @@ nsDOMMouseEvent::InitFromCtor(const nsAString& aType,
|
||||
switch(mEvent->eventStructType) {
|
||||
case NS_MOUSE_EVENT:
|
||||
case NS_MOUSE_SCROLL_EVENT:
|
||||
case NS_WHEEL_EVENT:
|
||||
case NS_DRAG_EVENT:
|
||||
case NS_SIMPLE_GESTURE_EVENT:
|
||||
case NS_MOZTOUCH_EVENT:
|
||||
@ -206,6 +209,7 @@ nsDOMMouseEvent::GetButton(PRUint16* aButton)
|
||||
{
|
||||
case NS_MOUSE_EVENT:
|
||||
case NS_MOUSE_SCROLL_EVENT:
|
||||
case NS_WHEEL_EVENT:
|
||||
case NS_DRAG_EVENT:
|
||||
case NS_SIMPLE_GESTURE_EVENT:
|
||||
case NS_MOZTOUCH_EVENT:
|
||||
@ -227,6 +231,7 @@ nsDOMMouseEvent::GetButtons(PRUint16* aButtons)
|
||||
{
|
||||
case NS_MOUSE_EVENT:
|
||||
case NS_MOUSE_SCROLL_EVENT:
|
||||
case NS_WHEEL_EVENT:
|
||||
case NS_DRAG_EVENT:
|
||||
case NS_SIMPLE_GESTURE_EVENT:
|
||||
case NS_MOZTOUCH_EVENT:
|
||||
@ -250,6 +255,7 @@ nsDOMMouseEvent::GetRelatedTarget(nsIDOMEventTarget** aRelatedTarget)
|
||||
{
|
||||
case NS_MOUSE_EVENT:
|
||||
case NS_MOUSE_SCROLL_EVENT:
|
||||
case NS_WHEEL_EVENT:
|
||||
case NS_DRAG_EVENT:
|
||||
case NS_SIMPLE_GESTURE_EVENT:
|
||||
case NS_MOZTOUCH_EVENT:
|
||||
|
@ -21,8 +21,7 @@ nsDOMMouseScrollEvent::nsDOMMouseScrollEvent(nsPresContext* aPresContext,
|
||||
}
|
||||
|
||||
if(mEvent->eventStructType == NS_MOUSE_SCROLL_EVENT) {
|
||||
nsMouseScrollEvent* mouseEvent = static_cast<nsMouseScrollEvent*>(mEvent);
|
||||
mDetail = mouseEvent->delta;
|
||||
mDetail = static_cast<nsMouseScrollEvent*>(mEvent)->delta;
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,9 +65,8 @@ nsDOMMouseScrollEvent::InitMouseScrollEvent(const nsAString & aType, bool aCanBu
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (mEvent->eventStructType == NS_MOUSE_SCROLL_EVENT) {
|
||||
static_cast<nsMouseScrollEvent*>(mEvent)->scrollFlags =
|
||||
(aAxis == HORIZONTAL_AXIS) ? nsMouseScrollEvent::kIsHorizontal
|
||||
: nsMouseScrollEvent::kIsVertical;
|
||||
static_cast<nsMouseScrollEvent*>(mEvent)->isHorizontal =
|
||||
(aAxis == HORIZONTAL_AXIS);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
@ -81,9 +79,9 @@ nsDOMMouseScrollEvent::GetAxis(PRInt32* aResult)
|
||||
NS_ENSURE_ARG_POINTER(aResult);
|
||||
|
||||
if (mEvent->eventStructType == NS_MOUSE_SCROLL_EVENT) {
|
||||
PRUint32 flags = static_cast<nsMouseScrollEvent*>(mEvent)->scrollFlags;
|
||||
*aResult = (flags & nsMouseScrollEvent::kIsHorizontal)
|
||||
? PRInt32(HORIZONTAL_AXIS) : PRInt32(VERTICAL_AXIS);
|
||||
*aResult = static_cast<nsMouseScrollEvent*>(mEvent)->isHorizontal ?
|
||||
static_cast<PRInt32>(HORIZONTAL_AXIS) :
|
||||
static_cast<PRInt32>(VERTICAL_AXIS);
|
||||
} else {
|
||||
*aResult = 0;
|
||||
}
|
||||
|
@ -97,7 +97,7 @@ protected:
|
||||
bool mPointsInitialized;
|
||||
};
|
||||
|
||||
class nsDOMTouchList : public nsIDOMTouchList
|
||||
class nsDOMTouchList MOZ_FINAL : public nsIDOMTouchList
|
||||
{
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
|
@ -114,6 +114,7 @@ nsDOMUIEvent::GetMovementPoint()
|
||||
(mEvent->eventStructType != NS_MOUSE_EVENT &&
|
||||
mEvent->eventStructType != NS_POPUP_EVENT &&
|
||||
mEvent->eventStructType != NS_MOUSE_SCROLL_EVENT &&
|
||||
mEvent->eventStructType != NS_WHEEL_EVENT &&
|
||||
mEvent->eventStructType != NS_MOZTOUCH_EVENT &&
|
||||
mEvent->eventStructType != NS_DRAG_EVENT &&
|
||||
mEvent->eventStructType != NS_SIMPLE_GESTURE_EVENT)) {
|
||||
@ -312,6 +313,7 @@ nsDOMUIEvent::GetLayerPoint()
|
||||
(mEvent->eventStructType != NS_MOUSE_EVENT &&
|
||||
mEvent->eventStructType != NS_POPUP_EVENT &&
|
||||
mEvent->eventStructType != NS_MOUSE_SCROLL_EVENT &&
|
||||
mEvent->eventStructType != NS_WHEEL_EVENT &&
|
||||
mEvent->eventStructType != NS_MOZTOUCH_EVENT &&
|
||||
mEvent->eventStructType != NS_TOUCH_EVENT &&
|
||||
mEvent->eventStructType != NS_DRAG_EVENT &&
|
||||
|
@ -39,6 +39,7 @@ public:
|
||||
(aEvent->eventStructType != NS_MOUSE_EVENT &&
|
||||
aEvent->eventStructType != NS_POPUP_EVENT &&
|
||||
aEvent->eventStructType != NS_MOUSE_SCROLL_EVENT &&
|
||||
aEvent->eventStructType != NS_WHEEL_EVENT &&
|
||||
aEvent->eventStructType != NS_MOZTOUCH_EVENT &&
|
||||
aEvent->eventStructType != NS_DRAG_EVENT &&
|
||||
aEvent->eventStructType != NS_SIMPLE_GESTURE_EVENT)) {
|
||||
@ -64,6 +65,7 @@ public:
|
||||
(aEvent->eventStructType != NS_MOUSE_EVENT &&
|
||||
aEvent->eventStructType != NS_POPUP_EVENT &&
|
||||
aEvent->eventStructType != NS_MOUSE_SCROLL_EVENT &&
|
||||
aEvent->eventStructType != NS_WHEEL_EVENT &&
|
||||
aEvent->eventStructType != NS_MOZTOUCH_EVENT &&
|
||||
aEvent->eventStructType != NS_DRAG_EVENT &&
|
||||
aEvent->eventStructType != NS_SIMPLE_GESTURE_EVENT) ||
|
||||
|
@ -22,6 +22,8 @@
|
||||
#include "sampler.h"
|
||||
#include "GeneratedEvents.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
#define NS_TARGET_CHAIN_FORCE_CONTENT_DISPATCH (1 << 0)
|
||||
#define NS_TARGET_CHAIN_WANTS_WILL_HANDLE_EVENT (1 << 1)
|
||||
#define NS_TARGET_CHAIN_MAY_HAVE_MANAGER (1 << 2)
|
||||
@ -734,6 +736,9 @@ nsEventDispatcher::CreateEvent(nsPresContext* aPresContext,
|
||||
case NS_MOUSE_SCROLL_EVENT:
|
||||
return NS_NewDOMMouseScrollEvent(aDOMEvent, aPresContext,
|
||||
static_cast<nsInputEvent*>(aEvent));
|
||||
case NS_WHEEL_EVENT:
|
||||
return NS_NewDOMWheelEvent(aDOMEvent, aPresContext,
|
||||
static_cast<widget::WheelEvent*>(aEvent));
|
||||
case NS_DRAG_EVENT:
|
||||
return NS_NewDOMDragEvent(aDOMEvent, aPresContext,
|
||||
static_cast<nsDragEvent*>(aEvent));
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -86,6 +86,14 @@ public:
|
||||
nsIFrame* aTargetFrame,
|
||||
nsEventStatus* aStatus);
|
||||
|
||||
/**
|
||||
* DispatchLegacyMouseScrollEvents() dispatches NS_MOUSE_SCROLL event and
|
||||
* NS_MOUSE_PIXEL_SCROLL event for compatiblity with old Gecko.
|
||||
*/
|
||||
void DispatchLegacyMouseScrollEvents(nsIFrame* aTargetFrame,
|
||||
mozilla::widget::WheelEvent* aEvent,
|
||||
nsEventStatus* aStatus);
|
||||
|
||||
void NotifyDestroyPresContext(nsPresContext* aPresContext);
|
||||
void SetPresContext(nsPresContext* aPresContext);
|
||||
void ClearFrameRefs(nsIFrame* aFrame);
|
||||
@ -317,67 +325,241 @@ protected:
|
||||
bool IsShellVisible(nsIDocShell* aShell);
|
||||
|
||||
// These functions are for mousewheel and pixel scrolling
|
||||
void SendLineScrollEvent(nsIFrame* aTargetFrame,
|
||||
nsMouseScrollEvent* aEvent,
|
||||
nsPresContext* aPresContext,
|
||||
nsEventStatus* aStatus,
|
||||
PRInt32 aNumLines);
|
||||
void SendPixelScrollEvent(nsIFrame* aTargetFrame,
|
||||
nsMouseScrollEvent* aEvent,
|
||||
nsPresContext* aPresContext,
|
||||
nsEventStatus* aStatus);
|
||||
|
||||
class WheelPrefs
|
||||
{
|
||||
public:
|
||||
static WheelPrefs* GetInstance();
|
||||
static void Shutdown();
|
||||
|
||||
/**
|
||||
* @param aQueryEvent If you set vailid pointer for this, DoScrollText()
|
||||
* computes the line-height and page size of current
|
||||
* mouse wheel scroll target and sets it to the event.
|
||||
* And then, this method does NOT scroll any scrollable
|
||||
* elements. I.e., you can just query the scroll target
|
||||
* information.
|
||||
* ApplyUserPrefsToDelta() overrides the wheel event's delta values with
|
||||
* user prefs.
|
||||
*/
|
||||
nsresult DoScrollText(nsIFrame* aTargetFrame,
|
||||
nsMouseScrollEvent* aMouseEvent,
|
||||
nsIScrollableFrame::ScrollUnit aScrollQuantity,
|
||||
bool aAllowScrollSpeedOverride,
|
||||
nsQueryContentEvent* aQueryEvent = nullptr,
|
||||
nsIAtom *aOrigin = nullptr);
|
||||
void ApplyUserPrefsToDelta(mozilla::widget::WheelEvent* aEvent);
|
||||
|
||||
/**
|
||||
* If ApplyUserPrefsToDelta() changed the delta values with customized
|
||||
* prefs, the overflowDelta values would be inflated.
|
||||
* CancelApplyingUserPrefsFromOverflowDelta() cancels the inflation.
|
||||
*/
|
||||
void CancelApplyingUserPrefsFromOverflowDelta(
|
||||
mozilla::widget::WheelEvent* aEvent);
|
||||
|
||||
/**
|
||||
* Computes the default action for the aEvent with the prefs.
|
||||
*/
|
||||
enum Action
|
||||
{
|
||||
ACTION_NONE = 0,
|
||||
ACTION_SCROLL,
|
||||
ACTION_HISTORY,
|
||||
ACTION_ZOOM,
|
||||
ACTION_LAST = ACTION_ZOOM
|
||||
};
|
||||
Action ComputeActionFor(mozilla::widget::WheelEvent* aEvent);
|
||||
|
||||
/**
|
||||
* NeedToComputeLineOrPageDelta() returns if the aEvent needs to be
|
||||
* computed the lineOrPageDelta values.
|
||||
*/
|
||||
bool NeedToComputeLineOrPageDelta(mozilla::widget::WheelEvent* aEvent);
|
||||
|
||||
private:
|
||||
WheelPrefs();
|
||||
~WheelPrefs();
|
||||
|
||||
static int OnPrefChanged(const char* aPrefName, void* aClosure);
|
||||
|
||||
enum Index
|
||||
{
|
||||
INDEX_DEFAULT = 0,
|
||||
INDEX_ALT,
|
||||
INDEX_CONTROL,
|
||||
INDEX_META,
|
||||
INDEX_SHIFT,
|
||||
INDEX_OS,
|
||||
COUNT_OF_MULTIPLIERS
|
||||
};
|
||||
|
||||
/**
|
||||
* GetIndexFor() returns the index of the members which should be used for
|
||||
* the aEvent. When only one modifier key of MODIFIER_ALT,
|
||||
* MODIFIER_CONTROL, MODIFIER_META, MODIFIER_SHIFT or MODIFIER_OS is
|
||||
* pressed, returns the index for the modifier. Otherwise, this return the
|
||||
* default index which is used at either no modifier key is pressed or
|
||||
* two or modifier keys are pressed.
|
||||
*/
|
||||
Index GetIndexFor(mozilla::widget::WheelEvent* aEvent);
|
||||
|
||||
/**
|
||||
* GetPrefNameBase() returns the base pref name for aEvent.
|
||||
* It's decided by GetModifierForPref() which modifier should be used for
|
||||
* the aEvent.
|
||||
*
|
||||
* @param aBasePrefName The result, must be "mousewheel.with_*." or
|
||||
* "mousewheel.default.".
|
||||
*/
|
||||
void GetBasePrefName(Index aIndex, nsACString& aBasePrefName);
|
||||
|
||||
void Init(Index aIndex);
|
||||
|
||||
void Reset();
|
||||
|
||||
bool mInit[COUNT_OF_MULTIPLIERS];
|
||||
double mMultiplierX[COUNT_OF_MULTIPLIERS];
|
||||
double mMultiplierY[COUNT_OF_MULTIPLIERS];
|
||||
double mMultiplierZ[COUNT_OF_MULTIPLIERS];
|
||||
Action mActions[COUNT_OF_MULTIPLIERS];
|
||||
|
||||
static WheelPrefs* sInstance;
|
||||
};
|
||||
|
||||
/**
|
||||
* DeltaDirection is used for specifying whether the called method should
|
||||
* handle vertical delta or horizontal delta.
|
||||
* This is clearer than using bool.
|
||||
*/
|
||||
enum DeltaDirection
|
||||
{
|
||||
DELTA_DIRECTION_X = 0,
|
||||
DELTA_DIRECTION_Y
|
||||
};
|
||||
|
||||
/**
|
||||
* SendLineScrollEvent() dispatches a DOMMouseScroll event for the
|
||||
* widget::WheelEvent. This method shouldn't be called for non-trusted
|
||||
* wheel event because it's not necessary for compatiblity.
|
||||
*
|
||||
* @param aTargetFrame The event target of wheel event.
|
||||
* @param aEvent The original Wheel event.
|
||||
* @param aStatus The event status, must not be
|
||||
* nsEventStatus_eConsumeNoDefault.
|
||||
* @param aDelta The delta value of the event.
|
||||
* @param aDeltaDirection The X/Y direction of dispatching event.
|
||||
*/
|
||||
void SendLineScrollEvent(nsIFrame* aTargetFrame,
|
||||
mozilla::widget::WheelEvent* aEvent,
|
||||
nsEventStatus* aStatus,
|
||||
PRInt32 aDelta,
|
||||
DeltaDirection aDeltaDirection);
|
||||
|
||||
/**
|
||||
* SendPixelScrollEvent() dispatches a MozMousePixelScroll event for the
|
||||
* widget::WheelEvent. This method shouldn't be called for non-trusted
|
||||
* wheel event because it's not necessary for compatiblity.
|
||||
*
|
||||
* @param aTargetFrame The event target of wheel event.
|
||||
* @param aEvent The original Wheel event.
|
||||
* @param aStatus The event status, must not be
|
||||
* nsEventStatus_eConsumeNoDefault.
|
||||
* @param aPixelDelta The delta value of the event.
|
||||
* @param aDeltaDirection The X/Y direction of dispatching event.
|
||||
*/
|
||||
void SendPixelScrollEvent(nsIFrame* aTargetFrame,
|
||||
mozilla::widget::WheelEvent* aEvent,
|
||||
nsEventStatus* aStatus,
|
||||
PRInt32 aPixelDelta,
|
||||
DeltaDirection aDeltaDirection);
|
||||
|
||||
/**
|
||||
* ComputeScrollTarget() returns the scrollable frame which should be
|
||||
* scrolled.
|
||||
*
|
||||
* @param aTargetFrame The event target of the wheel event.
|
||||
* @param aEvent The handling mouse wheel event.
|
||||
* @param aForDefaultAction Whether this uses wheel transaction or not.
|
||||
* If true, returns the latest scrolled frame if
|
||||
* there is it. Otherwise, the nearest ancestor
|
||||
* scrollable frame from aTargetFrame.
|
||||
* @return The scrollable frame which should be scrolled.
|
||||
*/
|
||||
nsIScrollableFrame* ComputeScrollTarget(nsIFrame* aTargetFrame,
|
||||
mozilla::widget::WheelEvent* aEvent,
|
||||
bool aForDefaultAction);
|
||||
|
||||
/**
|
||||
* GetScrollAmount() returns the scroll amount in app uints of one line or
|
||||
* one page. If the wheel event scrolls a page, returns the page width and
|
||||
* height. Otherwise, returns line height for both its width and height.
|
||||
*
|
||||
* @param aScrollableFrame A frame which will be scrolled by the event.
|
||||
* The result of ComputeScrollTarget() is
|
||||
* expected for this value.
|
||||
* This can be NULL if there is no scrollable
|
||||
* frame. Then, this method uses root frame's
|
||||
* line height or visible area's width and height.
|
||||
*/
|
||||
nsSize GetScrollAmount(nsPresContext* aPresContext,
|
||||
mozilla::widget::WheelEvent* aEvent,
|
||||
nsIScrollableFrame* aScrollableFrame);
|
||||
|
||||
/**
|
||||
* DoScrollText() scrolls the scrollable frame for aEvent.
|
||||
*/
|
||||
void DoScrollText(nsIScrollableFrame* aScrollableFrame,
|
||||
mozilla::widget::WheelEvent* aEvent);
|
||||
|
||||
void DoScrollHistory(PRInt32 direction);
|
||||
void DoScrollZoom(nsIFrame *aTargetFrame, PRInt32 adjustment);
|
||||
nsresult GetMarkupDocumentViewer(nsIMarkupDocumentViewer** aMv);
|
||||
nsresult ChangeTextSize(PRInt32 change);
|
||||
nsresult ChangeFullZoom(PRInt32 change);
|
||||
|
||||
/**
|
||||
* Computes actual delta value used for scrolling. If user customized the
|
||||
* scrolling speed and/or direction, this would return the customized value.
|
||||
* Otherwise, it would return the original delta value of aMouseEvent.
|
||||
* DeltaAccumulator class manages delta values for dispatching DOMMouseScroll
|
||||
* event. If wheel events are caused by pixel scroll only devices or
|
||||
* the delta values are customized by prefs, this class stores the delta
|
||||
* values and set lineOrPageDelta values.
|
||||
*/
|
||||
PRInt32 ComputeWheelDeltaFor(nsMouseScrollEvent* aMouseEvent);
|
||||
class DeltaAccumulator
|
||||
{
|
||||
public:
|
||||
static DeltaAccumulator* GetInstance()
|
||||
{
|
||||
if (!sInstance) {
|
||||
sInstance = new DeltaAccumulator;
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
static void Shutdown()
|
||||
{
|
||||
delete sInstance;
|
||||
sInstance = nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the action for the aMouseEvent with prefs. The result is
|
||||
* MOUSE_SCROLL_N_LINES, MOUSE_SCROLL_PAGE, MOUSE_SCROLL_HISTORY,
|
||||
* MOUSE_SCROLL_ZOOM, MOUSE_SCROLL_PIXELS or -1.
|
||||
* When the result is -1, nothing happens for the event.
|
||||
*
|
||||
* @param aUseSystemSettings Set the result of UseSystemScrollSettingFor().
|
||||
* InitLineOrPageDelta() stores pixel delta values of WheelEvents which are
|
||||
* caused if it's needed. And if the accumulated delta becomes a
|
||||
* line height, sets lineOrPageDeltaX and lineOrPageDeltaY automatically.
|
||||
*/
|
||||
PRInt32 ComputeWheelActionFor(nsMouseScrollEvent* aMouseEvent,
|
||||
bool aUseSystemSettings);
|
||||
void InitLineOrPageDelta(nsIFrame* aTargetFrame,
|
||||
nsEventStateManager* aESM,
|
||||
mozilla::widget::WheelEvent* aEvent);
|
||||
|
||||
/**
|
||||
* Gets the wheel action for the aMouseEvent ONLY with the pref.
|
||||
* When you actually do something for the event, probably you should use
|
||||
* ComputeWheelActionFor().
|
||||
* Reset() resets both delta values.
|
||||
*/
|
||||
PRInt32 GetWheelActionFor(nsMouseScrollEvent* aMouseEvent);
|
||||
/**
|
||||
* Gets the pref value for line scroll amount for the aMouseEvent.
|
||||
* Note that this method doesn't check whether the aMouseEvent is line scroll
|
||||
* event and doesn't use system settings.
|
||||
*/
|
||||
PRInt32 GetScrollLinesFor(nsMouseScrollEvent* aMouseEvent);
|
||||
/**
|
||||
* Whether use system scroll settings or settings in our prefs for the event.
|
||||
* TRUE, if use system scroll settings. Otherwise, FALSE.
|
||||
*/
|
||||
bool UseSystemScrollSettingFor(nsMouseScrollEvent* aMouseEvent);
|
||||
void Reset();
|
||||
|
||||
private:
|
||||
DeltaAccumulator() :
|
||||
mX(0.0), mY(0.0), mHandlingDeltaMode(PR_UINT32_MAX),
|
||||
mHandlingPixelOnlyDevice(false)
|
||||
{
|
||||
}
|
||||
|
||||
double mX;
|
||||
double mY;
|
||||
TimeStamp mLastTime;
|
||||
|
||||
PRUint32 mHandlingDeltaMode;
|
||||
bool mHandlingPixelOnlyDevice;
|
||||
|
||||
static DeltaAccumulator* sInstance;
|
||||
};
|
||||
|
||||
// end mousewheel functions
|
||||
|
||||
/*
|
||||
@ -440,8 +622,6 @@ protected:
|
||||
nsresult DoContentCommandEvent(nsContentCommandEvent* aEvent);
|
||||
nsresult DoContentCommandScrollEvent(nsContentCommandEvent* aEvent);
|
||||
|
||||
void DoQueryScrollTargetInfo(nsQueryContentEvent* aEvent,
|
||||
nsIFrame* aTargetFrame);
|
||||
void DoQuerySelectedText(nsQueryContentEvent* aEvent);
|
||||
|
||||
bool RemoteQueryContentEvent(nsEvent *aEvent);
|
||||
@ -530,10 +710,6 @@ public:
|
||||
// Array for accesskey support
|
||||
nsCOMArray<nsIContent> mAccessKeys;
|
||||
|
||||
// Unlocks pixel scrolling
|
||||
bool mLastLineScrollConsumedX;
|
||||
bool mLastLineScrollConsumedY;
|
||||
|
||||
static PRInt32 sUserInputEventDepth;
|
||||
|
||||
static bool sNormalLMouseEventInProcess;
|
||||
|
@ -84,6 +84,11 @@ MOCHITEST_FILES = \
|
||||
test_bug741666.html \
|
||||
test_dom_keyboard_event.html \
|
||||
test_dom_mouse_event.html \
|
||||
test_dom_wheel_event.html \
|
||||
test_continuous_wheel_events.html \
|
||||
test_moz_mouse_pixel_scroll_event.html \
|
||||
test_wheel_default_action.html \
|
||||
window_wheel_default_action.html \
|
||||
test_bug603008.html \
|
||||
test_bug716822.html \
|
||||
test_bug742376.html \
|
||||
@ -106,7 +111,6 @@ endif
|
||||
MOCHITEST_CHROME_FILES = \
|
||||
test_bug336682_2.xul \
|
||||
test_bug336682.js \
|
||||
test_bug350471.xul \
|
||||
test_bug586961.xul \
|
||||
test_bug415498.xul \
|
||||
bug415498-doc1.html \
|
||||
|
@ -1,264 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=350471
|
||||
-->
|
||||
<window title="Mozilla Bug 350471"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
<title>Test for Bug 350471</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=350471">Mozilla Bug 350471</a>
|
||||
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
</body>
|
||||
|
||||
<script class="testbody" type="application/javascript;version=1.7"><![CDATA[
|
||||
|
||||
/** Test for Bug 350471 **/
|
||||
|
||||
const minLineHeight = 10, maxLineHeight = 20;
|
||||
|
||||
function between(x, min, max) (min <= max) ? (min <= x && x <= max) : (max <= x && x <= min);
|
||||
function isbetween(x, min, max, msg) ok(between(x, min, max), msg + " - Expected " + min + " to " + max + ", got " + x);
|
||||
|
||||
function testEventDispatching(aWin) {
|
||||
function helper(aAxis, aDelta, aKind, aShiftKey, aCtrlKey, aAltKey, aMetaKey) {
|
||||
let expectedEvents = [];
|
||||
let deltaUnit = "";
|
||||
function listener(e) {
|
||||
if (!expectedEvents.length) {
|
||||
ok(false, "Received an event that I didn't expect. type: " + e.type +
|
||||
", axis: " + e.axis + ", delta: " + e.delta);
|
||||
return;
|
||||
}
|
||||
let expected = expectedEvents.shift();
|
||||
|
||||
["type", "shiftKey", "ctrlKey", "altKey", "metaKey"].forEach(function(field) {
|
||||
is(e[field], expected[field],
|
||||
"e." + field + " (" + e[field] + ") does not match expected value (" + expected[field] + ")");
|
||||
});
|
||||
|
||||
let expectedAxis = expected.axis == "horizontal" ? e.HORIZONTAL_AXIS : e.VERTICAL_AXIS;
|
||||
is(e.axis, expectedAxis,
|
||||
"e.axis (" + e.axis + ") does not match expected value (" + expectedAxis + ")");
|
||||
|
||||
// When modifier keys are pressed, cancel the event.
|
||||
// We don't want to zoom or navigate back / forward (history scroll).
|
||||
if (aShiftKey || aCtrlKey || aAltKey || aMetaKey) {
|
||||
e.preventDefault();
|
||||
// Note: If this is a DOMMouseScroll event without hasPixels, we still
|
||||
// expect a follow-up MozMousePixelScroll event.
|
||||
} else {
|
||||
// Only check the delta if no modifiers are pressed.
|
||||
// History scroll and zoom change the deltas in nsESM::PreHandleEvent.
|
||||
if (deltaUnit == (e.type == "DOMMouseScroll" ? "lines" : "pixels")) {
|
||||
// no unit conversion necessary
|
||||
is(e.detail, expected.delta,
|
||||
"e.detail (" + e.detail + ") does not match expected value (" + expected.delta + ")");
|
||||
} else if (e.type == "MozMousePixelScroll") {
|
||||
// We sent a line scroll event but are receiving a pixel scroll event,
|
||||
// so we need to convert the delta.
|
||||
let minDelta = expected.delta * minLineHeight;
|
||||
let maxDelta = expected.delta * maxLineHeight;
|
||||
isbetween(e.detail, minDelta, maxDelta, "wrong pixel scroll event delta");
|
||||
}
|
||||
}
|
||||
e.stopPropagation();
|
||||
}
|
||||
// Set up the expected values.
|
||||
if (aKind == 0 || aKind == 1) {
|
||||
expectedEvents.push({
|
||||
type: "DOMMouseScroll",
|
||||
axis: aAxis,
|
||||
delta: aDelta,
|
||||
hasPixels: (aKind == 1),
|
||||
shiftKey: aShiftKey,
|
||||
ctrlKey: aCtrlKey,
|
||||
altKey: aAltKey,
|
||||
metaKey: aMetaKey
|
||||
});
|
||||
}
|
||||
if (aKind == 0 || aKind == 2) {
|
||||
expectedEvents.push({
|
||||
type: "MozMousePixelScroll",
|
||||
axis: aAxis,
|
||||
delta: aDelta,
|
||||
shiftKey: aShiftKey,
|
||||
ctrlKey: aCtrlKey,
|
||||
altKey: aAltKey,
|
||||
metaKey: aMetaKey
|
||||
});
|
||||
}
|
||||
deltaUnit = aKind == 2 ? "pixels" : "lines";
|
||||
|
||||
aWin.document.addEventListener("DOMMouseScroll", listener, true);
|
||||
aWin.document.addEventListener("MozMousePixelScroll", listener, true);
|
||||
|
||||
// Send the event to the documentElement.
|
||||
synthesizeMouseScroll(aWin.document.documentElement, 10, 10, expectedEvents[0], aWin);
|
||||
|
||||
aWin.document.removeEventListener("DOMMouseScroll", listener, true);
|
||||
aWin.document.removeEventListener("MozMousePixelScroll", listener, true);
|
||||
|
||||
// expectedEvents should be empty now. If it's not, print errors.
|
||||
expectedEvents.forEach(function(e) {
|
||||
ok(false, "Didn't receive expected event: " + JSON.stringify(e));
|
||||
});
|
||||
};
|
||||
let i = 0;
|
||||
[0, 1, 2].forEach(function(aKind) {
|
||||
["horizontal", "vertical"].forEach(function(aAxis) {
|
||||
[false, true].forEach(function(aShift) {
|
||||
[false, true].forEach(function(aCtrl) {
|
||||
[false, true].forEach(function(aAlt) {
|
||||
[false, true].forEach(function(aMeta) {
|
||||
helper(aAxis, [-5, -1, 0, 1, 5][i++ % 5], aKind, aShift, aCtrl, aAlt, aMeta);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function testDefaultHandling(aWin, andThen) {
|
||||
let scrollbox = aWin.document.getElementById("scrollbox");
|
||||
|
||||
function scrollWithPreventDefault(aEvent, aDoConsume) {
|
||||
function listener(e) {
|
||||
if (aDoConsume[e.type])
|
||||
e.preventDefault();
|
||||
}
|
||||
scrollbox.addEventListener("DOMMouseScroll", listener, true);
|
||||
scrollbox.addEventListener("MozMousePixelScroll", listener, true);
|
||||
synthesizeMouseScroll(scrollbox, 10, 10, aEvent, aWin);
|
||||
scrollbox.removeEventListener("DOMMouseScroll", listener, true);
|
||||
scrollbox.removeEventListener("MozMousePixelScroll", listener, true);
|
||||
}
|
||||
|
||||
let tests = [];
|
||||
function helper(aType, aHasPixels, aAxis, aStart, aDelta, aConsumeLine, aConsumePixel, aPositionShouldChange, aCurrentTest) {
|
||||
tests.push([aType, aHasPixels, aAxis, aStart, aDelta, aConsumeLine, aConsumePixel, aPositionShouldChange, aCurrentTest]);
|
||||
}
|
||||
function exec() {
|
||||
let [aType, aHasPixels, aAxis, aStart, aDelta, aConsumeLine, aConsumePixel, aPositionShouldChange, currentTest] = tests[0];
|
||||
tests.shift();
|
||||
scrollbox.scrollLeft = aStart;
|
||||
scrollbox.scrollTop = aStart;
|
||||
scrollWithPreventDefault({
|
||||
type: aType,
|
||||
axis: aAxis,
|
||||
hasPixels: aHasPixels,
|
||||
delta: aDelta
|
||||
}, {
|
||||
"DOMMouseScroll": aConsumeLine,
|
||||
"MozMousePixelScroll": aConsumePixel
|
||||
});
|
||||
setTimeout(function() {
|
||||
let newPos = scrollbox[aAxis == "horizontal" ? "scrollLeft" : "scrollTop"];
|
||||
let newPosWrongAxis = scrollbox[aAxis == "horizontal" ? "scrollTop" : "scrollLeft"];
|
||||
|
||||
is(newPosWrongAxis, aStart, currentTest + " wrong axis scrolled - type: " + aType);
|
||||
|
||||
if (aPositionShouldChange) {
|
||||
if (aType == "MozMousePixelScroll") {
|
||||
// aDelta is in pixels, no conversion necessary
|
||||
is(newPos, aStart + aDelta, currentTest + " wrong scroll position - type: " + aType);
|
||||
} else {
|
||||
// Use minLineHeight and maxLineHeight as an estimate for the conversion factor.
|
||||
isbetween(newPos, aStart + aDelta * minLineHeight, aStart + aDelta * maxLineHeight,
|
||||
currentTest + " wrong scroll position - type: " + aType);
|
||||
}
|
||||
} else {
|
||||
is(newPos, aStart, currentTest + " The scroll position shouldn't have changed. - type: " + aType);
|
||||
}
|
||||
if (tests.length)
|
||||
exec();
|
||||
else
|
||||
andThen();
|
||||
}, 20);
|
||||
}
|
||||
|
||||
["horizontal", "vertical"].forEach(function(aAxis) {
|
||||
[-5, 5].forEach(function(aDelta) {
|
||||
[false, true].forEach(function(aConsumeLine) {
|
||||
[false, true].forEach(function(aConsumePixel) {
|
||||
let shouldScroll = !aConsumeLine && !aConsumePixel;
|
||||
let currentTest = "";
|
||||
|
||||
currentTest = "normal DOMMouseScroll: only scroll if neither line nor pixel scroll are consumed.";
|
||||
helper("DOMMouseScroll", false, aAxis, 4000, aDelta, aConsumeLine, aConsumePixel, shouldScroll, currentTest);
|
||||
|
||||
currentTest = "DOMMouseScroll with hasPixels: never scroll.";
|
||||
helper("DOMMouseScroll", true, aAxis, 4000, aDelta, aConsumeLine, aConsumePixel, false, currentTest);
|
||||
|
||||
currentTest = "MozMousePixelScroll (consumed: " + aConsumePixel +
|
||||
") with preceding DOMMouseScroll (consumed: " + aConsumeLine +
|
||||
"): " + (shouldScroll ? "scroll." : "don't scroll.");
|
||||
// It shouldn't matter:
|
||||
// 1. whether hasPixels is set on the preceding DOMMouseScroll event or
|
||||
// 2. whether the preceding DOMMouseScroll event's MozMousePixelScroll event is consumed.
|
||||
helper("DOMMouseScroll", true, aAxis, 4000, aDelta, aConsumeLine, false, false, currentTest);
|
||||
helper("MozMousePixelScroll", false, aAxis, 4000, aDelta, false, aConsumePixel, shouldScroll, currentTest);
|
||||
helper("DOMMouseScroll", false, aAxis, 4000, aDelta, aConsumeLine, false, !aConsumeLine, currentTest);
|
||||
helper("MozMousePixelScroll", false, aAxis, 4000, aDelta, false, aConsumePixel, shouldScroll, currentTest);
|
||||
helper("DOMMouseScroll", false, aAxis, 4000, aDelta, aConsumeLine, true, false, currentTest);
|
||||
helper("MozMousePixelScroll", false, aAxis, 4000, aDelta, false, aConsumePixel, shouldScroll, currentTest);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
exec();
|
||||
}
|
||||
|
||||
function initPrefs()
|
||||
{
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var prefSvc = Components.classes["@mozilla.org/preferences-service;1"].
|
||||
getService(Components.interfaces.nsIPrefBranch);
|
||||
// Disables the app level scroll acceleration
|
||||
prefSvc.setIntPref("mousewheel.acceleration.start", -1);
|
||||
prefSvc.setBoolPref("mousewheel.system_scroll_override_on_root_content.enabled", false);
|
||||
prefSvc.setBoolPref("general.smoothScroll", false);
|
||||
}
|
||||
|
||||
function clearPrefs()
|
||||
{
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var prefSvc = Components.classes["@mozilla.org/preferences-service;1"].
|
||||
getService(Components.interfaces.nsIPrefBranch);
|
||||
|
||||
prefSvc.clearUserPref("mousewheel.acceleration.start");
|
||||
prefSvc.clearUserPref("mousewheel.system_scroll_override_on_root_content.enabled");
|
||||
prefSvc.clearUserPref("general.smoothScroll");
|
||||
}
|
||||
|
||||
window.onload = function () {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
|
||||
let win = window.open('data:application/vnd.mozilla.xul+xml,<?xml version="1.0"?><?xml-stylesheet href="chrome://global/skin" type="text/css"?><window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"><vbox style="height: 150px; background: cyan; overflow: auto;" id="scrollbox"><hbox style="height: 8000px;"><vbox style="width: 8000px;"/></hbox></vbox></window>', '_blank', 'chrome,width=400,height=200');
|
||||
win.onload = function() {
|
||||
setTimeout(function() {
|
||||
initPrefs();
|
||||
testEventDispatching(win);
|
||||
testDefaultHandling(win, function() {
|
||||
clearPrefs();
|
||||
win.close();
|
||||
SimpleTest.finish();
|
||||
});
|
||||
}, 20);
|
||||
}
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
]]></script>
|
||||
|
||||
</window>
|
@ -23,25 +23,17 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=574663
|
||||
function sendTouchpadScrollMotion(scrollbox, direction, ctrl, momentum) {
|
||||
var win = scrollbox.ownerDocument.defaultView;
|
||||
let event = {
|
||||
'type': "DOMMouseScroll",
|
||||
'axis': "vertical",
|
||||
'delta': direction,
|
||||
'hasPixels': true,
|
||||
'ctrlKey': ctrl,
|
||||
'isMomentum': momentum,
|
||||
deltaMode: WheelEvent.DOM_DELTA_PIXEL,
|
||||
deltaY: direction * 3,
|
||||
lineOrPageDeltaY: direction,
|
||||
ctrlKey: ctrl,
|
||||
isMomentum: momentum
|
||||
};
|
||||
// first a line scroll
|
||||
synthesizeMouseScroll(scrollbox, 10, 10, event, win);
|
||||
// Then a line scroll with hasPixels set to false
|
||||
event.hasPixels = false;
|
||||
synthesizeMouseScroll(scrollbox, 10, 10, event, win);
|
||||
// then 5 pixel scrolls
|
||||
event.hasPixels = true;
|
||||
event.delta *= 3;
|
||||
event.type = "MozMousePixelScroll";
|
||||
event.hasPixels = false;
|
||||
synthesizeWheel(scrollbox, 10, 10, event, win);
|
||||
// then 5 additional pixel scrolls
|
||||
event.lineOrPageDeltaY = 0;
|
||||
for (let i = 0; i < 5; ++i) {
|
||||
synthesizeMouseScroll(scrollbox, 10, 10, event, win);
|
||||
synthesizeWheel(scrollbox, 10, 10, event, win);
|
||||
}
|
||||
}
|
||||
|
||||
@ -110,7 +102,7 @@ function initPrefs()
|
||||
prefSvc.setIntPref("mousewheel.acceleration.start", -1);
|
||||
prefSvc.setBoolPref("mousewheel.system_scroll_override_on_root_content.enabled", false);
|
||||
// Enable zooming for ctrl-scrolling
|
||||
prefSvc.setIntPref("mousewheel.withcontrolkey.action", 3);
|
||||
prefSvc.setIntPref("mousewheel.with_control.action", 3);
|
||||
}
|
||||
|
||||
function clearPrefs()
|
||||
@ -122,7 +114,7 @@ function clearPrefs()
|
||||
prefSvc.clearUserPref("general.smoothScroll");
|
||||
prefSvc.clearUserPref("mousewheel.acceleration.start");
|
||||
prefSvc.clearUserPref("mousewheel.system_scroll_override_on_root_content.enabled");
|
||||
prefSvc.clearUserPref("mousewheel.withcontrolkey.action");
|
||||
prefSvc.clearUserPref("mousewheel.with_control.action");
|
||||
}
|
||||
|
||||
window.onload = function () {
|
||||
|
@ -26,19 +26,16 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=607464
|
||||
function scrollDown15PxWithPixelScrolling(scrollbox) {
|
||||
var win = scrollbox.ownerDocument.defaultView;
|
||||
let event = {
|
||||
'type': "DOMMouseScroll",
|
||||
'axis': "vertical",
|
||||
'delta': 1,
|
||||
'hasPixels': true,
|
||||
deltaMode: WheelEvent.DOM_DELTA_PIXEL,
|
||||
deltaY: 3.0,
|
||||
lineOrPageDeltaY: 1
|
||||
};
|
||||
// first a line scroll
|
||||
synthesizeMouseScroll(scrollbox, 10, 10, event, win);
|
||||
// then 5 pixel scrolls with 3px each
|
||||
event.delta *= 3;
|
||||
event.type = "MozMousePixelScroll";
|
||||
event.hasPixels = false;
|
||||
for (let i = 0; i < 5; ++i) {
|
||||
synthesizeMouseScroll(scrollbox, 10, 10, event, win);
|
||||
// A pixel scroll with lineOrPageDeltaY.
|
||||
synthesizeWheel(scrollbox, 10, 10, event, win);
|
||||
// then 4 pixel scrolls without lineOrPageDeltaY.
|
||||
event.lineOrPageDeltaY = 0;
|
||||
for (let i = 0; i < 4; ++i) {
|
||||
synthesizeWheel(scrollbox, 10, 10, event, win);
|
||||
}
|
||||
|
||||
// Note: the line scroll shouldn't have any effect because it has
|
||||
|
3286
content/events/test/test_continuous_wheel_events.html
Normal file
3286
content/events/test/test_continuous_wheel_events.html
Normal file
File diff suppressed because it is too large
Load Diff
707
content/events/test/test_dom_wheel_event.html
Normal file
707
content/events/test/test_dom_wheel_event.html
Normal file
@ -0,0 +1,707 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html style="font-size: 32px;">
|
||||
<head>
|
||||
<title>Test for D3E WheelEvent</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="scrollable" style="font-size: 16px; line-height: 1; overflow: auto; width: 200px; height: 200px;">
|
||||
<div id="scrolled" style="font-size: 64px; width: 5000px; height: 5000px;">
|
||||
Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text.<br>
|
||||
Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text.<br>
|
||||
Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text.<br>
|
||||
Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text.<br>
|
||||
Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text.<br>
|
||||
Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text.<br>
|
||||
Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text.<br>
|
||||
Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text.<br>
|
||||
Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text.<br>
|
||||
Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text.<br>
|
||||
Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text.<br>
|
||||
Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text.<br>
|
||||
Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text.<br>
|
||||
Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text.<br>
|
||||
Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text.<br>
|
||||
Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text.<br>
|
||||
Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text.<br>
|
||||
Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text.<br>
|
||||
Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text.<br>
|
||||
Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text.<br>
|
||||
Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text.<br>
|
||||
Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text.<br>
|
||||
Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text.<br>
|
||||
Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text.<br>
|
||||
Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text.<br>
|
||||
Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text.<br>
|
||||
</div>
|
||||
</div>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.waitForFocus(runTests, window);
|
||||
|
||||
var gScrollableElement = document.getElementById("scrollable");
|
||||
var gScrolledElement = document.getElementById("scrolled");
|
||||
|
||||
var gLineHeight = 0;
|
||||
var gPageHeight = 0;
|
||||
var gPageWidth = 0;
|
||||
|
||||
function prepareScrollUnits()
|
||||
{
|
||||
var result = -1;
|
||||
function handler(aEvent)
|
||||
{
|
||||
result = aEvent.detail;
|
||||
aEvent.preventDefault();
|
||||
}
|
||||
window.addEventListener("MozMousePixelScroll", handler, true);
|
||||
|
||||
synthesizeWheel(gScrollableElement, 10, 10,
|
||||
{ deltaMode: WheelEvent.DOM_DELTA_LINE,
|
||||
deltaY: 1.0, lineOrPageDeltaY: 1 });
|
||||
gLineHeight = result;
|
||||
ok(gLineHeight > 10 && gLineHeight < 25, "prepareScrollUnits: gLineHeight may be illegal value, got " + gLineHeight);
|
||||
|
||||
result = -1;
|
||||
synthesizeWheel(gScrollableElement, 10, 10,
|
||||
{ deltaMode: WheelEvent.DOM_DELTA_PAGE,
|
||||
deltaY: 1.0, lineOrPageDeltaY: 1 });
|
||||
gPageHeight = result;
|
||||
// XXX Cannot we know the actual scroll port size?
|
||||
ok(gPageHeight >= 150 && gPageHeight <= 200,
|
||||
"prepareScrollUnits: gPageHeight is strange value, got " + gPageHeight);
|
||||
|
||||
result = -1;
|
||||
synthesizeWheel(gScrollableElement, 10, 10,
|
||||
{ deltaMode: WheelEvent.DOM_DELTA_PAGE,
|
||||
deltaX: 1.0, lineOrPageDeltaX: 1 });
|
||||
gPageWidth = result;
|
||||
ok(gPageWidth >= 150 && gPageWidth <= 200,
|
||||
"prepareScrollUnits: gPageWidth is strange value, got " + gPageWidth);
|
||||
|
||||
window.removeEventListener("MozMousePixelScroll", handler, true);
|
||||
}
|
||||
|
||||
function testMakingUntrustedEvent()
|
||||
{
|
||||
const kCreateEventArgs = [
|
||||
"WheelEvent", "wheelevent", "wheelEvent", "Wheelevent"
|
||||
];
|
||||
|
||||
for (var i = 0; i < kCreateEventArgs.length; i++) {
|
||||
try {
|
||||
// We never support WheelEvent construction with document.createEvent().
|
||||
var event = document.createEvent(kCreateEventArgs[i]);
|
||||
ok(false, "document.createEvent(" + kCreateEventArgs[i] + ") should throw an error");
|
||||
} catch (e) {
|
||||
ok(true, "document.createEvent(" + kCreateEventArgs[i] + ") threw an error");
|
||||
}
|
||||
}
|
||||
|
||||
var wheelEvent = new WheelEvent("wheel");
|
||||
ok(wheelEvent instanceof WheelEvent,
|
||||
"new WheelEvent() should create an instance of WheelEvent");
|
||||
ok(typeof(wheelEvent.initWheelEvent) != "function",
|
||||
"WheelEvent must not have initWheelEvent()");
|
||||
}
|
||||
|
||||
// delta_multiplier prefs should cause changing delta values of trusted events only.
|
||||
// And also legacy events' detail value should be changed too.
|
||||
function testDeltaMultiplierPrefs()
|
||||
{
|
||||
const kModifierAlt = 0x01;
|
||||
const kModifierControl = 0x02;
|
||||
const kModifierMeta = 0x04;
|
||||
const kModifierShift = 0x08;
|
||||
const kModifierWin = 0x10;
|
||||
|
||||
const kTests = [
|
||||
{ name: "default",
|
||||
expected: [ 0, kModifierShift | kModifierAlt, kModifierShift | kModifierControl,
|
||||
kModifierShift | kModifierMeta, kModifierShift | kModifierWin,
|
||||
kModifierControl | kModifierAlt, kModifierMeta | kModifierAlt ],
|
||||
unexpected: [ kModifierAlt, kModifierControl, kModifierMeta, kModifierShift, kModifierWin ] },
|
||||
{ name: "with_alt",
|
||||
expected: [ kModifierAlt ],
|
||||
unexpected: [0, kModifierControl, kModifierMeta, kModifierShift, kModifierWin,
|
||||
kModifierShift | kModifierAlt, kModifierControl | kModifierAlt,
|
||||
kModifierMeta | kModifierAlt ] },
|
||||
{ name: "with_control",
|
||||
expected: [ kModifierControl ],
|
||||
unexpected: [0, kModifierAlt, kModifierMeta, kModifierShift, kModifierWin,
|
||||
kModifierShift | kModifierControl, kModifierControl | kModifierAlt,
|
||||
kModifierMeta | kModifierControl ] },
|
||||
{ name: "with_meta",
|
||||
expected: [ kModifierMeta ],
|
||||
unexpected: [0, kModifierAlt, kModifierControl, kModifierShift, kModifierWin,
|
||||
kModifierShift | kModifierMeta, kModifierControl | kModifierMeta,
|
||||
kModifierMeta | kModifierAlt ] },
|
||||
{ name: "with_shift",
|
||||
expected: [ kModifierShift ],
|
||||
unexpected: [0, kModifierAlt, kModifierControl, kModifierMeta, kModifierWin,
|
||||
kModifierShift | kModifierAlt, kModifierControl | kModifierShift,
|
||||
kModifierMeta | kModifierShift ] },
|
||||
{ name: "with_win",
|
||||
expected: [ kModifierWin ],
|
||||
unexpected: [0, kModifierAlt, kModifierControl, kModifierMeta, kModifierShift,
|
||||
kModifierShift | kModifierWin ] },
|
||||
];
|
||||
|
||||
// Note that this test doesn't support complicated lineOrPageDelta values which are computed with
|
||||
// accumulated delta values by the prefs. If you need to test the lineOrPageDelta accumulation,
|
||||
// use test_continuous_dom_wheel_event.html.
|
||||
const kEvents = [
|
||||
{ deltaMode: WheelEvent.DOM_DELTA_PIXEL,
|
||||
deltaX: gLineHeight, deltaY: gLineHeight, deltaZ: gLineHeight, lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 },
|
||||
{ deltaMode: WheelEvent.DOM_DELTA_LINE,
|
||||
deltaX: 1.0, deltaY: 1.0, deltaZ: 1.0, lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 },
|
||||
{ deltaMode: WheelEvent.DOM_DELTA_PAGE,
|
||||
deltaX: 1.0, deltaY: 1.0, deltaZ: 1.0, lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 },
|
||||
{ deltaMode: WheelEvent.DOM_DELTA_PIXEL,
|
||||
deltaX: -gLineHeight, deltaY: -gLineHeight, deltaZ: -gLineHeight, lineOrPageDeltaX: -1, lineOrPageDeltaY: -1 },
|
||||
{ deltaMode: WheelEvent.DOM_DELTA_LINE,
|
||||
deltaX: -1.0, deltaY: -1.0, deltaZ: -1.0, lineOrPageDeltaX: -1, lineOrPageDeltaY: -1 },
|
||||
{ deltaMode: WheelEvent.DOM_DELTA_PAGE,
|
||||
deltaX: -1.0, deltaY: -1.0, deltaZ: -1.0, lineOrPageDeltaX: -1, lineOrPageDeltaY: -1 },
|
||||
];
|
||||
|
||||
const kDeltaMultiplierPrefs = [
|
||||
"delta_multiplier_x", "delta_multiplier_y", "delta_multiplier_z"
|
||||
];
|
||||
|
||||
const kPrefValues = [
|
||||
200, 50, 0, -50, -150
|
||||
];
|
||||
|
||||
var currentTest, currentModifiers, currentEvent, currentPref, currentMultiplier, testingExpected;
|
||||
var description;
|
||||
var calledHandlers = { wheel: false,
|
||||
DOMMouseScroll: { horizontal: false, vertical: false },
|
||||
MozMousePixelScroll: { horizontal: false, vertical: false } };
|
||||
|
||||
function wheelEventHandler(aEvent) {
|
||||
calledHandlers.wheel = true;
|
||||
|
||||
var expectedDeltaX = currentEvent.deltaX;
|
||||
var expectedDeltaY = currentEvent.deltaY;
|
||||
var expectedDeltaZ = currentEvent.deltaZ;
|
||||
|
||||
if (testingExpected) {
|
||||
switch (currentPref.charAt(currentPref.length - 1)) {
|
||||
case "x":
|
||||
expectedDeltaX *= currentMultiplier;
|
||||
break;
|
||||
case "y":
|
||||
expectedDeltaY *= currentMultiplier;
|
||||
break;
|
||||
case "z":
|
||||
expectedDeltaZ *= currentMultiplier;
|
||||
break;
|
||||
}
|
||||
}
|
||||
is(aEvent.deltaX, expectedDeltaX, description + "deltaX (" + currentEvent.deltaX + ") was invaild");
|
||||
is(aEvent.deltaY, expectedDeltaY, description + "deltaY (" + currentEvent.deltaY + ") was invaild");
|
||||
is(aEvent.deltaZ, expectedDeltaZ, description + "deltaZ (" + currentEvent.deltaZ + ") was invaild");
|
||||
}
|
||||
|
||||
function legacyEventHandler(aEvent) {
|
||||
var isHorizontal = (aEvent.axis == MouseScrollEvent.HORIZONTAL_AXIS);
|
||||
var isScrollEvent = (aEvent.type == "DOMMouseScroll");
|
||||
if (isScrollEvent) {
|
||||
if (isHorizontal) {
|
||||
calledHandlers.DOMMouseScroll.horizontal = true;
|
||||
} else {
|
||||
calledHandlers.DOMMouseScroll.vertical = true;
|
||||
}
|
||||
} else {
|
||||
if (isHorizontal) {
|
||||
calledHandlers.MozMousePixelScroll.horizontal = true;
|
||||
} else {
|
||||
calledHandlers.MozMousePixelScroll.vertical = true;
|
||||
}
|
||||
}
|
||||
var eventName = (isHorizontal ? "Horizontal " : "Vertical ") + aEvent.type + " ";
|
||||
var expectedDetail;
|
||||
if (isScrollEvent) {
|
||||
expectedDetail = isHorizontal ? currentEvent.lineOrPageDeltaX : currentEvent.lineOrPageDeltaY;
|
||||
if (currentEvent.deltaMode == WheelEvent.DOM_DELTA_PAGE && expectedDetail) {
|
||||
expectedDetail = ((expectedDetail > 0) ? UIEvent.SCROLL_PAGE_DOWN : UIEvent.SCROLL_PAGE_UP);
|
||||
}
|
||||
} else {
|
||||
expectedDetail = isHorizontal ? currentEvent.deltaX : currentEvent.deltaY;
|
||||
if (expectedDetail) {
|
||||
if (currentEvent.deltaMode == WheelEvent.DOM_DELTA_LINE) {
|
||||
expectedDetail *= gLineHeight;
|
||||
} else if (currentEvent.deltaMode == WheelEvent.DOM_DELTA_PAGE) {
|
||||
if (expectedDetail > 0) {
|
||||
expectedDetail = (isHorizontal ? gPageWidth : gPageHeight);
|
||||
} else {
|
||||
expectedDetail = (isHorizontal ? -gPageWidth : -gPageHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (testingExpected) {
|
||||
if ((isHorizontal && currentPref.charAt(currentPref.length - 1) == "x") ||
|
||||
(!isHorizontal && currentPref.charAt(currentPref.length - 1) == "y")) {
|
||||
// If it's a page scroll event, the detail value is UIEvent.SCROLL_PAGE_DOWN or
|
||||
// UIEvent.SCROLL_PAGE_UP. If the delta value sign is reverted, we need to
|
||||
// revert the expected detail value too. Otherwise, don't touch it.
|
||||
if (isScrollEvent && currentEvent.deltaMode == WheelEvent.DOM_DELTA_PAGE) {
|
||||
if (currentMultiplier < 0) {
|
||||
expectedDetail = ((expectedDetail == UIEvent.SCROLL_PAGE_UP) ? UIEvent.SCROLL_PAGE_DOWN : UIEvent.SCROLL_PAGE_UP);
|
||||
}
|
||||
} else {
|
||||
expectedDetail *= currentMultiplier;
|
||||
expectedDetail = expectedDetail < 0 ? Math.ceil(expectedDetail) : Math.floor(expectedDetail);
|
||||
}
|
||||
}
|
||||
}
|
||||
is(aEvent.detail, expectedDetail, description + eventName + "detail was invalid");
|
||||
|
||||
aEvent.preventDefault();
|
||||
}
|
||||
|
||||
window.addEventListener("wheel", wheelEventHandler, true);
|
||||
window.addEventListener("DOMMouseScroll", legacyEventHandler, true);
|
||||
window.addEventListener("MozMousePixelScroll", legacyEventHandler, true);
|
||||
|
||||
function dispatchEvent(aIsExpected) {
|
||||
for (var i = 0; i < kEvents.length; i++) {
|
||||
currentEvent = kEvents[i];
|
||||
currentEvent.shiftKey = (currentModifiers & kModifierShift) != 0;
|
||||
currentEvent.ctrlKey = (currentModifiers & kModifierControl) != 0;
|
||||
currentEvent.altKey = (currentModifiers & kModifierAlt) != 0;
|
||||
currentEvent.metaKey = (currentModifiers & kModifierMeta) != 0;
|
||||
currentEvent.osKey = (currentModifiers & kModifierWin) != 0;
|
||||
var modifierList = "";
|
||||
if (currentEvent.shiftKey) {
|
||||
modifierList += "Shift ";
|
||||
}
|
||||
if (currentEvent.ctrlKey) {
|
||||
modifierList += "Control ";
|
||||
}
|
||||
if (currentEvent.altKey) {
|
||||
modifierList += "Alt ";
|
||||
}
|
||||
if (currentEvent.metaKey) {
|
||||
modifierList += "Meta ";
|
||||
}
|
||||
if (currentEvent.osKey) {
|
||||
modifierList += "Win ";
|
||||
}
|
||||
|
||||
for (var j = 0; j < kPrefValues.length; j++) {
|
||||
currentMultiplier = kPrefValues[j] / 100;
|
||||
if (currentMultiplier > -1.0 && currentMultiplier < 1.0) {
|
||||
currentMultiplier = currentMultiplier < 0 ? -1.0 : 1.0;
|
||||
}
|
||||
for (var k = 0; k < kDeltaMultiplierPrefs.length; k++) {
|
||||
currentPref = "mousewheel." + currentTest.name + "." + kDeltaMultiplierPrefs[k];
|
||||
|
||||
SpecialPowers.setIntPref(currentPref, kPrefValues[j]);
|
||||
|
||||
gScrollableElement.scrollTop = gScrollableElement.scrollBottom = 1000;
|
||||
|
||||
// trusted event's delta valuses should be reverted by the pref.
|
||||
testingExpected = aIsExpected;
|
||||
|
||||
description = "testDeltaMultiplierPrefs, pref: " + currentPref + "=" + kPrefValues[j] +
|
||||
", deltaMode: " + currentEvent.deltaMode + ", modifiers: \"" + modifierList + "\", (trusted event): ";
|
||||
synthesizeWheel(gScrollableElement, 10, 10, currentEvent);
|
||||
|
||||
ok(calledHandlers.wheel, description + "wheel event was not fired");
|
||||
ok(calledHandlers.DOMMouseScroll.horizontal,
|
||||
description + "Horizontal DOMMouseScroll event was not fired");
|
||||
ok(calledHandlers.DOMMouseScroll.vertical,
|
||||
description + "Vertical DOMMouseScroll event was not fired");
|
||||
ok(calledHandlers.MozMousePixelScroll.horizontal,
|
||||
description + "Horizontal MozMousePixelScroll event was not fired");
|
||||
ok(calledHandlers.MozMousePixelScroll.vertical,
|
||||
description + "Vertical MozMousePixelScroll event was not fired");
|
||||
|
||||
calledHandlers = { wheel: false,
|
||||
DOMMouseScroll: { horizontal: false, vertical: false },
|
||||
MozMousePixelScroll: { horizontal: false, vertical: false } };
|
||||
|
||||
// untrusted event's delta values shouldn't be reverted by the pref.
|
||||
testingExpected = false;
|
||||
var props = {
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
shiftKey: currentEvent.shiftKey,
|
||||
ctrlKey: currentEvent.ctrlKey,
|
||||
altKey: currentEvent.altKey,
|
||||
metaKey: currentEvent.metaKey,
|
||||
deltaX: currentEvent.deltaX,
|
||||
deltaY: currentEvent.deltaY,
|
||||
deltaZ: currentEvent.deltaZ,
|
||||
deltaMode: currentEvent.deltaMode,
|
||||
};
|
||||
var untrustedEvent = new WheelEvent("wheel", props);
|
||||
|
||||
description = "testDeltaMultiplierPrefs, pref: " + currentPref + "=" + kPrefValues[j] +
|
||||
", deltaMode: " + currentEvent.deltaMode + ", modifiers: \"" + modifierList + "\", (untrusted event): ";
|
||||
gScrollableElement.dispatchEvent(untrustedEvent);
|
||||
|
||||
ok(calledHandlers.wheel, description + "wheel event was not fired for untrusted event");
|
||||
ok(!calledHandlers.DOMMouseScroll.horizontal,
|
||||
description + "Horizontal DOMMouseScroll event was fired for untrusted event");
|
||||
ok(!calledHandlers.DOMMouseScroll.vertical,
|
||||
description + "Vertical DOMMouseScroll event was fired for untrusted event");
|
||||
ok(!calledHandlers.MozMousePixelScroll.horizontal,
|
||||
description + "Horizontal MozMousePixelScroll event was fired for untrusted event");
|
||||
ok(!calledHandlers.MozMousePixelScroll.vertical,
|
||||
description + "Vertical MozMousePixelScroll event was fired for untrusted event");
|
||||
|
||||
SpecialPowers.setIntPref(currentPref, 100);
|
||||
|
||||
calledHandlers = { wheel: false,
|
||||
DOMMouseScroll: { horizontal: false, vertical: false },
|
||||
MozMousePixelScroll: { horizontal: false, vertical: false } };
|
||||
|
||||
}
|
||||
// We should skip other value tests if testing with modifier key.
|
||||
// If we didn't do so, it would test too many times, but we don't need to do so.
|
||||
if (kTests.name != "default") {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < kTests.length; i++) {
|
||||
currentTest = kTests[i];
|
||||
for (var j = 0; j < currentTest.expected.length; j++) {
|
||||
currentModifiers = currentTest.expected[j];
|
||||
dispatchEvent(true);
|
||||
}
|
||||
for (var k = 0; k < currentTest.unexpected.length; k++) {
|
||||
currentModifiers = currentTest.unexpected[k];
|
||||
dispatchEvent(false);
|
||||
}
|
||||
}
|
||||
|
||||
window.removeEventListener("wheel", wheelEventHandler, true);
|
||||
window.removeEventListener("DOMMouseScroll", legacyEventHandler, true);
|
||||
window.removeEventListener("MozMousePixelScroll", legacyEventHandler, true);
|
||||
}
|
||||
|
||||
// Untrusted wheel events shouldn't cause legacy mouse scroll events.
|
||||
function testDispatchingUntrustEvent()
|
||||
{
|
||||
var descriptionBase = "testDispatchingUntrustEvent, ";
|
||||
var description, wheelEventFired;
|
||||
function wheelEventHandler(aEvent)
|
||||
{
|
||||
wheelEventFired = true;
|
||||
}
|
||||
|
||||
function legacyEventHandler(aEvent)
|
||||
{
|
||||
ok(false, aEvent.type + " must not be fired");
|
||||
}
|
||||
|
||||
window.addEventListener("wheel", wheelEventHandler, true);
|
||||
window.addEventListener("DOMMouseScroll", legacyEventHandler, true);
|
||||
window.addEventListener("MozMousePixelScroll", legacyEventHandler, true);
|
||||
|
||||
description = descriptionBase + "dispatching a pixel wheel event: ";
|
||||
wheelEventFired = false;
|
||||
var untrustedPixelEvent = new WheelEvent("wheel", {
|
||||
bubbles: true, cancelable: true,
|
||||
deltaX: 24.0, deltaY: 24.0,
|
||||
deltaMode: WheelEvent.DOM_DELTA_PIXEL,
|
||||
});
|
||||
gScrolledElement.dispatchEvent(untrustedPixelEvent);
|
||||
ok(wheelEventFired, description + "wheel event wasn't fired");
|
||||
|
||||
description = descriptionBase + "dispatching a line wheel event: ";
|
||||
wheelEventFired = false;
|
||||
var untrustedLineEvent = new WheelEvent("wheel", {
|
||||
bubbles: true, cancelable: true,
|
||||
deltaX: 3.0, deltaY: 3.0,
|
||||
deltaMode: WheelEvent.DOM_DELTA_LINE,
|
||||
});
|
||||
gScrolledElement.dispatchEvent(untrustedLineEvent);
|
||||
ok(wheelEventFired, description + "wheel event wasn't fired");
|
||||
|
||||
description = descriptionBase + "dispatching a page wheel event: ";
|
||||
wheelEventFired = false;
|
||||
var untrustedPageEvent = new WheelEvent("wheel", {
|
||||
bubbles: true, cancelable: true,
|
||||
deltaX: 1.0, deltaY: 1.0,
|
||||
deltaMode: WheelEvent.DOM_DELTA_PAGE,
|
||||
});
|
||||
gScrolledElement.dispatchEvent(untrustedPageEvent);
|
||||
ok(wheelEventFired, description + "wheel event wasn't fired");
|
||||
|
||||
window.removeEventListener("wheel", wheelEventHandler, true);
|
||||
window.removeEventListener("DOMMouseScroll", legacyEventHandler, true);
|
||||
window.removeEventListener("MozMousePixelScroll", legacyEventHandler, true);
|
||||
}
|
||||
|
||||
function testEventOrder()
|
||||
{
|
||||
const kWheelEvent = 0x0001;
|
||||
const kDOMMouseScrollEvent = 0x0002;
|
||||
const kMozMousePixelScrollEvent = 0x0004;
|
||||
const kVerticalScrollEvent = 0x0010;
|
||||
const kHorizontalScrollEvent = 0x0020;
|
||||
const kInSystemGroup = 0x0100;
|
||||
const kDefaultPrevented = 0x1000;
|
||||
|
||||
var currentTest;
|
||||
|
||||
const kTests = [
|
||||
{
|
||||
description: "Testing the order of the events without preventDefault()",
|
||||
expectedEvents: [ kWheelEvent,
|
||||
kDOMMouseScrollEvent | kVerticalScrollEvent,
|
||||
kDOMMouseScrollEvent | kVerticalScrollEvent | kInSystemGroup,
|
||||
kMozMousePixelScrollEvent | kVerticalScrollEvent,
|
||||
kMozMousePixelScrollEvent | kVerticalScrollEvent | kInSystemGroup,
|
||||
kDOMMouseScrollEvent | kHorizontalScrollEvent,
|
||||
kDOMMouseScrollEvent | kHorizontalScrollEvent | kInSystemGroup,
|
||||
kMozMousePixelScrollEvent | kHorizontalScrollEvent,
|
||||
kMozMousePixelScrollEvent | kHorizontalScrollEvent | kInSystemGroup,
|
||||
kWheelEvent | kInSystemGroup],
|
||||
resultEvents: [],
|
||||
doPreventDefaultAt: 0,
|
||||
},
|
||||
{
|
||||
description: "Testing the order of the events, calling preventDefault() at default group wheel event",
|
||||
expectedEvents: [ kWheelEvent,
|
||||
kWheelEvent | kInSystemGroup | kDefaultPrevented],
|
||||
resultEvents: [],
|
||||
doPreventDefaultAt: kWheelEvent,
|
||||
},
|
||||
{
|
||||
description: "Testing the order of the events, calling preventDefault() at default group DOMMouseScroll event",
|
||||
expectedEvents: [ kWheelEvent,
|
||||
kDOMMouseScrollEvent | kVerticalScrollEvent,
|
||||
kDOMMouseScrollEvent | kVerticalScrollEvent | kInSystemGroup | kDefaultPrevented,
|
||||
kMozMousePixelScrollEvent | kVerticalScrollEvent | kDefaultPrevented,
|
||||
kMozMousePixelScrollEvent | kVerticalScrollEvent | kInSystemGroup | kDefaultPrevented,
|
||||
kDOMMouseScrollEvent | kHorizontalScrollEvent,
|
||||
kDOMMouseScrollEvent | kHorizontalScrollEvent | kInSystemGroup,
|
||||
kMozMousePixelScrollEvent | kHorizontalScrollEvent,
|
||||
kMozMousePixelScrollEvent | kHorizontalScrollEvent | kInSystemGroup,
|
||||
kWheelEvent | kInSystemGroup | kDefaultPrevented],
|
||||
resultEvents: [],
|
||||
doPreventDefaultAt: kDOMMouseScrollEvent | kVerticalScrollEvent,
|
||||
},
|
||||
{
|
||||
description: "Testing the order of the events, calling preventDefault() at default group MozMousePixelScroll event",
|
||||
expectedEvents: [ kWheelEvent,
|
||||
kDOMMouseScrollEvent | kVerticalScrollEvent,
|
||||
kDOMMouseScrollEvent | kVerticalScrollEvent | kInSystemGroup,
|
||||
kMozMousePixelScrollEvent | kVerticalScrollEvent,
|
||||
kMozMousePixelScrollEvent | kVerticalScrollEvent | kInSystemGroup | kDefaultPrevented,
|
||||
kDOMMouseScrollEvent | kHorizontalScrollEvent,
|
||||
kDOMMouseScrollEvent | kHorizontalScrollEvent | kInSystemGroup,
|
||||
kMozMousePixelScrollEvent | kHorizontalScrollEvent,
|
||||
kMozMousePixelScrollEvent | kHorizontalScrollEvent | kInSystemGroup,
|
||||
kWheelEvent | kInSystemGroup | kDefaultPrevented],
|
||||
resultEvents: [],
|
||||
doPreventDefaultAt: kMozMousePixelScrollEvent | kVerticalScrollEvent,
|
||||
},
|
||||
{
|
||||
description: "Testing the order of the events, calling preventDefault() at system group DOMMouseScroll event",
|
||||
expectedEvents: [ kWheelEvent,
|
||||
kDOMMouseScrollEvent | kVerticalScrollEvent,
|
||||
kDOMMouseScrollEvent | kVerticalScrollEvent | kInSystemGroup,
|
||||
kMozMousePixelScrollEvent | kVerticalScrollEvent | kDefaultPrevented,
|
||||
kMozMousePixelScrollEvent | kVerticalScrollEvent | kInSystemGroup | kDefaultPrevented,
|
||||
kDOMMouseScrollEvent | kHorizontalScrollEvent,
|
||||
kDOMMouseScrollEvent | kHorizontalScrollEvent | kInSystemGroup,
|
||||
kMozMousePixelScrollEvent | kHorizontalScrollEvent,
|
||||
kMozMousePixelScrollEvent | kHorizontalScrollEvent | kInSystemGroup,
|
||||
kWheelEvent | kInSystemGroup | kDefaultPrevented],
|
||||
resultEvents: [],
|
||||
doPreventDefaultAt: kDOMMouseScrollEvent | kVerticalScrollEvent | kInSystemGroup,
|
||||
},
|
||||
{
|
||||
description: "Testing the order of the events, calling preventDefault() at system group MozMousePixelScroll event",
|
||||
expectedEvents: [ kWheelEvent,
|
||||
kDOMMouseScrollEvent | kVerticalScrollEvent,
|
||||
kDOMMouseScrollEvent | kVerticalScrollEvent | kInSystemGroup,
|
||||
kMozMousePixelScrollEvent | kVerticalScrollEvent,
|
||||
kMozMousePixelScrollEvent | kVerticalScrollEvent | kInSystemGroup,
|
||||
kDOMMouseScrollEvent | kHorizontalScrollEvent,
|
||||
kDOMMouseScrollEvent | kHorizontalScrollEvent | kInSystemGroup,
|
||||
kMozMousePixelScrollEvent | kHorizontalScrollEvent,
|
||||
kMozMousePixelScrollEvent | kHorizontalScrollEvent | kInSystemGroup,
|
||||
kWheelEvent | kInSystemGroup | kDefaultPrevented],
|
||||
resultEvents: [],
|
||||
doPreventDefaultAt: kMozMousePixelScrollEvent | kVerticalScrollEvent | kInSystemGroup,
|
||||
},
|
||||
];
|
||||
|
||||
function getEventDescription(aEvent)
|
||||
{
|
||||
var result = "";
|
||||
if (aEvent & kWheelEvent) {
|
||||
result = "wheel"
|
||||
} else {
|
||||
if (aEvent & kDOMMouseScrollEvent) {
|
||||
result = "DOMMouseScroll";
|
||||
} else if (aEvent & kMozMousePixelScrollEvent) {
|
||||
result = "MozMousePixelScroll";
|
||||
}
|
||||
if (aEvent & kVerticalScrollEvent) {
|
||||
result += ", vertical";
|
||||
} else {
|
||||
result += ", horizontal";
|
||||
}
|
||||
}
|
||||
if (aEvent & kInSystemGroup) {
|
||||
result += ", system group";
|
||||
}
|
||||
if (aEvent & kDefaultPrevented) {
|
||||
result += ", defaultPrevented";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function pushEvent(aEvent, aIsSystemGroup)
|
||||
{
|
||||
var event = 0;
|
||||
if (aEvent.type == "wheel") {
|
||||
event = kWheelEvent;
|
||||
} else {
|
||||
if (aEvent.type == "DOMMouseScroll") {
|
||||
event = kDOMMouseScrollEvent;
|
||||
} else if (aEvent.type == "MozMousePixelScroll") {
|
||||
event = kMozMousePixelScrollEvent;
|
||||
}
|
||||
if (aEvent.axis == MouseScrollEvent.HORIZONTAL_AXIS) {
|
||||
event |= kHorizontalScrollEvent;
|
||||
} else {
|
||||
event |= kVerticalScrollEvent;
|
||||
}
|
||||
}
|
||||
if (aIsSystemGroup) {
|
||||
event |= kInSystemGroup;
|
||||
}
|
||||
if (aEvent.defaultPrevented) {
|
||||
event |= kDefaultPrevented;
|
||||
}
|
||||
currentTest.resultEvents.push(event);
|
||||
return event;
|
||||
}
|
||||
|
||||
function handler(aEvent)
|
||||
{
|
||||
if (pushEvent(aEvent, false) == currentTest.doPreventDefaultAt) {
|
||||
aEvent.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
function systemHandler(aEvent)
|
||||
{
|
||||
if (pushEvent(aEvent, true) == currentTest.doPreventDefaultAt) {
|
||||
aEvent.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener("wheel", handler, true);
|
||||
window.addEventListener("DOMMouseScroll", handler, true);
|
||||
window.addEventListener("MozMousePixelScroll", handler, true);
|
||||
|
||||
SpecialPowers.addSystemEventListener(window, "wheel", systemHandler, true);
|
||||
SpecialPowers.addSystemEventListener(window, "DOMMouseScroll", systemHandler, true);
|
||||
SpecialPowers.addSystemEventListener(window, "MozMousePixelScroll", systemHandler, true);
|
||||
|
||||
for (var i = 0; i < kTests.length; i++) {
|
||||
currentTest = kTests[i];
|
||||
synthesizeWheel(gScrollableElement, 10, 10,
|
||||
{ deltaMode: WheelEvent.DOM_DELTA_LINE, deltaX: 1.0, deltaY: 1.0 });
|
||||
|
||||
for (var j = 0; j < currentTest.expectedEvents.length; j++) {
|
||||
if (currentTest.resultEvents.length == j) {
|
||||
ok(false, currentTest.description + ": " +
|
||||
getEventDescription(currentTest.expectedEvents[j]) + " wasn't fired");
|
||||
break;
|
||||
}
|
||||
is(getEventDescription(currentTest.resultEvents[j]),
|
||||
getEventDescription(currentTest.expectedEvents[j]),
|
||||
currentTest.description + ": " + (j + 1) + "th event is mismatched");
|
||||
}
|
||||
if (currentTest.expectedEvents.length < currentTest.resultEvents.length) {
|
||||
ok(false, currentTest.description + ": " +
|
||||
getEventDescription(currentTest.resultEvents[currentTest.expectedEvents.length]) +
|
||||
" was fired unexpectedly");
|
||||
}
|
||||
}
|
||||
|
||||
window.removeEventListener("wheel", handler, true);
|
||||
window.removeEventListener("DOMMouseScroll", handler, true);
|
||||
window.removeEventListener("MozMousePixelScroll", handler, true);
|
||||
|
||||
SpecialPowers.removeSystemEventListener(window, "wheel", systemHandler, true);
|
||||
SpecialPowers.removeSystemEventListener(window, "DOMMouseScroll", systemHandler, true);
|
||||
SpecialPowers.removeSystemEventListener(window, "MozMousePixelScroll", systemHandler, true);
|
||||
}
|
||||
|
||||
function runTests()
|
||||
{
|
||||
SpecialPowers.setIntPref("mousewheel.default.delta_multiplier_x", 100);
|
||||
SpecialPowers.setIntPref("mousewheel.default.delta_multiplier_y", 100);
|
||||
SpecialPowers.setIntPref("mousewheel.default.delta_multiplier_z", 100);
|
||||
SpecialPowers.setIntPref("mousewheel.with_alt.delta_multiplier_x", 100);
|
||||
SpecialPowers.setIntPref("mousewheel.with_alt.delta_multiplier_y", 100);
|
||||
SpecialPowers.setIntPref("mousewheel.with_alt.delta_multiplier_z", 100);
|
||||
SpecialPowers.setIntPref("mousewheel.with_control.delta_multiplier_x", 100);
|
||||
SpecialPowers.setIntPref("mousewheel.with_control.delta_multiplier_y", 100);
|
||||
SpecialPowers.setIntPref("mousewheel.with_control.delta_multiplier_z", 100);
|
||||
SpecialPowers.setIntPref("mousewheel.with_meta.delta_multiplier_x", 100);
|
||||
SpecialPowers.setIntPref("mousewheel.with_meta.delta_multiplier_y", 100);
|
||||
SpecialPowers.setIntPref("mousewheel.with_meta.delta_multiplier_z", 100);
|
||||
SpecialPowers.setIntPref("mousewheel.with_shift.delta_multiplier_x", 100);
|
||||
SpecialPowers.setIntPref("mousewheel.with_shift.delta_multiplier_y", 100);
|
||||
SpecialPowers.setIntPref("mousewheel.with_shift.delta_multiplier_z", 100);
|
||||
SpecialPowers.setIntPref("mousewheel.with_win.delta_multiplier_x", 100);
|
||||
SpecialPowers.setIntPref("mousewheel.with_win.delta_multiplier_y", 100);
|
||||
SpecialPowers.setIntPref("mousewheel.with_win.delta_multiplier_z", 100);
|
||||
|
||||
prepareScrollUnits();
|
||||
testMakingUntrustedEvent();
|
||||
testDeltaMultiplierPrefs();
|
||||
testDispatchingUntrustEvent();
|
||||
testEventOrder();
|
||||
|
||||
SpecialPowers.clearUserPref("mousewheel.default.delta_multiplier_x");
|
||||
SpecialPowers.clearUserPref("mousewheel.default.delta_multiplier_y");
|
||||
SpecialPowers.clearUserPref("mousewheel.default.delta_multiplier_z");
|
||||
SpecialPowers.clearUserPref("mousewheel.with_alt.delta_multiplier_x");
|
||||
SpecialPowers.clearUserPref("mousewheel.with_alt.delta_multiplier_y");
|
||||
SpecialPowers.clearUserPref("mousewheel.with_alt.delta_multiplier_z");
|
||||
SpecialPowers.clearUserPref("mousewheel.with_control.delta_multiplier_x");
|
||||
SpecialPowers.clearUserPref("mousewheel.with_control.delta_multiplier_y");
|
||||
SpecialPowers.clearUserPref("mousewheel.with_control.delta_multiplier_z");
|
||||
SpecialPowers.clearUserPref("mousewheel.with_meta.delta_multiplier_x");
|
||||
SpecialPowers.clearUserPref("mousewheel.with_meta.delta_multiplier_y");
|
||||
SpecialPowers.clearUserPref("mousewheel.with_meta.delta_multiplier_z");
|
||||
SpecialPowers.clearUserPref("mousewheel.with_shift.delta_multiplier_x");
|
||||
SpecialPowers.clearUserPref("mousewheel.with_shift.delta_multiplier_y");
|
||||
SpecialPowers.clearUserPref("mousewheel.with_shift.delta_multiplier_z");
|
||||
SpecialPowers.clearUserPref("mousewheel.with_win.delta_multiplier_x");
|
||||
SpecialPowers.clearUserPref("mousewheel.with_win.delta_multiplier_y");
|
||||
SpecialPowers.clearUserPref("mousewheel.with_win.delta_multiplier_z");
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -451,16 +451,16 @@ try {
|
||||
} catch(exp) {
|
||||
ex = true;
|
||||
}
|
||||
ok(ex, "First parameter is required!");
|
||||
ok(ex, "MouseEvent: First parameter is required!");
|
||||
ex = false;
|
||||
|
||||
e = new MouseEvent("hello");
|
||||
ok(e.type, "hello", "Wrong event type!");
|
||||
ok(!e.isTrusted, "Event shouldn't be trusted!");
|
||||
ok(!e.bubbles, "Event shouldn't bubble!");
|
||||
ok(!e.cancelable, "Event shouldn't be cancelable!");
|
||||
ok(e.type, "hello", "MouseEvent: Wrong event type!");
|
||||
ok(!e.isTrusted, "MouseEvent: Event shouldn't be trusted!");
|
||||
ok(!e.bubbles, "MouseEvent: Event shouldn't bubble!");
|
||||
ok(!e.cancelable, "MouseEvent: Event shouldn't be cancelable!");
|
||||
document.dispatchEvent(e);
|
||||
is(receivedEvent, e, "Wrong event!");
|
||||
is(receivedEvent, e, "MouseEvent: Wrong event!");
|
||||
|
||||
var mouseEventProps =
|
||||
[ { screenX: 0 },
|
||||
@ -494,7 +494,7 @@ var testProps =
|
||||
var defaultMouseEventValues = {};
|
||||
for (var i = 0; i < mouseEventProps.length; ++i) {
|
||||
for (prop in mouseEventProps[i]) {
|
||||
ok(prop in e, "MouseEvent doesn't have property " + prop + "!");
|
||||
ok(prop in e, "MouseEvent: MouseEvent doesn't have property " + prop + "!");
|
||||
defaultMouseEventValues[prop] = mouseEventProps[i][prop];
|
||||
}
|
||||
}
|
||||
@ -504,9 +504,86 @@ while (testProps.length) {
|
||||
e = new MouseEvent("foo", p);
|
||||
for (var def in defaultMouseEventValues) {
|
||||
if (!(def in p)) {
|
||||
is(e[def], defaultMouseEventValues[def], "Wrong default value for " + def + "!");
|
||||
is(e[def], defaultMouseEventValues[def],
|
||||
"MouseEvent: Wrong default value for " + def + "!");
|
||||
} else {
|
||||
is(e[def], p[def], "Wrong event init value for " + def + "!");
|
||||
is(e[def], p[def], "MouseEvent: Wrong event init value for " + def + "!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WheelEvent
|
||||
|
||||
try {
|
||||
e = new WheelEvent();
|
||||
} catch(exp) {
|
||||
ex = true;
|
||||
}
|
||||
ok(ex, "WheelEvent: First parameter is required!");
|
||||
ex = false;
|
||||
|
||||
e = new WheelEvent("hello");
|
||||
ok(e.type, "hello", "WheelEvent: Wrong event type!");
|
||||
ok(!e.isTrusted, "WheelEvent: Event shouldn't be trusted!");
|
||||
ok(!e.bubbles, "WheelEvent: Event shouldn't bubble!");
|
||||
ok(!e.cancelable, "WheelEvent: Event shouldn't be cancelable!");
|
||||
document.dispatchEvent(e);
|
||||
is(receivedEvent, e, "WheelEvent: Wrong event!");
|
||||
|
||||
var wheelEventProps =
|
||||
[ { screenX: 0 },
|
||||
{ screenY: 0 },
|
||||
{ clientX: 0 },
|
||||
{ clientY: 0 },
|
||||
{ ctrlKey: false },
|
||||
{ shiftKey: false },
|
||||
{ altKey: false },
|
||||
{ metaKey: false },
|
||||
{ button: 0 },
|
||||
{ buttons: 0 },
|
||||
{ relatedTarget: null },
|
||||
{ deltaX: 0.0 },
|
||||
{ deltaY: 0.0 },
|
||||
{ deltaZ: 0.0 },
|
||||
{ deltaMode: 0 }
|
||||
];
|
||||
|
||||
var testWheelProps =
|
||||
[
|
||||
{ screenX: 1 },
|
||||
{ screenY: 2 },
|
||||
{ clientX: 3 },
|
||||
{ clientY: 4 },
|
||||
{ ctrlKey: true },
|
||||
{ shiftKey: true },
|
||||
{ altKey: true },
|
||||
{ metaKey: true },
|
||||
{ button: 5 },
|
||||
{ buttons: 6 },
|
||||
{ relatedTarget: window },
|
||||
{ deltaX: 7.8 },
|
||||
{ deltaY: 9.1 },
|
||||
{ deltaZ: 2.3 },
|
||||
{ deltaMode: 4 }
|
||||
];
|
||||
|
||||
var defaultWheelEventValues = {};
|
||||
for (var i = 0; i < wheelEventProps.length; ++i) {
|
||||
for (prop in wheelEventProps[i]) {
|
||||
ok(prop in e, "WheelEvent: WheelEvent doesn't have property " + prop + "!");
|
||||
defaultWheelEventValues[prop] = wheelEventProps[i][prop];
|
||||
}
|
||||
}
|
||||
|
||||
while (testWheelProps.length) {
|
||||
var p = testWheelProps.shift();
|
||||
e = new WheelEvent("foo", p);
|
||||
for (var def in defaultWheelEventValues) {
|
||||
if (!(def in p)) {
|
||||
is(e[def], defaultWheelEventValues[def],
|
||||
"WheelEvent: Wrong default value for " + def + "!");
|
||||
} else {
|
||||
is(e[def], p[def], "WheelEvent: Wrong event init value for " + def + "!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
1313
content/events/test/test_moz_mouse_pixel_scroll_event.html
Normal file
1313
content/events/test/test_moz_mouse_pixel_scroll_event.html
Normal file
File diff suppressed because it is too large
Load Diff
31
content/events/test/test_wheel_default_action.html
Normal file
31
content/events/test/test_wheel_default_action.html
Normal file
@ -0,0 +1,31 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for default action of WheelEvent</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.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">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var subWin = window.open("window_wheel_default_action.html", "_blank",
|
||||
"width=500,height=500,scrollbars=yes");
|
||||
|
||||
function finish()
|
||||
{
|
||||
subWin.close();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
1014
content/events/test/window_wheel_default_action.html
Normal file
1014
content/events/test/window_wheel_default_action.html
Normal file
File diff suppressed because it is too large
Load Diff
@ -53,6 +53,7 @@
|
||||
|
||||
#include "nsHTMLParts.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "mozilla/dom/DirectionalityUtils.h"
|
||||
#include "nsString.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "nsGkAtoms.h"
|
||||
@ -96,6 +97,7 @@
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla::directionality;
|
||||
|
||||
class nsINodeInfo;
|
||||
class nsIDOMNodeList;
|
||||
@ -1687,6 +1689,24 @@ nsGenericHTMLElement::UpdateEditableState(bool aNotify)
|
||||
nsStyledElement::UpdateEditableState(aNotify);
|
||||
}
|
||||
|
||||
nsEventStates
|
||||
nsGenericHTMLElement::IntrinsicState() const
|
||||
{
|
||||
nsEventStates state = nsGenericHTMLElementBase::IntrinsicState();
|
||||
|
||||
if (GetDirectionality() == eDir_RTL) {
|
||||
state |= NS_EVENT_STATE_RTL;
|
||||
state &= ~NS_EVENT_STATE_LTR;
|
||||
} else { // at least for HTML, directionality is exclusively LTR or RTL
|
||||
NS_ASSERTION(GetDirectionality() == eDir_LTR,
|
||||
"HTML element's directionality must be either RTL or LTR");
|
||||
state |= NS_EVENT_STATE_LTR;
|
||||
state &= ~NS_EVENT_STATE_RTL;
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsGenericHTMLElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
nsIContent* aBindingParent,
|
||||
@ -1889,6 +1909,20 @@ nsGenericHTMLElement::AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
|
||||
else if (aNotify && aName == nsGkAtoms::spellcheck) {
|
||||
SyncEditorsOnSubtree(this);
|
||||
}
|
||||
else if (aName == nsGkAtoms::dir) {
|
||||
Directionality dir;
|
||||
if (aValue &&
|
||||
(aValue->Equals(nsGkAtoms::ltr, eIgnoreCase) ||
|
||||
aValue->Equals(nsGkAtoms::rtl, eIgnoreCase))) {
|
||||
SetHasValidDir();
|
||||
dir = aValue->Equals(nsGkAtoms::rtl, eIgnoreCase) ? eDir_RTL : eDir_LTR;
|
||||
SetDirectionality(dir, aNotify);
|
||||
} else {
|
||||
ClearHasValidDir();
|
||||
dir = RecomputeDirectionality(this, aNotify);
|
||||
}
|
||||
SetDirectionalityOnDescendants(this, dir, aNotify);
|
||||
}
|
||||
}
|
||||
|
||||
return nsGenericHTMLElementBase::AfterSetAttr(aNamespaceID, aName,
|
||||
|
@ -49,6 +49,8 @@ public:
|
||||
{
|
||||
NS_ASSERTION(mNodeInfo->NamespaceID() == kNameSpaceID_XHTML,
|
||||
"Unexpected namespace");
|
||||
AddStatesSilently(NS_EVENT_STATE_LTR);
|
||||
SetFlags(NODE_HAS_DIRECTION_LTR);
|
||||
}
|
||||
|
||||
/** Typesafe, non-refcounting cast from nsIContent. Cheaper than QI. **/
|
||||
@ -202,6 +204,8 @@ public:
|
||||
|
||||
virtual void UpdateEditableState(bool aNotify);
|
||||
|
||||
virtual nsEventStates IntrinsicState() const;
|
||||
|
||||
// Helper for setting our editable flag and notifying
|
||||
void DoSetEditableFlag(bool aEditable, bool aNotify) {
|
||||
SetEditableFlag(aEditable);
|
||||
|
@ -116,7 +116,8 @@ nsHTMLAudioElement::MozSetup(PRUint32 aChannels, PRUint32 aRate)
|
||||
}
|
||||
|
||||
mAudioStream = nsAudioStream::AllocateStream();
|
||||
nsresult rv = mAudioStream->Init(aChannels, aRate);
|
||||
nsresult rv = mAudioStream->Init(aChannels, aRate,
|
||||
nsAudioStream::FORMAT_FLOAT32);
|
||||
if (NS_FAILED(rv)) {
|
||||
mAudioStream->Shutdown();
|
||||
mAudioStream = nullptr;
|
||||
|
@ -359,11 +359,12 @@ nsHTMLCanvasElement::ToDataURLImpl(const nsAString& aMimeType,
|
||||
aDataURL = NS_LITERAL_STRING("data:") + type +
|
||||
NS_LITERAL_STRING(";base64,");
|
||||
|
||||
PRUint32 count;
|
||||
PRUint64 count;
|
||||
rv = stream->Available(&count);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(count <= PR_UINT32_MAX, NS_ERROR_FILE_TOO_BIG);
|
||||
|
||||
return Base64EncodeInputStream(stream, aDataURL, count, aDataURL.Length());
|
||||
return Base64EncodeInputStream(stream, aDataURL, (PRUint32)count, aDataURL.Length());
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -398,17 +399,18 @@ nsHTMLCanvasElement::MozGetAsFileImpl(const nsAString& aName,
|
||||
type.AssignLiteral("image/png");
|
||||
}
|
||||
|
||||
PRUint32 imgSize;
|
||||
PRUint64 imgSize;
|
||||
rv = stream->Available(&imgSize);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(imgSize <= PR_UINT32_MAX, NS_ERROR_FILE_TOO_BIG);
|
||||
|
||||
void* imgData = nullptr;
|
||||
rv = NS_ReadInputStreamToBuffer(stream, &imgData, imgSize);
|
||||
rv = NS_ReadInputStreamToBuffer(stream, &imgData, (PRUint32)imgSize);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// The DOMFile takes ownership of the buffer
|
||||
nsRefPtr<nsDOMMemoryFile> file =
|
||||
new nsDOMMemoryFile(imgData, imgSize, aName, type);
|
||||
new nsDOMMemoryFile(imgData, (PRUint32)imgSize, aName, type);
|
||||
|
||||
file.forget(aResult);
|
||||
return NS_OK;
|
||||
|
@ -2204,7 +2204,7 @@ nsHTMLMediaElement::CanHandleMediaType(const char* aMIMEType,
|
||||
}
|
||||
#endif
|
||||
#ifdef MOZ_MEDIA_PLUGINS
|
||||
if (GetMediaPluginHost()->FindDecoder(nsDependentCString(aMIMEType), aCodecList))
|
||||
if (IsMediaPluginsEnabled() && GetMediaPluginHost()->FindDecoder(nsDependentCString(aMIMEType), aCodecList))
|
||||
return CANPLAY_MAYBE;
|
||||
#endif
|
||||
return CANPLAY_NO;
|
||||
@ -2230,7 +2230,7 @@ bool nsHTMLMediaElement::ShouldHandleMediaType(const char* aMIMEType)
|
||||
return true;
|
||||
#endif
|
||||
#ifdef MOZ_MEDIA_PLUGINS
|
||||
if (GetMediaPluginHost()->FindDecoder(nsDependentCString(aMIMEType), NULL))
|
||||
if (IsMediaPluginsEnabled() && GetMediaPluginHost()->FindDecoder(nsDependentCString(aMIMEType), NULL))
|
||||
return true;
|
||||
#endif
|
||||
// We should not return true for Wave types, since there are some
|
||||
@ -2346,7 +2346,7 @@ nsHTMLMediaElement::CreateDecoder(const nsACString& aType)
|
||||
}
|
||||
#endif
|
||||
#ifdef MOZ_MEDIA_PLUGINS
|
||||
if (GetMediaPluginHost()->FindDecoder(aType, NULL)) {
|
||||
if (IsMediaPluginsEnabled() && GetMediaPluginHost()->FindDecoder(aType, NULL)) {
|
||||
nsRefPtr<nsMediaPluginDecoder> decoder = new nsMediaPluginDecoder(aType);
|
||||
if (decoder->Init(this)) {
|
||||
return decoder.forget();
|
||||
|
@ -517,6 +517,12 @@ nsHTMLObjectElement::GetAttributeMappingFunction() const
|
||||
void
|
||||
nsHTMLObjectElement::StartObjectLoad(bool aNotify)
|
||||
{
|
||||
// BindToTree can call us asynchronously, and we may be removed from the tree
|
||||
// in the interim
|
||||
if (!IsInDoc() || !OwnerDoc()->IsActive()) {
|
||||
return;
|
||||
}
|
||||
|
||||
LoadObject(aNotify);
|
||||
SetIsNetworkCreated(false);
|
||||
}
|
||||
|
@ -465,6 +465,12 @@ nsHTMLSharedObjectElement::GetAttributeMappingFunction() const
|
||||
void
|
||||
nsHTMLSharedObjectElement::StartObjectLoad(bool aNotify)
|
||||
{
|
||||
// BindToTree can call us asynchronously, and we may be removed from the tree
|
||||
// in the interim
|
||||
if (!IsInDoc() || !OwnerDoc()->IsActive()) {
|
||||
return;
|
||||
}
|
||||
|
||||
LoadObject(aNotify);
|
||||
SetIsNetworkCreated(false);
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ include $(DEPTH)/config/autoconf.mk
|
||||
MODULE = content
|
||||
LIBRARY_NAME = gkconhtmldoc_s
|
||||
LIBXUL_LIBRARY = 1
|
||||
|
||||
FAIL_ON_WARNINGS = 1
|
||||
|
||||
CPPSRCS = \
|
||||
nsHTMLContentSink.cpp \
|
||||
|
@ -13,6 +13,7 @@ include $(DEPTH)/config/autoconf.mk
|
||||
MODULE = content
|
||||
LIBRARY_NAME = gkcontentmathml_s
|
||||
LIBXUL_LIBRARY = 1
|
||||
FAIL_ON_WARNINGS = 1
|
||||
|
||||
CPPSRCS = \
|
||||
nsMathMLElement.cpp \
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user