mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge mozilla-central and b2g-inbound
This commit is contained in:
commit
bac7c78535
@ -19,7 +19,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="508c85713fdf35eb2b3c8e8340e1d2ee306e6aec"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="28e9b207fa9a6f42ad94459ddb3057f7e240f796"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="dbb66e540194a187326cece28ae0b51cdd500184"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="8e4420c0c5c8e8c8e58a000278a7129403769f96"/>
|
||||
|
@ -17,7 +17,7 @@
|
||||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="508c85713fdf35eb2b3c8e8340e1d2ee306e6aec"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="28e9b207fa9a6f42ad94459ddb3057f7e240f796"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="dbb66e540194a187326cece28ae0b51cdd500184"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="cabebb87fcd32f8596af08e6b5e80764ee0157dd"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="276ce45e78b09c4a4ee643646f691d22804754c1">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="508c85713fdf35eb2b3c8e8340e1d2ee306e6aec"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="28e9b207fa9a6f42ad94459ddb3057f7e240f796"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="dbb66e540194a187326cece28ae0b51cdd500184"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
@ -19,7 +19,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="508c85713fdf35eb2b3c8e8340e1d2ee306e6aec"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="28e9b207fa9a6f42ad94459ddb3057f7e240f796"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="dbb66e540194a187326cece28ae0b51cdd500184"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="8e4420c0c5c8e8c8e58a000278a7129403769f96"/>
|
||||
|
@ -17,7 +17,7 @@
|
||||
</project>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="508c85713fdf35eb2b3c8e8340e1d2ee306e6aec"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="28e9b207fa9a6f42ad94459ddb3057f7e240f796"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="dbb66e540194a187326cece28ae0b51cdd500184"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="cabebb87fcd32f8596af08e6b5e80764ee0157dd"/>
|
||||
|
@ -4,6 +4,6 @@
|
||||
"remote": "",
|
||||
"branch": ""
|
||||
},
|
||||
"revision": "489903115b8067c6d565e37626213da4ba592331",
|
||||
"revision": "d6cf58c5909ec588ac43c88358181201e5f581ad",
|
||||
"repo_path": "/integration/gaia-central"
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="508c85713fdf35eb2b3c8e8340e1d2ee306e6aec"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="28e9b207fa9a6f42ad94459ddb3057f7e240f796"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="dbb66e540194a187326cece28ae0b51cdd500184"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="508c85713fdf35eb2b3c8e8340e1d2ee306e6aec"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="28e9b207fa9a6f42ad94459ddb3057f7e240f796"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="dbb66e540194a187326cece28ae0b51cdd500184"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
@ -17,7 +17,7 @@
|
||||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="508c85713fdf35eb2b3c8e8340e1d2ee306e6aec"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="28e9b207fa9a6f42ad94459ddb3057f7e240f796"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="dbb66e540194a187326cece28ae0b51cdd500184"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="cabebb87fcd32f8596af08e6b5e80764ee0157dd"/>
|
||||
|
@ -17,7 +17,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="508c85713fdf35eb2b3c8e8340e1d2ee306e6aec"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="28e9b207fa9a6f42ad94459ddb3057f7e240f796"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="dbb66e540194a187326cece28ae0b51cdd500184"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
@ -56,7 +56,8 @@ this.PermissionsInstaller = {
|
||||
* A function called if an error occurs
|
||||
* @returns void
|
||||
**/
|
||||
installPermissions: function installPermissions(aApp, aIsReinstall, aOnError) {
|
||||
installPermissions: function installPermissions(aApp, aIsReinstall, aOnError,
|
||||
aIsSystemUpdate) {
|
||||
try {
|
||||
let newManifest = new ManifestHelper(aApp.manifest, aApp.origin);
|
||||
if (!newManifest.permissions && !aIsReinstall) {
|
||||
@ -145,6 +146,10 @@ this.PermissionsInstaller = {
|
||||
expandPermissions(permName,
|
||||
newManifest.permissions[permName].access);
|
||||
for (let idx in expandedPermNames) {
|
||||
|
||||
let isPromptPermission =
|
||||
PermissionsTable[permName][appStatus] === PROMPT_ACTION;
|
||||
|
||||
// We silently upgrade the permission to whatever the permission
|
||||
// is for certified apps (ALLOW or PROMPT) only if the
|
||||
// following holds true:
|
||||
@ -152,15 +157,26 @@ this.PermissionsInstaller = {
|
||||
// * The permission that would be granted is PROMPT
|
||||
// * The app is privileged
|
||||
let permission =
|
||||
aApp.isPreinstalled &&
|
||||
PermissionsTable[permName][appStatus] === PROMPT_ACTION &&
|
||||
aApp.isPreinstalled && isPromptPermission &&
|
||||
appStatus === "privileged"
|
||||
? PermissionsTable[permName]["certified"]
|
||||
: PermissionsTable[permName][appStatus];
|
||||
|
||||
this._setPermission(expandedPermNames[idx],
|
||||
PERM_TO_STRING[permission],
|
||||
aApp);
|
||||
let permValue = PERM_TO_STRING[permission];
|
||||
if (!aIsSystemUpdate && isPromptPermission) {
|
||||
// If it's not a system update, then we should keep the prompt
|
||||
// permissions that have been granted or denied previously.
|
||||
permValue =
|
||||
PermissionSettingsModule.getPermission(permName,
|
||||
aApp.manifestURL,
|
||||
aApp.origin,
|
||||
false);
|
||||
if (permValue === "unknown") {
|
||||
permValue = PERM_TO_STRING[permission];
|
||||
}
|
||||
}
|
||||
|
||||
this._setPermission(expandedPermNames[idx], permValue, aApp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -351,7 +351,7 @@ this.DOMApplicationRegistry = {
|
||||
results[0].manifest, app.appStatus);
|
||||
}),
|
||||
|
||||
updatePermissionsForApp: function(aId, aIsPreinstalled) {
|
||||
updatePermissionsForApp: function(aId, aIsPreinstalled, aIsSystemUpdate) {
|
||||
if (!this.webapps[aId]) {
|
||||
return;
|
||||
}
|
||||
@ -366,7 +366,8 @@ this.DOMApplicationRegistry = {
|
||||
manifest: data.manifest,
|
||||
manifestURL: this.webapps[aId].manifestURL,
|
||||
origin: this.webapps[aId].origin,
|
||||
isPreinstalled: aIsPreinstalled
|
||||
isPreinstalled: aIsPreinstalled,
|
||||
isSystemUpdate: aIsSystemUpdate
|
||||
}, true, function() {
|
||||
debug("Error installing permissions for " + aId);
|
||||
});
|
||||
@ -598,7 +599,8 @@ this.DOMApplicationRegistry = {
|
||||
continue;
|
||||
}
|
||||
this.updateOfflineCacheForApp(id);
|
||||
this.updatePermissionsForApp(id, isPreinstalled);
|
||||
this.updatePermissionsForApp(id, isPreinstalled,
|
||||
true /* isSystemUpdate */);
|
||||
}
|
||||
// Need to update the persisted list of apps since
|
||||
// installPreinstalledApp() removes the ones failing to install.
|
||||
|
@ -4,6 +4,12 @@
|
||||
"size" : PACKAGESIZETOKEN,
|
||||
"package_path": "PACKAGEPATHTOKEN",
|
||||
"description": "Updated even faster than Firefox, just to annoy slashdotters",
|
||||
"permissions": {
|
||||
"geolocation": {},
|
||||
"audio-capture": {},
|
||||
"video-capture": {},
|
||||
"downloads": {}
|
||||
},
|
||||
"launch_path": "tests/dom/apps/tests/file_packaged_app.sjs",
|
||||
"developer": {
|
||||
"name": "DEVELOPERTOKEN",
|
||||
|
@ -55,7 +55,7 @@ function checkForUpdate(aExpected, aOnSuccess, aOnApplied, aOnDownloadError,
|
||||
|
||||
function checkLastAppState(aMiniManifestURL, aExpectedReady, aExpectedDownload,
|
||||
aExpectedVersion, aCb) {
|
||||
ok(true, aExpectedReady ? "App downloaded" : "App download applied");
|
||||
info(aExpectedReady ? "App downloaded" : "App download applied");
|
||||
var expected = {
|
||||
name: PackagedTestHelper.gAppName,
|
||||
manifestURL: aMiniManifestURL,
|
||||
@ -91,26 +91,68 @@ function updateApp(aExpectedReady, aPreviousVersion, aNextVersion) {
|
||||
|
||||
}
|
||||
|
||||
var initialPermissionState = {
|
||||
"geolocation": "prompt",
|
||||
"audio-capture": "prompt",
|
||||
"video-capture": "prompt",
|
||||
"downloads": "deny"
|
||||
}
|
||||
|
||||
var permissionsToSet = {
|
||||
"geolocation": "allow",
|
||||
"audio-capture": "deny"
|
||||
}
|
||||
|
||||
var permissionsToCheck = {
|
||||
"geolocation": "allow",
|
||||
"audio-capture": "deny",
|
||||
"video-capture": "prompt",
|
||||
"downloads": "deny"
|
||||
}
|
||||
|
||||
function validatePermissions(aList, aDontFail) {
|
||||
var gApp = PackagedTestHelper.gApp;
|
||||
var mozPermissions = window.navigator.mozPermissionSettings;
|
||||
var permission;
|
||||
for (permission in aList) {
|
||||
var permValue = mozPermissions.get(permission, gApp.manifestURL,
|
||||
gApp.origin, false);
|
||||
var wouldFail = permValue != aList[permission];
|
||||
var checkFun = (aDontFail && wouldFail) ? todo_is : is;
|
||||
checkFun(permValue, aList[permission],
|
||||
"Permission " + permission + " should be " + aList[permission]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var steps = [
|
||||
function() {
|
||||
// Set up
|
||||
SpecialPowers.setAllAppsLaunchable(true);
|
||||
SpecialPowers.addPermission("webapps-manage", true, document);
|
||||
ok(true, "Set up");
|
||||
PackagedTestHelper.next();
|
||||
info("Set up");
|
||||
// Note that without useCurrentProfile the permissions just aren't added.
|
||||
SpecialPowers.pushPermissions(
|
||||
[{'type': 'permissions', 'allow': true, 'context': document}],
|
||||
function() {
|
||||
SpecialPowers.pushPrefEnv(
|
||||
{"set": [["dom.mozPermissionSettings.enabled", true],
|
||||
["dom.webapps.useCurrentProfile", true]]},
|
||||
PackagedTestHelper.next);
|
||||
}
|
||||
);
|
||||
},
|
||||
function() {
|
||||
ok(true, "autoConfirmAppInstall");
|
||||
info("autoConfirmAppInstall");
|
||||
SpecialPowers.autoConfirmAppInstall(PackagedTestHelper.next);
|
||||
},
|
||||
function() {
|
||||
PackagedTestHelper.setAppVersion(2, PackagedTestHelper.next);
|
||||
},
|
||||
function() {
|
||||
ok(true, "== TEST == Install packaged app");
|
||||
info("== TEST == Install packaged app");
|
||||
navigator.mozApps.mgmt.oninstall = function(evt) {
|
||||
ok(true, "Got oninstall event");
|
||||
info("Got oninstall event");
|
||||
PackagedTestHelper.gApp = evt.application;
|
||||
PackagedTestHelper.gApp.ondownloaderror = function() {
|
||||
ok(false, "Download error " + PackagedTestHelper.gApp.downloadError.name);
|
||||
@ -124,11 +166,16 @@ var steps = [
|
||||
var request = navigator.mozApps.installPackage(miniManifestURL);
|
||||
request.onerror = PackagedTestHelper.mozAppsError;
|
||||
request.onsuccess = function() {
|
||||
ok(true, "Application installed");
|
||||
info("Application installed");
|
||||
};
|
||||
},
|
||||
function() {
|
||||
ok(true, "== TEST == Check for Update and try to download it without update available");
|
||||
info("== TEST == Permissions installed correctly");
|
||||
validatePermissions(initialPermissionState);
|
||||
PackagedTestHelper.next();
|
||||
},
|
||||
function() {
|
||||
info("== TEST == Check for Update and try to download it without update available");
|
||||
|
||||
function onerror() {
|
||||
is(PackagedTestHelper.gApp.downloadError.name, "NO_DOWNLOAD_AVAILABLE", "Download not available");
|
||||
@ -142,33 +189,63 @@ var steps = [
|
||||
|
||||
checkForUpdate(false, onsuccess, null, onerror, true);
|
||||
},
|
||||
function() {
|
||||
info("== TEST == Remember permissions");
|
||||
var gApp = PackagedTestHelper.gApp;
|
||||
var mozPermissions = window.navigator.mozPermissionSettings;
|
||||
var permission;
|
||||
for (permission in permissionsToSet) {
|
||||
try {
|
||||
window.navigator.mozPermissionSettings.set(permission,
|
||||
permissionsToSet[permission],
|
||||
gApp.manifestURL,
|
||||
gApp.origin, false);
|
||||
} catch (e) {
|
||||
ok(false,
|
||||
"mozPermissionSettings.set failed for " + permission + " - " + e);
|
||||
}
|
||||
}
|
||||
PackagedTestHelper.next();
|
||||
},
|
||||
function() {
|
||||
info("== TEST == Check that the permissions have been saved");
|
||||
// Since the permission API isn't really synchronous, just log any errors
|
||||
// here.
|
||||
validatePermissions(permissionsToCheck, true /*dontFail*/);
|
||||
PackagedTestHelper.next();
|
||||
},
|
||||
function() {
|
||||
PackagedTestHelper.setAppVersion(3, PackagedTestHelper.next);
|
||||
},
|
||||
function() {
|
||||
ok(true, "== TEST == Update packaged app");
|
||||
info("== TEST == Update packaged app");
|
||||
updateApp(true, 2, 3);
|
||||
},
|
||||
function() {
|
||||
ok(true, "== TEST == Check for Update after getting a new package");
|
||||
info("== TEST == Check that saved permissions were kept");
|
||||
validatePermissions(permissionsToCheck);
|
||||
PackagedTestHelper.next();
|
||||
},
|
||||
function() {
|
||||
info("== TEST == Check for Update after getting a new package");
|
||||
checkForUpdate(false);
|
||||
},
|
||||
function() {
|
||||
PackagedTestHelper.setAppVersion(4, PackagedTestHelper.next, true);
|
||||
},
|
||||
function() {
|
||||
ok(true, "== TEST == Update packaged app - same package");
|
||||
info("== TEST == Update packaged app - same package");
|
||||
updateApp(false, 3, 3);
|
||||
},
|
||||
function() {
|
||||
ok(true, "== TEST == Check for Update after getting the same package");
|
||||
info("== TEST == Check for Update after getting the same package");
|
||||
checkForUpdate(false);
|
||||
},
|
||||
function() {
|
||||
PackagedTestHelper.setAppVersion(1, PackagedTestHelper.next);
|
||||
},
|
||||
function() {
|
||||
ok(true, "== TEST == Update packaged app - Updating a pending app");
|
||||
info("== TEST == Update packaged app - Updating a pending app");
|
||||
miniManifestURL = PackagedTestHelper.gSJS +
|
||||
"?getManifest=true" +
|
||||
"&appName=arandomname" +
|
||||
@ -180,7 +257,7 @@ var steps = [
|
||||
checkForUpdate(false, null, null, null, false,
|
||||
function (request) {
|
||||
if (request.error.name === "PENDING_APP_NOT_UPDATABLE") {
|
||||
ok(true, "Got expected PENDING_APP_NOT_UPDATEABLE");
|
||||
info("Got expected PENDING_APP_NOT_UPDATEABLE");
|
||||
} else {
|
||||
ok(false, "Got unexpected " + request.error.name);
|
||||
}
|
||||
@ -189,7 +266,7 @@ var steps = [
|
||||
});
|
||||
},
|
||||
function() {
|
||||
ok(true, "all done!\n");
|
||||
info("all done!\n");
|
||||
PackagedTestHelper.finish();
|
||||
}
|
||||
];
|
||||
|
15
layout/base/tests/marionette/manifest.ini
Normal file
15
layout/base/tests/marionette/manifest.ini
Normal file
@ -0,0 +1,15 @@
|
||||
[DEFAULT]
|
||||
; true if the test requires an emulator, otherwise false
|
||||
qemu = false
|
||||
|
||||
; true if the test is compatible with the browser, otherwise false
|
||||
browser = true
|
||||
|
||||
; true if the test is compatible with b2g, otherwise false
|
||||
b2g = true
|
||||
|
||||
; true if the test should be skipped
|
||||
skip = false
|
||||
|
||||
[test_touchcaret.py]
|
||||
b2g = false ; Bug 1020261
|
329
layout/base/tests/marionette/test_touchcaret.py
Normal file
329
layout/base/tests/marionette/test_touchcaret.py
Normal file
@ -0,0 +1,329 @@
|
||||
# -*- coding: utf-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/.
|
||||
|
||||
from by import By
|
||||
from marionette import Actions
|
||||
from marionette_test import MarionetteTestCase
|
||||
|
||||
|
||||
class TouchCaretTest(MarionetteTestCase):
|
||||
_input_selector = (By.ID, 'input')
|
||||
_textarea_selector = (By.ID, 'textarea')
|
||||
_contenteditable_selector = (By.ID, 'contenteditable')
|
||||
_large_expiration_time = 3000 * 20 # 60 seconds
|
||||
|
||||
def setUp(self):
|
||||
# Code to execute before a test is being run.
|
||||
MarionetteTestCase.setUp(self)
|
||||
self.actions = Actions(self.marionette)
|
||||
self.original_expiration_time = self.expiration_time
|
||||
|
||||
def tearDown(self):
|
||||
# Code to execute after a test is being run.
|
||||
self.expiration_time = self.original_expiration_time
|
||||
MarionetteTestCase.tearDown(self)
|
||||
|
||||
@property
|
||||
def expiration_time(self):
|
||||
'Return touch caret expiration time in milliseconds.'
|
||||
return self.marionette.execute_script(
|
||||
'return SpecialPowers.getIntPref("touchcaret.expiration.time");')
|
||||
|
||||
@expiration_time.setter
|
||||
def expiration_time(self, expiration_time):
|
||||
'Set touch caret expiration time in milliseconds.'
|
||||
self.marionette.execute_script(
|
||||
'SpecialPowers.setIntPref("touchcaret.expiration.time", arguments[0]);',
|
||||
script_args=[expiration_time])
|
||||
|
||||
def openTestHtml(self, enabled=True, expiration_time=None):
|
||||
'''Open html for testing and locate elements, enable/disable touch caret, and
|
||||
set touch caret expiration time in milliseconds).
|
||||
|
||||
'''
|
||||
self.marionette.execute_script(
|
||||
'SpecialPowers.setBoolPref("touchcaret.enabled", %s);' %
|
||||
('true' if enabled else 'false'))
|
||||
|
||||
# Set a larger expiration time to avoid intermittent test failures.
|
||||
if expiration_time is not None:
|
||||
self.expiration_time = expiration_time
|
||||
|
||||
test_html = self.marionette.absolute_url('test_touchcaret.html')
|
||||
self.marionette.navigate(test_html)
|
||||
|
||||
self._input = self.marionette.find_element(*self._input_selector)
|
||||
self._textarea = self.marionette.find_element(*self._textarea_selector)
|
||||
self._contenteditable = self.marionette.find_element(*self._contenteditable_selector)
|
||||
|
||||
def is_input_or_textarea(self, element):
|
||||
'''Return True if element is either <input> or <textarea>'''
|
||||
return element.tag_name in ('input', 'textarea')
|
||||
|
||||
def get_js_selection_cmd(self, element):
|
||||
'''Return a command snippet to get selection object.
|
||||
|
||||
If the element is <input> or <textarea>, return the selection object
|
||||
associated with it. Otherwise, return the current selection object.
|
||||
|
||||
Note: "element" must be provided as the first argument to
|
||||
execute_script().
|
||||
|
||||
'''
|
||||
if self.is_input_or_textarea(element):
|
||||
# We must unwrap sel so that DOMRect could be returned to Python
|
||||
# side.
|
||||
return '''var sel = SpecialPowers.wrap(arguments[0]).editor.selection;
|
||||
sel = SpecialPowers.unwrap(sel);'''
|
||||
else:
|
||||
return '''var sel = window.getSelection();'''
|
||||
|
||||
def caret_rect(self, element):
|
||||
'''Return the caret's DOMRect object.
|
||||
|
||||
If the element is either <input> or <textarea>, return the caret's
|
||||
DOMRect within the element. Otherwise, return the DOMRect of the
|
||||
current selected caret.
|
||||
|
||||
'''
|
||||
cmd = self.get_js_selection_cmd(element) +\
|
||||
'''return sel.getRangeAt(0).getClientRects()[0];'''
|
||||
return self.marionette.execute_script(cmd, script_args=[element])
|
||||
|
||||
def caret_location(self, element):
|
||||
'''Return caret's center location by the number of characters offset
|
||||
within the given element.
|
||||
|
||||
Return (x, y) coordinates of the caret's center by the number of
|
||||
characters offset relative to the top left-hand corner of the given
|
||||
element.
|
||||
|
||||
'''
|
||||
rect = self.caret_rect(element)
|
||||
x = rect['left'] + rect['width'] / 2.0 - element.location['x']
|
||||
y = rect['top'] + rect['height'] / 2.0 - element.location['y']
|
||||
return x, y
|
||||
|
||||
def touch_caret_location(self, element):
|
||||
'''Return touch caret's location (based on current caret location).
|
||||
|
||||
Return (x, y) coordinates of the touch caret's tip relative to the top
|
||||
left-hand corner of the given element.
|
||||
|
||||
'''
|
||||
rect = self.caret_rect(element)
|
||||
x = rect['left'] - element.location['x']
|
||||
|
||||
# Touch caret's tip is below the bottom of the caret. Add 5px to y
|
||||
# should be sufficient to locate it.
|
||||
y = rect['bottom'] + 5 - element.location['y']
|
||||
|
||||
return x, y
|
||||
|
||||
def move_caret_by_offset(self, element, offset, backward=False):
|
||||
'''Move caret in the element by offset.'''
|
||||
cmd = self.get_js_selection_cmd(element) +\
|
||||
'''sel.modify("move", arguments[1], "character");'''
|
||||
direction = 'backward' if backward else 'forward'
|
||||
|
||||
for i in range(offset):
|
||||
self.marionette.execute_script(
|
||||
cmd, script_args=[element, direction])
|
||||
|
||||
def move_caret_to_front(self, element):
|
||||
if self.is_input_or_textarea(element):
|
||||
cmd = '''arguments[0].setSelectionRange(0, 0);'''
|
||||
else:
|
||||
cmd = '''var sel = window.getSelection();
|
||||
sel.collapse(arguments[0].firstChild, 0);'''
|
||||
|
||||
self.marionette.execute_script(cmd, script_args=[element])
|
||||
|
||||
def move_caret_to_end(self, element):
|
||||
if self.is_input_or_textarea(element):
|
||||
cmd = '''var len = arguments[0].value.length;
|
||||
arguments[0].setSelectionRange(len, len);'''
|
||||
else:
|
||||
cmd = '''var sel = window.getSelection();
|
||||
sel.collapse(arguments[0].lastChild, arguments[0].lastChild.length);'''
|
||||
|
||||
self.marionette.execute_script(cmd, script_args=[element])
|
||||
|
||||
def get_content(self, element):
|
||||
'''Return the content of the element.'''
|
||||
if self.is_input_or_textarea(element):
|
||||
return element.get_attribute('value')
|
||||
else:
|
||||
return element.text
|
||||
|
||||
def _test_move_caret_to_the_right_by_one_character(self, el, assertFunc):
|
||||
content_to_add = '!'
|
||||
target_content = self.get_content(el)
|
||||
target_content = target_content[:1] + content_to_add + target_content[1:]
|
||||
|
||||
# Get touch caret (x, y) at position 1 and 2.
|
||||
self.move_caret_to_front(el)
|
||||
caret0_x, caret0_y = self.caret_location(el)
|
||||
touch_caret0_x, touch_caret0_y = self.touch_caret_location(el)
|
||||
self.move_caret_by_offset(el, 1)
|
||||
touch_caret1_x, touch_caret1_y = self.touch_caret_location(el)
|
||||
|
||||
# Tap the front of the input to make touch caret appear.
|
||||
el.tap(caret0_x, caret0_y)
|
||||
|
||||
# Move touch caret
|
||||
self.actions.flick(el, touch_caret0_x, touch_caret0_y,
|
||||
touch_caret1_x, touch_caret1_y).perform()
|
||||
|
||||
el.send_keys(content_to_add)
|
||||
assertFunc(target_content, self.get_content(el))
|
||||
|
||||
def _test_move_caret_to_end_by_dragging_touch_caret_to_bottom_right_corner(self, el, assertFunc):
|
||||
content_to_add = '!'
|
||||
target_content = self.get_content(el) + content_to_add
|
||||
|
||||
# Tap the front of the input to make touch caret appear.
|
||||
self.move_caret_to_front(el)
|
||||
el.tap(*self.caret_location(el))
|
||||
|
||||
# Move touch caret to the bottom-right corner of the element.
|
||||
src_x, src_y = self.touch_caret_location(el)
|
||||
dest_x, dest_y = el.size['width'], el.size['height']
|
||||
self.actions.flick(el, src_x, src_y, dest_x, dest_y).perform()
|
||||
|
||||
el.send_keys(content_to_add)
|
||||
assertFunc(target_content, self.get_content(el))
|
||||
|
||||
def _test_move_caret_to_front_by_dragging_touch_caret_to_top_left_corner(self, el, assertFunc):
|
||||
content_to_add = '!'
|
||||
target_content = content_to_add + self.get_content(el)
|
||||
|
||||
# Tap to make touch caret appear. Note: it's strange that when the caret
|
||||
# is at the end, the rect of the caret in <textarea> cannot be obtained.
|
||||
# A bug perhaps.
|
||||
self.move_caret_to_end(el)
|
||||
self.move_caret_by_offset(el, 1, backward=True)
|
||||
el.tap(*self.caret_location(el))
|
||||
|
||||
# Move touch caret to the top-left corner of the input box.
|
||||
src_x, src_y = self.touch_caret_location(el)
|
||||
dest_x, dest_y = 0, 0
|
||||
self.actions.flick(el, src_x, src_y, dest_x, dest_y).perform()
|
||||
|
||||
el.send_keys(content_to_add)
|
||||
assertFunc(target_content, self.get_content(el))
|
||||
|
||||
def _test_touch_caret_timeout_by_dragging_it_to_top_left_corner_after_timout(self, el, assertFunc):
|
||||
content_to_add = '!'
|
||||
non_target_content = content_to_add + self.get_content(el)
|
||||
|
||||
# Get touch caret expiration time in millisecond, and convert it to second.
|
||||
timeout = self.expiration_time / 1000.0
|
||||
|
||||
# Tap to make touch caret appear. Note: it's strange that when the caret
|
||||
# is at the end, the rect of the caret in <textarea> cannot be obtained.
|
||||
# A bug perhaps.
|
||||
self.move_caret_to_end(el)
|
||||
self.move_caret_by_offset(el, 1, backward=True)
|
||||
el.tap(*self.caret_location(el))
|
||||
|
||||
# Wait until touch caret disappears, then pretend to move it to the
|
||||
# top-left corner of the input box.
|
||||
src_x, src_y = self.touch_caret_location(el)
|
||||
dest_x, dest_y = 0, 0
|
||||
self.actions.wait(timeout).flick(el, src_x, src_y, dest_x, dest_y).perform()
|
||||
|
||||
el.send_keys(content_to_add)
|
||||
assertFunc(non_target_content, self.get_content(el))
|
||||
|
||||
########################################################################
|
||||
# <input> test cases with touch caret enabled
|
||||
########################################################################
|
||||
def test_input_move_caret_to_the_right_by_one_character(self):
|
||||
self.openTestHtml(enabled=True, expiration_time=self._large_expiration_time)
|
||||
self._test_move_caret_to_the_right_by_one_character(self._input, self.assertEqual)
|
||||
|
||||
def test_input_move_caret_to_end_by_dragging_touch_caret_to_bottom_right_corner(self):
|
||||
self.openTestHtml(enabled=True, expiration_time=self._large_expiration_time)
|
||||
self._test_move_caret_to_end_by_dragging_touch_caret_to_bottom_right_corner(self._input, self.assertEqual)
|
||||
|
||||
def test_input_move_caret_to_front_by_dragging_touch_caret_to_top_left_corner(self):
|
||||
self.openTestHtml(enabled=True, expiration_time=self._large_expiration_time)
|
||||
self._test_move_caret_to_front_by_dragging_touch_caret_to_top_left_corner(self._input, self.assertEqual)
|
||||
|
||||
def test_input_touch_caret_timeout(self):
|
||||
self.openTestHtml(enabled=True)
|
||||
self._test_touch_caret_timeout_by_dragging_it_to_top_left_corner_after_timout(self._input, self.assertNotEqual)
|
||||
|
||||
########################################################################
|
||||
# <input> test cases with touch caret disabled
|
||||
########################################################################
|
||||
def test_input_move_caret_to_the_right_by_one_character_disabled(self):
|
||||
self.openTestHtml(enabled=False)
|
||||
self._test_move_caret_to_the_right_by_one_character(self._input, self.assertNotEqual)
|
||||
|
||||
def test_input_move_caret_to_front_by_dragging_touch_caret_to_top_left_corner_disabled(self):
|
||||
self.openTestHtml(enabled=False)
|
||||
self._test_move_caret_to_front_by_dragging_touch_caret_to_top_left_corner(self._input, self.assertNotEqual)
|
||||
|
||||
########################################################################
|
||||
# <textarea> test cases with touch caret enabled
|
||||
########################################################################
|
||||
def test_textarea_move_caret_to_the_right_by_one_character(self):
|
||||
self.openTestHtml(enabled=True, expiration_time=self._large_expiration_time)
|
||||
self._test_move_caret_to_the_right_by_one_character(self._textarea, self.assertEqual)
|
||||
|
||||
def test_textarea_move_caret_to_end_by_dragging_touch_caret_to_bottom_right_corner(self):
|
||||
self.openTestHtml(enabled=True, expiration_time=self._large_expiration_time)
|
||||
self._test_move_caret_to_end_by_dragging_touch_caret_to_bottom_right_corner(self._textarea, self.assertEqual)
|
||||
|
||||
def test_textarea_move_caret_to_front_by_dragging_touch_caret_to_top_left_corner(self):
|
||||
self.openTestHtml(enabled=True, expiration_time=self._large_expiration_time)
|
||||
self._test_move_caret_to_front_by_dragging_touch_caret_to_top_left_corner(self._textarea, self.assertEqual)
|
||||
|
||||
def test_textarea_touch_caret_timeout(self):
|
||||
self.openTestHtml(enabled=True)
|
||||
self._test_touch_caret_timeout_by_dragging_it_to_top_left_corner_after_timout(self._textarea, self.assertNotEqual)
|
||||
|
||||
########################################################################
|
||||
# <textarea> test cases with touch caret disabled
|
||||
########################################################################
|
||||
def test_textarea_move_caret_to_the_right_by_one_character_disabled(self):
|
||||
self.openTestHtml(enabled=False)
|
||||
self._test_move_caret_to_the_right_by_one_character(self._textarea, self.assertNotEqual)
|
||||
|
||||
def test_textarea_move_caret_to_front_by_dragging_touch_caret_to_top_left_corner_disabled(self):
|
||||
self.openTestHtml(enabled=False)
|
||||
self._test_move_caret_to_front_by_dragging_touch_caret_to_top_left_corner(self._textarea, self.assertNotEqual)
|
||||
|
||||
########################################################################
|
||||
# <div> contenteditable test cases with touch caret enabled
|
||||
########################################################################
|
||||
def test_contenteditable_move_caret_to_the_right_by_one_character(self):
|
||||
self.openTestHtml(enabled=True, expiration_time=self._large_expiration_time)
|
||||
self._test_move_caret_to_the_right_by_one_character(self._contenteditable, self.assertEqual)
|
||||
|
||||
def test_contenteditable_move_caret_to_end_by_dragging_touch_caret_to_bottom_right_corner(self):
|
||||
self.openTestHtml(enabled=True, expiration_time=self._large_expiration_time)
|
||||
self._test_move_caret_to_end_by_dragging_touch_caret_to_bottom_right_corner(self._contenteditable, self.assertEqual)
|
||||
|
||||
def test_contenteditable_move_caret_to_front_by_dragging_touch_caret_to_top_left_corner(self):
|
||||
self.openTestHtml(enabled=True, expiration_time=self._large_expiration_time)
|
||||
self._test_move_caret_to_front_by_dragging_touch_caret_to_top_left_corner(self._contenteditable, self.assertEqual)
|
||||
|
||||
def test_contenteditable_touch_caret_timeout(self):
|
||||
self.openTestHtml(enabled=True)
|
||||
self._test_touch_caret_timeout_by_dragging_it_to_top_left_corner_after_timout(self._contenteditable, self.assertNotEqual)
|
||||
|
||||
########################################################################
|
||||
# <div> contenteditable test cases with touch caret disabled
|
||||
########################################################################
|
||||
def test_contenteditable_move_caret_to_the_right_by_one_character_disabled(self):
|
||||
self.openTestHtml(enabled=False)
|
||||
self._test_move_caret_to_the_right_by_one_character(self._contenteditable, self.assertNotEqual)
|
||||
|
||||
def test_contenteditable_move_caret_to_front_by_dragging_touch_caret_to_top_left_corner_disabled(self):
|
||||
self.openTestHtml(enabled=False)
|
||||
self._test_move_caret_to_front_by_dragging_touch_caret_to_top_left_corner(self._contenteditable, self.assertNotEqual)
|
@ -28,5 +28,8 @@ skip = false
|
||||
[include:../../../../../dom/events/test/marionette/manifest.ini]
|
||||
[include:../../../../../dom/wifi/test/marionette/manifest.ini]
|
||||
|
||||
; layout tests
|
||||
[include:../../../../../layout/base/tests/marionette/manifest.ini]
|
||||
|
||||
; loop tests
|
||||
[include:../../../../../browser/components/loop/manifest.ini]
|
||||
|
@ -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/. -->
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html id="html">
|
||||
<head>
|
||||
<title>Bug 960897: Marionette tests for touch caret</title>
|
||||
</head>
|
||||
<body>
|
||||
<div><input id="input" value="ABCDEFGHI"></input></div>
|
||||
<br />
|
||||
<div><textarea name="textarea" id="textarea" rows="4" cols="6">ABCDEFGHI</textarea></div>
|
||||
<br />
|
||||
<div style="width: 10em; height: 2em; word-wrap: break-word; overflow: auto;" contenteditable="true" id="contenteditable">ABCDEFGHI</div>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue
Block a user