import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo

This commit is contained in:
Roy Tam 2018-01-19 03:59:58 +08:00
commit dcd9973243
150858 changed files with 23884658 additions and 0 deletions

View file

@ -0,0 +1,11 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
DevToolsModules(
'simulator-content.js',
'simulator-core.js',
'simulator.js',
)

View file

@ -0,0 +1,43 @@
/* 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/. */
/* globals addMessageListener, sendAsyncMessage */
"use strict";
const { utils: Cu } = Components;
const { require } = Cu.import("resource://devtools/shared/Loader.jsm", {});
const { SimulatorCore } = require("devtools/shared/touch/simulator-core");
/**
* Launches SimulatorCore in the content window to simulate touch events
* This frame script is managed by `simulator.js`.
*/
var simulator = {
messages: [
"TouchEventSimulator:Start",
"TouchEventSimulator:Stop",
],
init() {
this.simulatorCore = new SimulatorCore(docShell.chromeEventHandler);
this.messages.forEach(msgName => {
addMessageListener(msgName, this);
});
},
receiveMessage(msg) {
switch (msg.name) {
case "TouchEventSimulator:Start":
this.simulatorCore.start();
sendAsyncMessage("TouchEventSimulator:Started");
break;
case "TouchEventSimulator:Stop":
this.simulatorCore.stop();
sendAsyncMessage("TouchEventSimulator:Stopped");
break;
}
},
};
simulator.init();

View file

@ -0,0 +1,366 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { Ci, Cu } = require("chrome");
const { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
var systemAppOrigin = (function () {
let systemOrigin = "_";
try {
systemOrigin = Services.io.newURI(
Services.prefs.getCharPref("b2g.system_manifest_url"), null, null)
.prePath;
} catch (e) {
// Fall back to default value
}
return systemOrigin;
})();
var threshold = 25;
try {
threshold = Services.prefs.getIntPref("ui.dragThresholdX");
} catch (e) {
// Fall back to default value
}
var delay = 500;
try {
delay = Services.prefs.getIntPref("ui.click_hold_context_menus.delay");
} catch (e) {
// Fall back to default value
}
function SimulatorCore(simulatorTarget) {
this.simulatorTarget = simulatorTarget;
}
/**
* Simulate touch events for platforms where they aren't generally available.
*/
SimulatorCore.prototype = {
events: [
"mousedown",
"mousemove",
"mouseup",
"touchstart",
"touchend",
"mouseenter",
"mouseover",
"mouseout",
"mouseleave"
],
contextMenuTimeout: null,
simulatorTarget: null,
enabled: false,
start() {
if (this.enabled) {
// Simulator is already started
return;
}
this.events.forEach(evt => {
// Only listen trusted events to prevent messing with
// event dispatched manually within content documents
this.simulatorTarget.addEventListener(evt, this, true, false);
});
this.enabled = true;
},
stop() {
if (!this.enabled) {
// Simulator isn't running
return;
}
this.events.forEach(evt => {
this.simulatorTarget.removeEventListener(evt, this, true);
});
this.enabled = false;
},
handleEvent(evt) {
// The gaia system window use an hybrid system even on the device which is
// a mix of mouse/touch events. So let's not cancel *all* mouse events
// if it is the current target.
let content = this.getContent(evt.target);
if (!content) {
return;
}
let isSystemWindow = content.location.toString()
.startsWith(systemAppOrigin);
// App touchstart & touchend should also be dispatched on the system app
// to match on-device behavior.
if (evt.type.startsWith("touch") && !isSystemWindow) {
let sysFrame = content.realFrameElement;
if (!sysFrame) {
return;
}
let sysDocument = sysFrame.ownerDocument;
let sysWindow = sysDocument.defaultView;
let touchEvent = sysDocument.createEvent("touchevent");
let touch = evt.touches[0] || evt.changedTouches[0];
let point = sysDocument.createTouch(sysWindow, sysFrame, 0,
touch.pageX, touch.pageY,
touch.screenX, touch.screenY,
touch.clientX, touch.clientY,
1, 1, 0, 0);
let touches = sysDocument.createTouchList(point);
let targetTouches = touches;
let changedTouches = touches;
touchEvent.initTouchEvent(evt.type, true, true, sysWindow, 0,
false, false, false, false,
touches, targetTouches, changedTouches);
sysFrame.dispatchEvent(touchEvent);
return;
}
// Ignore all but real mouse event coming from physical mouse
// (especially ignore mouse event being dispatched from a touch event)
if (evt.button ||
evt.mozInputSource != Ci.nsIDOMMouseEvent.MOZ_SOURCE_MOUSE ||
evt.isSynthesized) {
return;
}
let eventTarget = this.target;
let type = "";
switch (evt.type) {
case "mouseenter":
case "mouseover":
case "mouseout":
case "mouseleave":
// Don't propagate events which are not related to touch events
evt.stopPropagation();
break;
case "mousedown":
this.target = evt.target;
this.contextMenuTimeout = this.sendContextMenu(evt);
this.cancelClick = false;
this.startX = evt.pageX;
this.startY = evt.pageY;
// Capture events so if a different window show up the events
// won't be dispatched to something else.
evt.target.setCapture(false);
type = "touchstart";
break;
case "mousemove":
if (!eventTarget) {
// Don't propagate mousemove event when touchstart event isn't fired
evt.stopPropagation();
return;
}
if (!this.cancelClick) {
if (Math.abs(this.startX - evt.pageX) > threshold ||
Math.abs(this.startY - evt.pageY) > threshold) {
this.cancelClick = true;
content.clearTimeout(this.contextMenuTimeout);
}
}
type = "touchmove";
break;
case "mouseup":
if (!eventTarget) {
return;
}
this.target = null;
content.clearTimeout(this.contextMenuTimeout);
type = "touchend";
// Only register click listener after mouseup to ensure
// catching only real user click. (Especially ignore click
// being dispatched on form submit)
if (evt.detail == 1) {
this.simulatorTarget.addEventListener("click", this, true, false);
}
break;
case "click":
// Mouse events has been cancelled so dispatch a sequence
// of events to where touchend has been fired
evt.preventDefault();
evt.stopImmediatePropagation();
this.simulatorTarget.removeEventListener("click", this, true, false);
if (this.cancelClick) {
return;
}
content.setTimeout(function dispatchMouseEvents(self) {
try {
self.fireMouseEvent("mousedown", evt);
self.fireMouseEvent("mousemove", evt);
self.fireMouseEvent("mouseup", evt);
} catch (e) {
console.error("Exception in touch event helper: " + e);
}
}, this.getDelayBeforeMouseEvent(evt), this);
return;
}
let target = eventTarget || this.target;
if (target && type) {
this.sendTouchEvent(evt, target, type);
}
if (!isSystemWindow) {
evt.preventDefault();
evt.stopImmediatePropagation();
}
},
fireMouseEvent(type, evt) {
let content = this.getContent(evt.target);
let utils = content.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
utils.sendMouseEvent(type, evt.clientX, evt.clientY, 0, 1, 0, true, 0,
Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH);
},
sendContextMenu({ target, clientX, clientY, screenX, screenY }) {
let view = target.ownerDocument.defaultView;
let { MouseEvent } = view;
let evt = new MouseEvent("contextmenu", {
bubbles: true,
cancelable: true,
view,
screenX,
screenY,
clientX,
clientY,
});
let content = this.getContent(target);
let timeout = content.setTimeout((function contextMenu() {
target.dispatchEvent(evt);
this.cancelClick = true;
}).bind(this), delay);
return timeout;
},
sendTouchEvent(evt, target, name) {
function clone(obj) {
return Cu.cloneInto(obj, target);
}
// When running OOP b2g desktop, we need to send the touch events
// using the mozbrowser api on the unwrapped frame.
if (target.localName == "iframe" && target.mozbrowser === true) {
if (name == "touchstart") {
this.touchstartTime = Date.now();
} else if (name == "touchend") {
// If we have a "fast" tap, don't send a click as both will be turned
// into a click and that breaks eg. checkboxes.
if (Date.now() - this.touchstartTime < delay) {
this.cancelClick = true;
}
}
let unwrapped = XPCNativeWrapper.unwrap(target);
unwrapped.sendTouchEvent(name, clone([0]), // event type, id
clone([evt.clientX]), // x
clone([evt.clientY]), // y
clone([1]), clone([1]), // rx, ry
clone([0]), clone([0]), // rotation, force
1); // count
return;
}
let document = target.ownerDocument;
let content = this.getContent(target);
if (!content) {
return;
}
let touchEvent = document.createEvent("touchevent");
let point = document.createTouch(content, target, 0,
evt.pageX, evt.pageY,
evt.screenX, evt.screenY,
evt.clientX, evt.clientY,
1, 1, 0, 0);
let touches = document.createTouchList(point);
let targetTouches = touches;
let changedTouches = touches;
if (name === "touchend" || name === "touchcancel") {
// "touchend" and "touchcancel" events should not have the removed touch
// neither in touches nor in targetTouches
touches = targetTouches = document.createTouchList();
}
touchEvent.initTouchEvent(name, true, true, content, 0,
false, false, false, false,
touches, targetTouches, changedTouches);
target.dispatchEvent(touchEvent);
},
getContent(target) {
let win = (target && target.ownerDocument)
? target.ownerDocument.defaultView
: null;
return win;
},
getDelayBeforeMouseEvent(evt) {
// On mobile platforms, Firefox inserts a 300ms delay between
// touch events and accompanying mouse events, except if the
// content window is not zoomable and the content window is
// auto-zoomed to device-width.
// If the preference dom.meta-viewport.enabled is set to false,
// we couldn't read viewport's information from getViewportInfo().
// So we always simulate 300ms delay when the
// dom.meta-viewport.enabled is false.
let savedMetaViewportEnabled =
Services.prefs.getBoolPref("dom.meta-viewport.enabled");
if (!savedMetaViewportEnabled) {
return 300;
}
let content = this.getContent(evt.target);
if (!content) {
return 0;
}
let utils = content.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
let allowZoom = {},
minZoom = {},
maxZoom = {},
autoSize = {};
utils.getViewportInfo(content.innerWidth, content.innerHeight, {},
allowZoom, minZoom, maxZoom, {}, {}, autoSize);
// FIXME: On Safari and Chrome mobile platform, if the css property
// touch-action set to none or manipulation would also suppress 300ms
// delay. But Firefox didn't support this property now, we can't get
// this value from utils.getVisitedDependentComputedStyle() to check
// if we should suppress 300ms delay.
if (!allowZoom.value || // user-scalable = no
minZoom.value === maxZoom.value || // minimum-scale = maximum-scale
autoSize.value // width = device-width
) {
return 0;
} else {
return 300;
}
}
};
exports.SimulatorCore = SimulatorCore;

View file

@ -0,0 +1,77 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
var promise = require("promise");
var defer = require("devtools/shared/defer");
var Services = require("Services");
const FRAME_SCRIPT =
"resource://devtools/shared/touch/simulator-content.js";
var trackedBrowsers = new WeakMap();
var savedTouchEventsEnabled =
Services.prefs.getIntPref("dom.w3c_touch_events.enabled");
/**
* Simulate touch events for platforms where they aren't generally available.
* Defers to the `simulator-content.js` frame script to perform the real work.
*/
function TouchEventSimulator(browser) {
// Returns an already instantiated simulator for this browser
let simulator = trackedBrowsers.get(browser);
if (simulator) {
return simulator;
}
let mm = browser.frameLoader.messageManager;
mm.loadFrameScript(FRAME_SCRIPT, true);
simulator = {
enabled: false,
start() {
if (this.enabled) {
return promise.resolve({ isReloadNeeded: false });
}
this.enabled = true;
let deferred = defer();
let isReloadNeeded =
Services.prefs.getIntPref("dom.w3c_touch_events.enabled") != 1;
Services.prefs.setIntPref("dom.w3c_touch_events.enabled", 1);
let onStarted = () => {
mm.removeMessageListener("TouchEventSimulator:Started", onStarted);
deferred.resolve({ isReloadNeeded });
};
mm.addMessageListener("TouchEventSimulator:Started", onStarted);
mm.sendAsyncMessage("TouchEventSimulator:Start");
return deferred.promise;
},
stop() {
if (!this.enabled) {
return promise.resolve();
}
this.enabled = false;
let deferred = defer();
Services.prefs.setIntPref("dom.w3c_touch_events.enabled",
savedTouchEventsEnabled);
let onStopped = () => {
mm.removeMessageListener("TouchEventSimulator:Stopped", onStopped);
deferred.resolve();
};
mm.addMessageListener("TouchEventSimulator:Stopped", onStopped);
mm.sendAsyncMessage("TouchEventSimulator:Stop");
return deferred.promise;
}
};
trackedBrowsers.set(browser, simulator);
return simulator;
}
exports.TouchEventSimulator = TouchEventSimulator;