зеркало из https://github.com/mozilla/gecko-dev.git
Merge latest green inbound changeset and mozilla-central
This commit is contained in:
Коммит
702a315b61
2
CLOBBER
2
CLOBBER
|
@ -17,7 +17,7 @@
|
|||
#
|
||||
# Modifying this file will now automatically clobber the buildbot machines \o/
|
||||
#
|
||||
Bug 868047 - Adding a field to FrameMetrics affects ContainerLayer class size
|
||||
Bug 874640 touched webidl, so Windows needs to clobber + Bug 854517: Integrate valgrind into B2G builds
|
||||
|
||||
Alternative to clobber is to run ./config.status from the objdir and to
|
||||
touch the CLOBBER file in the objdir.
|
||||
|
|
|
@ -61,6 +61,7 @@ xul|scrollbarbutton[sbattr="scrollbar-bottom-top"] {
|
|||
}
|
||||
|
||||
xul|thumb {
|
||||
-moz-appearance: none !important;
|
||||
background-color: rgba(0, 0, 0, 0.4) !important;
|
||||
-moz-border-top-colors: none !important;
|
||||
-moz-border-bottom-colors: none !important;
|
||||
|
@ -75,30 +76,30 @@ xul|thumb {
|
|||
-moz-binding: url("chrome://global/content/bindings/videocontrols.xml#touchControls");
|
||||
}
|
||||
|
||||
select:not([size]):not([multiple]) > xul|scrollbar,
|
||||
select[size="1"] > xul|scrollbar,
|
||||
select:not([size]):not([multiple]) xul|scrollbarbutton,
|
||||
select[size="1"] xul|scrollbarbutton {
|
||||
html select:not([size]):not([multiple]) > xul|scrollbar,
|
||||
html select[size="1"] > xul|scrollbar,
|
||||
html select:not([size]):not([multiple]) xul|scrollbarbutton,
|
||||
html select[size="1"] xul|scrollbarbutton {
|
||||
display: block;
|
||||
margin-left: 0;
|
||||
min-width: 16px;
|
||||
}
|
||||
|
||||
/* Override inverse OS themes */
|
||||
select,
|
||||
textarea,
|
||||
button,
|
||||
xul|button,
|
||||
* > input:not([type="image"]) {
|
||||
html select,
|
||||
html textarea,
|
||||
html button,
|
||||
html xul|button,
|
||||
html * > input:not([type="image"]) {
|
||||
-moz-appearance: none !important; /* See bug 598421 for fixing the platform */
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
select[size],
|
||||
select[multiple],
|
||||
select[size][multiple],
|
||||
textarea,
|
||||
* > input:not([type="image"]) {
|
||||
html select[size],
|
||||
html select[multiple],
|
||||
html select[size][multiple],
|
||||
html textarea,
|
||||
html * > input:not([type="image"]) {
|
||||
border-style: solid;
|
||||
border-color: #7d7d7d;
|
||||
color: #414141;
|
||||
|
@ -106,70 +107,70 @@ textarea,
|
|||
}
|
||||
|
||||
/* Selects are handled by the form helper, see bug 685197 */
|
||||
select option, select optgroup {
|
||||
html select option, html select optgroup {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
select:not([size]):not([multiple]),
|
||||
select[size="0"],
|
||||
select[size="1"],
|
||||
* > input[type="button"],
|
||||
* > input[type="submit"],
|
||||
* > input[type="reset"],
|
||||
button {
|
||||
html select:not([size]):not([multiple]),
|
||||
html select[size="0"],
|
||||
html select[size="1"],
|
||||
html * > input[type="button"],
|
||||
html * > input[type="submit"],
|
||||
html * > input[type="reset"],
|
||||
html button {
|
||||
border-style: solid;
|
||||
border-color: #7d7d7d;
|
||||
color: #414141;
|
||||
background: white linear-gradient(rgba(255,255,255,0.2) 0, rgba(215,215,215,0.5) 18px, rgba(115,115,115,0.5) 100%);
|
||||
}
|
||||
|
||||
input[type="checkbox"] {
|
||||
html input[type="checkbox"] {
|
||||
background: white linear-gradient(rgba(115,115,115,0.5) 0, rgba(215,215,215,0.5) 2px, rgba(255,255,255,0.2) 6px);
|
||||
}
|
||||
|
||||
input[type="radio"] {
|
||||
html input[type="radio"] {
|
||||
background: radial-gradient(at 6px 6px, rgba(255,255,255,0.2) 3px, rgba(195,195,195,0.5) 5px, rgba(115,115,115,0.5) 100%);
|
||||
}
|
||||
|
||||
select {
|
||||
html select {
|
||||
border-width: 1px;
|
||||
padding: 1px;
|
||||
}
|
||||
|
||||
select:not([size]):not([multiple]),
|
||||
select[size="0"],
|
||||
select[size="1"] {
|
||||
html select:not([size]):not([multiple]),
|
||||
html select[size="0"],
|
||||
html select[size="1"] {
|
||||
padding: 0 1px 0 1px;
|
||||
}
|
||||
|
||||
* > input:not([type="image"]) {
|
||||
html * > input:not([type="image"]) {
|
||||
border-width: 1px;
|
||||
padding: 1px;
|
||||
}
|
||||
|
||||
textarea {
|
||||
html textarea {
|
||||
resize: none;
|
||||
border-width: 1px;
|
||||
padding: 2px 1px 2px 1px;
|
||||
}
|
||||
|
||||
input[type="button"],
|
||||
input[type="submit"],
|
||||
input[type="reset"],
|
||||
button {
|
||||
html input[type="button"],
|
||||
html input[type="submit"],
|
||||
html input[type="reset"],
|
||||
html button {
|
||||
border-width: 1px;
|
||||
padding: 0 7px 0 7px;
|
||||
}
|
||||
|
||||
input[type="radio"],
|
||||
input[type="checkbox"] {
|
||||
html input[type="radio"],
|
||||
html input[type="checkbox"] {
|
||||
max-width: 14px;
|
||||
max-height: 14px;
|
||||
border: 1px solid #a7a7a7 !important;
|
||||
padding: 2px 1px 2px 1px;
|
||||
}
|
||||
|
||||
select > button {
|
||||
html select > button {
|
||||
border-width: 0px !important;
|
||||
margin: 0px !important;
|
||||
padding: 0px !important;
|
||||
|
@ -187,54 +188,54 @@ select > button {
|
|||
font-size: inherit;
|
||||
}
|
||||
|
||||
select[size]:focus,
|
||||
select[multiple]:focus,
|
||||
select[size][multiple]:focus,
|
||||
textarea:focus,
|
||||
input[type="file"]:focus > input[type="text"],
|
||||
* > input:not([type="image"]):focus {
|
||||
html select[size]:focus,
|
||||
html select[multiple]:focus,
|
||||
html select[size][multiple]:focus,
|
||||
html textarea:focus,
|
||||
html input[type="file"]:focus > input[type="text"],
|
||||
html * > input:not([type="image"]):focus {
|
||||
outline: 0px !important;
|
||||
border-style: solid;
|
||||
border-color: rgb(94,128,153);
|
||||
background: white linear-gradient(rgba(27,113,177,0.5) 0, rgba(198,225,246,0.2) 3px, rgba(255,255,255,0.2) 16px);
|
||||
}
|
||||
|
||||
select:not([size]):not([multiple]):focus,
|
||||
select[size="0"]:focus,
|
||||
select[size="1"]:focus,
|
||||
input[type="button"]:focus,
|
||||
input[type="submit"]:focus,
|
||||
input[type="reset"]:focus,
|
||||
button:focus {
|
||||
html select:not([size]):not([multiple]):focus,
|
||||
html select[size="0"]:focus,
|
||||
html select[size="1"]:focus,
|
||||
html input[type="button"]:focus,
|
||||
html input[type="submit"]:focus,
|
||||
html input[type="reset"]:focus,
|
||||
html button:focus {
|
||||
outline: 0px !important;
|
||||
border-style: solid;
|
||||
border-color: rgb(94,128,153);
|
||||
background: white linear-gradient(rgba(255,255,255,0.2) 0, rgba(198,225,256,0.2) 18px, rgba(27,113,177,0.5) 100%);
|
||||
}
|
||||
|
||||
input[type="checkbox"]:focus,
|
||||
input[type="radio"]:focus {
|
||||
html input[type="checkbox"]:focus,
|
||||
html input[type="radio"]:focus {
|
||||
border-color: #99c6e0 !important;
|
||||
}
|
||||
|
||||
input[type="checkbox"]:focus {
|
||||
html input[type="checkbox"]:focus {
|
||||
background: white linear-gradient(rgba(27,113,177,0.5) 0, rgba(198,225,246,0.2) 2px, rgba(255,255,255,0.2) 6px);
|
||||
}
|
||||
|
||||
input[type="radio"]:focus {
|
||||
html input[type="radio"]:focus {
|
||||
background: radial-gradient(at 6px 6px, rgba(255,255,255,0.2) 3px, rgba(198,225,246,0.2) 5px, rgba(27,113,177,0.5) 100%);
|
||||
}
|
||||
|
||||
/* we need to be specific for selects because the above rules are specific too */
|
||||
textarea[disabled],
|
||||
select[size][disabled],
|
||||
select[multiple][disabled],
|
||||
select[size][multiple][disabled],
|
||||
select:not([size]):not([multiple])[disabled],
|
||||
select[size="0"][disabled],
|
||||
select[size="1"][disabled],
|
||||
button[disabled],
|
||||
* > input:not([type="image"])[disabled] {
|
||||
html textarea[disabled],
|
||||
html select[size][disabled],
|
||||
html select[multiple][disabled],
|
||||
html select[size][multiple][disabled],
|
||||
html select:not([size]):not([multiple])[disabled],
|
||||
html select[size="0"][disabled],
|
||||
html select[size="1"][disabled],
|
||||
html button[disabled],
|
||||
html * > input:not([type="image"])[disabled] {
|
||||
color: rgba(0,0,0,0.3);
|
||||
border-color: rgba(125,125,125,0.4);
|
||||
border-style: solid;
|
||||
|
@ -242,44 +243,44 @@ button[disabled],
|
|||
background: transparent linear-gradient(rgba(185,185,185,0.4) 0, rgba(235,235,235,0.4) 3px, rgba(255,255,255,0.4) 100%);
|
||||
}
|
||||
|
||||
select:not([size]):not([multiple])[disabled],
|
||||
select[size="0"][disabled],
|
||||
select[size="1"][disabled] {
|
||||
html select:not([size]):not([multiple])[disabled],
|
||||
html select[size="0"][disabled],
|
||||
html select[size="1"][disabled] {
|
||||
background: transparent linear-gradient(rgba(255,255,255,0.4) 0, rgba(235,235,235,0.4) 3px, rgba(185,185,185,0.4) 100%);
|
||||
}
|
||||
|
||||
input[type="button"][disabled],
|
||||
input[type="submit"][disabled],
|
||||
input[type="reset"][disabled],
|
||||
button[disabled="true"] {
|
||||
html input[type="button"][disabled],
|
||||
html input[type="submit"][disabled],
|
||||
html input[type="reset"][disabled],
|
||||
html button[disabled="true"] {
|
||||
padding: 0 7px 0 7px;
|
||||
background: transparent linear-gradient(rgba(255,255,255,0.4) 0, rgba(235,235,235,0.4) 3px, rgba(185,185,185,0.4) 100%);
|
||||
}
|
||||
|
||||
input[type="radio"][disabled],
|
||||
input[type="radio"][disabled]:active,
|
||||
input[type="radio"][disabled]:hover,
|
||||
input[type="radio"][disabled]:hover:active,
|
||||
input[type="checkbox"][disabled],
|
||||
input[type="checkbox"][disabled]:active,
|
||||
input[type="checkbox"][disabled]:hover,
|
||||
input[type="checkbox"][disabled]:hover:active {
|
||||
html input[type="radio"][disabled],
|
||||
html input[type="radio"][disabled]:active,
|
||||
html input[type="radio"][disabled]:hover,
|
||||
html input[type="radio"][disabled]:hover:active,
|
||||
html input[type="checkbox"][disabled],
|
||||
html input[type="checkbox"][disabled]:active,
|
||||
html input[type="checkbox"][disabled]:hover,
|
||||
html input[type="checkbox"][disabled]:hover:active {
|
||||
border:1px solid rgba(125,125,125,0.4) !important;
|
||||
}
|
||||
|
||||
select[disabled] > button {
|
||||
html select[disabled] > button {
|
||||
opacity: 0.6;
|
||||
padding: 1px 7px 1px 7px;
|
||||
}
|
||||
|
||||
*:-moz-any-link:active,
|
||||
*[role=button]:active,
|
||||
button:active,
|
||||
input:active,
|
||||
option:active,
|
||||
select:active,
|
||||
label:active,
|
||||
textarea:active {
|
||||
html *:-moz-any-link:active,
|
||||
html *[role=button]:active,
|
||||
html button:active,
|
||||
html input:active,
|
||||
html option:active,
|
||||
html select:active,
|
||||
html label:active,
|
||||
html textarea:active {
|
||||
background-color: rgba(141, 184, 216, 0.5);
|
||||
}
|
||||
|
||||
|
|
|
@ -431,8 +431,8 @@ var shell = {
|
|||
},
|
||||
|
||||
lastHardwareButtonEventType: null, // property for the hack above
|
||||
needBufferSysMsgs: true,
|
||||
bufferedSysMsgs: [],
|
||||
needBufferOpenAppReq: true,
|
||||
bufferedOpenAppReqs: [],
|
||||
timer: null,
|
||||
visibleNormalAudioActive: false,
|
||||
|
||||
|
@ -548,7 +548,7 @@ var shell = {
|
|||
ObjectWrapper.wrap(details, getContentWindow()));
|
||||
},
|
||||
|
||||
sendSystemMessage: function shell_sendSystemMessage(msg) {
|
||||
openAppForSystemMessage: function shell_openAppForSystemMessage(msg) {
|
||||
let origin = Services.io.newURI(msg.manifest, null, null).prePath;
|
||||
this.sendChromeEvent({
|
||||
type: 'open-app',
|
||||
|
@ -623,16 +623,16 @@ nsBrowserAccess.prototype = {
|
|||
}
|
||||
};
|
||||
|
||||
// Listen for system messages and relay them to Gaia.
|
||||
Services.obs.addObserver(function onSystemMessage(subject, topic, data) {
|
||||
// Listen for the request of opening app and relay them to Gaia.
|
||||
Services.obs.addObserver(function onSystemMessageOpenApp(subject, topic, data) {
|
||||
let msg = JSON.parse(data);
|
||||
// Buffer non-activity messages until content starts to load for 10 seconds.
|
||||
// We'll revisit this later if new kind of messages don't need to be cached.
|
||||
if (shell.needBufferSysMsgs && msg.type !== 'activity') {
|
||||
shell.bufferedSysMsgs.push(msg);
|
||||
// Buffer non-activity request until content starts to load for 10 seconds.
|
||||
// We'll revisit this later if new kind of requests don't need to be cached.
|
||||
if (shell.needBufferOpenAppReq && msg.type !== 'activity') {
|
||||
shell.bufferedOpenAppReqs.push(msg);
|
||||
return;
|
||||
}
|
||||
shell.sendSystemMessage(msg);
|
||||
shell.openAppForSystemMessage(msg);
|
||||
}, 'system-messages-open-app', false);
|
||||
|
||||
Services.obs.addObserver(function(aSubject, aTopic, aData) {
|
||||
|
@ -662,14 +662,17 @@ var CustomEventManager = {
|
|||
content.addEventListener("mozContentEvent", this, false, true);
|
||||
|
||||
// After content starts to load for 10 seconds, send and
|
||||
// clean up the buffered system messages if there is any.
|
||||
// clean up the buffered open-app requests if there is any.
|
||||
//
|
||||
// TODO: Bug 793420 - Remove the waiting timer for the 'open-app'
|
||||
// mozChromeEvents requested by System Message
|
||||
shell.timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||
shell.timer.initWithCallback(function timerCallback() {
|
||||
shell.bufferedSysMsgs.forEach(function sendSysMsg(msg) {
|
||||
shell.sendSystemMessage(msg);
|
||||
shell.bufferedOpenAppReqs.forEach(function bufferOpenAppReq(msg) {
|
||||
shell.openAppForSystemMessage(msg);
|
||||
});
|
||||
shell.bufferedSysMsgs.length = 0;
|
||||
shell.needBufferSysMsgs = false;
|
||||
shell.bufferedOpenAppReqs.length = 0;
|
||||
shell.needBufferOpenAppReq = false;
|
||||
shell.timer = null;
|
||||
}, 10000, Ci.nsITimer.TYPE_ONE_SHOT);
|
||||
}).bind(this), false);
|
||||
|
|
|
@ -4,13 +4,8 @@
|
|||
|
||||
"use strict"
|
||||
|
||||
let DEBUG = 0;
|
||||
let debug;
|
||||
if (DEBUG) {
|
||||
debug = function (s) { dump("-*- ContentPermissionPrompt: " + s + "\n"); };
|
||||
}
|
||||
else {
|
||||
debug = function (s) {};
|
||||
function debug(str) {
|
||||
//dump("-*- ContentPermissionPrompt: " + s + "\n");
|
||||
}
|
||||
|
||||
const Ci = Components.interfaces;
|
||||
|
@ -18,7 +13,7 @@ const Cr = Components.results;
|
|||
const Cu = Components.utils;
|
||||
const Cc = Components.classes;
|
||||
|
||||
const PROMPT_FOR_UNKNOWN = ['geolocation', 'desktop-notification'];
|
||||
const PROMPT_FOR_UNKNOWN = ["geolocation", "desktop-notification"];
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
@ -116,8 +111,8 @@ ContentPermissionPrompt.prototype = {
|
|||
return true;
|
||||
},
|
||||
|
||||
_id: 0,
|
||||
prompt: function(request) {
|
||||
|
||||
if (secMan.isSystemPrincipal(request.principal)) {
|
||||
request.allow();
|
||||
return true;
|
||||
|
@ -130,58 +125,104 @@ ContentPermissionPrompt.prototype = {
|
|||
if (this.handleExistingPermission(request))
|
||||
return;
|
||||
|
||||
// If the request was initiated from a hidden iframe
|
||||
// we don't forward it to content and cancel it right away
|
||||
let frame = request.element;
|
||||
let requestId = this._id++;
|
||||
|
||||
if (!frame) {
|
||||
this.delegatePrompt(request);
|
||||
this.delegatePrompt(request, requestId);
|
||||
return;
|
||||
}
|
||||
|
||||
frame = frame.wrappedJSObject;
|
||||
var cancelRequest = function() {
|
||||
frame.removeEventListener("mozbrowservisibilitychange", onVisibilityChange);
|
||||
request.cancel();
|
||||
}
|
||||
|
||||
var self = this;
|
||||
frame.wrappedJSObject.getVisible().onsuccess = function gv_success(evt) {
|
||||
var onVisibilityChange = function(evt) {
|
||||
if (evt.detail.visible === true)
|
||||
return;
|
||||
|
||||
self.cancelPrompt(request, requestId);
|
||||
cancelRequest();
|
||||
}
|
||||
|
||||
// If the request was initiated from a hidden iframe
|
||||
// we don't forward it to content and cancel it right away
|
||||
let domRequest = frame.getVisible();
|
||||
domRequest.onsuccess = function gv_success(evt) {
|
||||
if (!evt.target.result) {
|
||||
request.cancel();
|
||||
cancelRequest();
|
||||
return;
|
||||
}
|
||||
|
||||
self.delegatePrompt(request);
|
||||
// Monitor the frame visibility and cancel the request if the frame goes
|
||||
// away but the request is still here.
|
||||
frame.addEventListener("mozbrowservisibilitychange", onVisibilityChange);
|
||||
|
||||
self.delegatePrompt(request, requestId, function onCallback() {
|
||||
frame.removeEventListener("mozbrowservisibilitychange", onVisibilityChange);
|
||||
});
|
||||
};
|
||||
|
||||
// Something went wrong. Let's cancel the request just in case.
|
||||
domRequest.onerror = function gv_error() {
|
||||
cancelRequest();
|
||||
}
|
||||
},
|
||||
|
||||
_id: 0,
|
||||
delegatePrompt: function(request) {
|
||||
cancelPrompt: function(request, requestId) {
|
||||
this.sendToBrowserWindow("cancel-permission-prompt", request, requestId);
|
||||
},
|
||||
|
||||
delegatePrompt: function(request, requestId, callback) {
|
||||
let access = (request.access && request.access !== "unused") ? request.type + "-" + request.access :
|
||||
request.type;
|
||||
let principal = request.principal;
|
||||
|
||||
this._permission = access;
|
||||
this._uri = principal.URI.spec;
|
||||
this._origin = principal.origin;
|
||||
|
||||
this.sendToBrowserWindow("permission-prompt", request, requestId, function(type, remember) {
|
||||
if (type == "permission-allow") {
|
||||
rememberPermission(request.type, principal, !remember);
|
||||
callback();
|
||||
request.allow();
|
||||
return;
|
||||
}
|
||||
|
||||
if (remember) {
|
||||
Services.perms.addFromPrincipal(principal, access,
|
||||
Ci.nsIPermissionManager.DENY_ACTION);
|
||||
} else {
|
||||
Services.perms.addFromPrincipal(principal, access,
|
||||
Ci.nsIPermissionManager.DENY_ACTION,
|
||||
Ci.nsIPermissionManager.EXPIRE_SESSION, 0);
|
||||
}
|
||||
|
||||
callback();
|
||||
request.cancel();
|
||||
});
|
||||
},
|
||||
|
||||
sendToBrowserWindow: function(type, request, requestId, callback) {
|
||||
let browser = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
let content = browser.getContentWindow();
|
||||
if (!content)
|
||||
return;
|
||||
|
||||
let access = (request.access && request.access !== "unused") ? request.type + "-" + request.access :
|
||||
request.type;
|
||||
if (callback) {
|
||||
content.addEventListener("mozContentEvent", function contentEvent(evt) {
|
||||
let detail = evt.detail;
|
||||
if (detail.id != requestId)
|
||||
return;
|
||||
evt.target.removeEventListener(evt.type, contentEvent);
|
||||
|
||||
let requestId = this._id++;
|
||||
content.addEventListener("mozContentEvent", function contentEvent(evt) {
|
||||
if (evt.detail.id != requestId)
|
||||
return;
|
||||
evt.target.removeEventListener(evt.type, contentEvent);
|
||||
|
||||
if (evt.detail.type == "permission-allow") {
|
||||
rememberPermission(request.type, request.principal, !evt.detail.remember);
|
||||
request.allow();
|
||||
return;
|
||||
}
|
||||
|
||||
if (evt.detail.remember) {
|
||||
Services.perms.addFromPrincipal(request.principal, access,
|
||||
Ci.nsIPermissionManager.DENY_ACTION);
|
||||
} else {
|
||||
Services.perms.addFromPrincipal(request.principal, access,
|
||||
Ci.nsIPermissionManager.DENY_ACTION,
|
||||
Ci.nsIPermissionManager.EXPIRE_SESSION, 0);
|
||||
}
|
||||
|
||||
request.cancel();
|
||||
});
|
||||
callback(detail.type, detail.remember);
|
||||
})
|
||||
}
|
||||
|
||||
let principal = request.principal;
|
||||
let isApp = principal.appStatus != Ci.nsIPrincipal.APP_STATUS_NOT_INSTALLED;
|
||||
|
@ -191,7 +232,7 @@ ContentPermissionPrompt.prototype = {
|
|||
: request.remember;
|
||||
|
||||
let details = {
|
||||
type: "permission-prompt",
|
||||
type: type,
|
||||
permission: request.type,
|
||||
id: requestId,
|
||||
origin: principal.origin,
|
||||
|
@ -199,10 +240,6 @@ ContentPermissionPrompt.prototype = {
|
|||
remember: remember
|
||||
};
|
||||
|
||||
this._permission = access;
|
||||
this._uri = request.principal.URI.spec;
|
||||
this._origin = request.principal.origin;
|
||||
|
||||
if (!isApp) {
|
||||
browser.shell.sendChromeEvent(details);
|
||||
return;
|
||||
|
|
|
@ -38,6 +38,7 @@ let Keyboard = {
|
|||
init: function keyboardInit() {
|
||||
Services.obs.addObserver(this, 'in-process-browser-or-app-frame-shown', false);
|
||||
Services.obs.addObserver(this, 'remote-browser-frame-shown', false);
|
||||
Services.obs.addObserver(this, 'oop-frameloader-crashed', false);
|
||||
|
||||
for (let name of this._messageNames)
|
||||
ppmm.addMessageListener('Keyboard:' + name, this);
|
||||
|
@ -46,18 +47,26 @@ let Keyboard = {
|
|||
observe: function keyboardObserve(subject, topic, data) {
|
||||
let frameLoader = subject.QueryInterface(Ci.nsIFrameLoader);
|
||||
let mm = frameLoader.messageManager;
|
||||
mm.addMessageListener('Forms:Input', this);
|
||||
mm.addMessageListener('Forms:SelectionChange', this);
|
||||
|
||||
// When not running apps OOP, we need to load forms.js here since this
|
||||
// won't happen from dom/ipc/preload.js
|
||||
try {
|
||||
if (Services.prefs.getBoolPref("dom.ipc.tabs.disabled") === true) {
|
||||
mm.loadFrameScript(kFormsFrameScript, true);
|
||||
}
|
||||
} catch (e) {
|
||||
dump('Error loading ' + kFormsFrameScript + ' as frame script: ' + e + '\n');
|
||||
}
|
||||
if (topic == 'oop-frameloader-crashed') {
|
||||
if (this.messageManager == mm) {
|
||||
// The application has been closed unexpectingly. Let's tell the
|
||||
// keyboard app that the focus has been lost.
|
||||
ppmm.broadcastAsyncMessage('Keyboard:FocusChange', { 'type': 'blur' });
|
||||
}
|
||||
} else {
|
||||
mm.addMessageListener('Forms:Input', this);
|
||||
|
||||
// When not running apps OOP, we need to load forms.js here since this
|
||||
// won't happen from dom/ipc/preload.js
|
||||
try {
|
||||
if (Services.prefs.getBoolPref("dom.ipc.tabs.disabled") === true) {
|
||||
mm.loadFrameScript(kFormsFrameScript, true);
|
||||
}
|
||||
} catch (e) {
|
||||
dump('Error loading ' + kFormsFrameScript + ' as frame script: ' + e + '\n');
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
receiveMessage: function keyboardReceiveMessage(msg) {
|
||||
|
|
|
@ -203,7 +203,7 @@ if test -n "$gonkdir" ; then
|
|||
|
||||
case "$ANDROID_VERSION" in
|
||||
15)
|
||||
GONK_INCLUDES="-I$gonkdir/frameworks/base/opengl/include -I$gonkdir/frameworks/base/native/include -I$gonkdir/frameworks/base/include -I$gonkdir/frameworks/base/services/camera -I$gonkdir/frameworks/base/include/media/stagefright -I$gonkdir/frameworks/base/include/media/stagefright/openmax -I$gonkdir/frameworks/base/media/libstagefright/rtsp -I$gonkdir/frameworks/base/media/libstagefright/include -I$gonkdir/external/dbus -I$gonkdir/external/bluetooth/bluez/lib -I$gonkdir/dalvik/libnativehelper/include/nativehelper"
|
||||
GONK_INCLUDES="-I$gonkdir/frameworks/base/opengl/include -I$gonkdir/frameworks/base/native/include -I$gonkdir/frameworks/base/include -I$gonkdir/frameworks/base/services/camera -I$gonkdir/frameworks/base/include/media/stagefright -I$gonkdir/frameworks/base/include/media/stagefright/openmax -I$gonkdir/frameworks/base/media/libstagefright/rtsp -I$gonkdir/frameworks/base/media/libstagefright/include -I$gonkdir/external/dbus -I$gonkdir/external/bluetooth/bluez/lib -I$gonkdir/dalvik/libnativehelper/include/nativehelper -I$gonkdir/external/valgrind"
|
||||
MOZ_B2G_BT=1
|
||||
MOZ_B2G_CAMERA=1
|
||||
MOZ_OMX_DECODER=1
|
||||
|
|
|
@ -1700,6 +1700,10 @@ void HTMLMediaElement::SetMutedInternal(uint32_t aMuted)
|
|||
|
||||
NS_IMETHODIMP HTMLMediaElement::SetMuted(bool aMuted)
|
||||
{
|
||||
if (aMuted == Muted()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (aMuted) {
|
||||
SetMutedInternal(mMuted | MUTED_BY_CONTENT);
|
||||
} else {
|
||||
|
|
|
@ -710,19 +710,22 @@ BluetoothOppManager::ServerDataHandler(UnixSocketRawData* aMessage)
|
|||
ReplyToConnect();
|
||||
AfterOppConnected();
|
||||
mIsServer = true;
|
||||
} else if (opCode == ObexRequestCode::Disconnect ||
|
||||
opCode == ObexRequestCode::Abort) {
|
||||
// Section 3.3.2 "Disconnect", IrOBEX 1.2
|
||||
} else if (opCode == ObexRequestCode::Abort) {
|
||||
// Section 3.3.5 "Abort", IrOBEX 1.2
|
||||
// [opcode:1][length:2][Headers:var]
|
||||
ParseHeaders(&aMessage->mData[3],
|
||||
receivedLength - 3,
|
||||
&pktHeaders);
|
||||
ReplyToDisconnect();
|
||||
ReplyToDisconnectOrAbort();
|
||||
DeleteReceivedFile();
|
||||
} else if (opCode == ObexRequestCode::Disconnect) {
|
||||
// Section 3.3.2 "Disconnect", IrOBEX 1.2
|
||||
// [opcode:1][length:2][Headers:var]
|
||||
ParseHeaders(&aMessage->mData[3],
|
||||
receivedLength - 3,
|
||||
&pktHeaders);
|
||||
ReplyToDisconnectOrAbort();
|
||||
AfterOppDisconnected();
|
||||
if (opCode == ObexRequestCode::Abort) {
|
||||
DeleteReceivedFile();
|
||||
}
|
||||
FileTransferComplete();
|
||||
} else if (opCode == ObexRequestCode::Put ||
|
||||
opCode == ObexRequestCode::PutFinal) {
|
||||
|
@ -1143,11 +1146,12 @@ BluetoothOppManager::ReplyToConnect()
|
|||
}
|
||||
|
||||
void
|
||||
BluetoothOppManager::ReplyToDisconnect()
|
||||
BluetoothOppManager::ReplyToDisconnectOrAbort()
|
||||
{
|
||||
if (!mConnected) return;
|
||||
|
||||
// Section 3.3.2 "Disconnect", IrOBEX 1.2
|
||||
// Section 3.3.2 "Disconnect" and Section 3.3.5 "Abort", IrOBEX 1.2
|
||||
// The format of response packet of "Disconnect" and "Abort" are the same
|
||||
// [opcode:1][length:2][Headers:var]
|
||||
uint8_t req[255];
|
||||
int index = 3;
|
||||
|
|
|
@ -101,7 +101,7 @@ private:
|
|||
bool WriteToFile(const uint8_t* aData, int aDataLength);
|
||||
void DeleteReceivedFile();
|
||||
void ReplyToConnect();
|
||||
void ReplyToDisconnect();
|
||||
void ReplyToDisconnectOrAbort();
|
||||
void ReplyToPut(bool aFinal, bool aContinue);
|
||||
void AfterOppConnected();
|
||||
void AfterFirstPut();
|
||||
|
|
|
@ -220,7 +220,7 @@ BluetoothServiceChildProcess::UpdateSdpRecords(const nsAString& aDeviceAddress,
|
|||
BluetoothProfileManagerBase* aManager)
|
||||
{
|
||||
MOZ_NOT_REACHED("This should never be called!");
|
||||
return NS_ERROR_FAILURE;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -41,6 +41,66 @@ function sendAsyncMsg(msg, data) {
|
|||
sendAsyncMessage('browser-element-api:call', data);
|
||||
}
|
||||
|
||||
function sendSyncMsg(msg, data) {
|
||||
// Ensure that we don't send any messages before BrowserElementChild.js
|
||||
// finishes loading.
|
||||
if (!BrowserElementIsReady)
|
||||
return;
|
||||
|
||||
if (!data) {
|
||||
data = { };
|
||||
}
|
||||
|
||||
data.msg_name = msg;
|
||||
return sendSyncMessage('browser-element-api:call', data);
|
||||
}
|
||||
|
||||
let CERTIFICATE_ERROR_PAGE_PREF = 'security.alternate_certificate_error_page';
|
||||
|
||||
let NS_ERROR_MODULE_BASE_OFFSET = 0x45;
|
||||
let NS_ERROR_MODULE_SECURITY= 21;
|
||||
function NS_ERROR_GET_MODULE(err) {
|
||||
return ((((err) >> 16) - NS_ERROR_MODULE_BASE_OFFSET) & 0x1fff)
|
||||
}
|
||||
|
||||
function NS_ERROR_GET_CODE(err) {
|
||||
return ((err) & 0xffff);
|
||||
}
|
||||
|
||||
let SEC_ERROR_BASE = Ci.nsINSSErrorsService.NSS_SEC_ERROR_BASE;
|
||||
let SEC_ERROR_UNKNOWN_ISSUER = (SEC_ERROR_BASE + 13);
|
||||
let SEC_ERROR_CA_CERT_INVALID = (SEC_ERROR_BASE + 36);
|
||||
let SEC_ERROR_UNTRUSTED_ISSUER = (SEC_ERROR_BASE + 20);
|
||||
let SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE = (SEC_ERROR_BASE + 30);
|
||||
let SEC_ERROR_UNTRUSTED_CERT = (SEC_ERROR_BASE + 21);
|
||||
let SEC_ERROR_INADEQUATE_KEY_USAGE = (SEC_ERROR_BASE + 90);
|
||||
let SEC_ERROR_EXPIRED_CERTIFICATE = (SEC_ERROR_BASE + 11);
|
||||
let SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED = (SEC_ERROR_BASE + 176);
|
||||
|
||||
let SSL_ERROR_BASE = Ci.nsINSSErrorsService.NSS_SSL_ERROR_BASE;
|
||||
let SSL_ERROR_BAD_CERT_DOMAIN = (SSL_ERROR_BASE + 12);
|
||||
|
||||
function getErrorClass(errorCode) {
|
||||
let NSPRCode = -1 * NS_ERROR_GET_CODE(errorCode);
|
||||
|
||||
switch (NSPRCode) {
|
||||
case SEC_ERROR_UNKNOWN_ISSUER:
|
||||
case SEC_ERROR_CA_CERT_INVALID:
|
||||
case SEC_ERROR_UNTRUSTED_ISSUER:
|
||||
case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
|
||||
case SEC_ERROR_UNTRUSTED_CERT:
|
||||
case SEC_ERROR_INADEQUATE_KEY_USAGE:
|
||||
case SSL_ERROR_BAD_CERT_DOMAIN:
|
||||
case SEC_ERROR_EXPIRED_CERTIFICATE:
|
||||
case SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED:
|
||||
return Ci.nsINSSErrorsService.ERROR_CLASS_BAD_CERT;
|
||||
default:
|
||||
return Ci.nsINSSErrorsService.ERROR_CLASS_SSL_PROTOCOL;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The BrowserElementChild implements one half of <iframe mozbrowser>.
|
||||
* (The other half is, unsurprisingly, BrowserElementParent.)
|
||||
|
@ -478,8 +538,6 @@ BrowserElementChild.prototype = {
|
|||
return;
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
this._ctxCounter++;
|
||||
this._ctxHandlers = {};
|
||||
|
||||
|
@ -508,7 +566,18 @@ BrowserElementChild.prototype = {
|
|||
menuData.contextmenu = this._buildMenuObj(menu, '');
|
||||
}
|
||||
}
|
||||
sendAsyncMsg('contextmenu', menuData);
|
||||
|
||||
// The value returned by the contextmenu sync call is true iff the embedder
|
||||
// called preventDefault() on its contextmenu event.
|
||||
//
|
||||
// We call preventDefault() on our contextmenu event iff the embedder called
|
||||
// preventDefault() on /its/ contextmenu event. This way, if the embedder
|
||||
// ignored the contextmenu event, TabChild will fire a click.
|
||||
if (sendSyncMsg('contextmenu', menuData)[0]) {
|
||||
e.preventDefault();
|
||||
} else {
|
||||
this._ctxHandlers = {};
|
||||
}
|
||||
},
|
||||
|
||||
_getSystemCtxMenuData: function(elem) {
|
||||
|
@ -700,7 +769,7 @@ BrowserElementChild.prototype = {
|
|||
var visible = this._forcedVisible && this._ownerVisible;
|
||||
if (docShell.isActive !== visible) {
|
||||
docShell.isActive = visible;
|
||||
sendAsyncMsg('visibility-change', {visible: visible});
|
||||
sendAsyncMsg('visibilitychange', {visible: visible});
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -827,6 +896,24 @@ BrowserElementChild.prototype = {
|
|||
return;
|
||||
}
|
||||
|
||||
if (NS_ERROR_GET_MODULE(status) == NS_ERROR_MODULE_SECURITY &&
|
||||
getErrorClass(status) == Ci.nsINSSErrorsService.ERROR_CLASS_BAD_CERT) {
|
||||
|
||||
// XXX Is there a point firing the event if the error page is not
|
||||
// certerror? If yes, maybe we should add a property to the
|
||||
// event to to indicate whether there is a custom page. That would
|
||||
// let the embedder have more control over the desired behavior.
|
||||
var errorPage = null;
|
||||
try {
|
||||
errorPage = Services.prefs.getCharPref(CERTIFICATE_ERROR_PAGE_PREF);
|
||||
} catch(e) {}
|
||||
|
||||
if (errorPage == 'certerror') {
|
||||
sendAsyncMsg('error', { type: 'certerror' });
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO See nsDocShell::DisplayLoadError for a list of all the error
|
||||
// codes (the status param) we should eventually handle here.
|
||||
sendAsyncMsg('error', { type: 'other' });
|
||||
|
|
|
@ -694,10 +694,22 @@ const KineticPanning = {
|
|||
|
||||
momentums: [],
|
||||
record: function kp_record(delta, timestamp) {
|
||||
this.momentums.push({ 'time': timestamp, 'dx' : delta.x, 'dy' : delta.y });
|
||||
this.momentums.push({ 'time': this._getTime(timestamp),
|
||||
'dx' : delta.x, 'dy' : delta.y });
|
||||
this.distance.add(delta.x, delta.y);
|
||||
},
|
||||
|
||||
_getTime: function kp_getTime(time) {
|
||||
// Touch events generated by the platform or hand-made are defined in
|
||||
// microseconds instead of milliseconds. Bug 77992 will fix this at the
|
||||
// platform level.
|
||||
if (time > Date.now()) {
|
||||
return Math.floor(time / 1000);
|
||||
} else {
|
||||
return time;
|
||||
}
|
||||
},
|
||||
|
||||
get threshold() {
|
||||
let dpi = content.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils)
|
||||
|
|
|
@ -119,7 +119,7 @@ function BrowserElementParent(frameLoader, hasRemoteFrame) {
|
|||
"rollback-fullscreen": this._remoteFrameFullscreenReverted,
|
||||
"exit-fullscreen": this._exitFullscreen,
|
||||
"got-visible": this._gotDOMRequestResult,
|
||||
"visibility-change": this._childVisibilityChange,
|
||||
"visibilitychange": this._childVisibilityChange,
|
||||
}
|
||||
|
||||
this._mm.addMessageListener('browser-element-api:call', function(aMsg) {
|
||||
|
@ -294,7 +294,7 @@ BrowserElementParent.prototype = {
|
|||
let evtName = detail.msg_name;
|
||||
|
||||
debug('fireCtxMenuEventFromMsg: ' + evtName + ' ' + detail);
|
||||
let evt = this._createEvent(evtName, detail);
|
||||
let evt = this._createEvent(evtName, detail, /* cancellable */ true);
|
||||
|
||||
if (detail.contextmenu) {
|
||||
var self = this;
|
||||
|
@ -302,10 +302,11 @@ BrowserElementParent.prototype = {
|
|||
self._sendAsyncMsg('fire-ctx-callback', {menuitem: id});
|
||||
});
|
||||
}
|
||||
|
||||
// The embedder may have default actions on context menu events, so
|
||||
// we fire a context menu event even if the child didn't define a
|
||||
// custom context menu
|
||||
this._frameElement.dispatchEvent(evt);
|
||||
return !this._frameElement.dispatchEvent(evt);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -575,6 +576,8 @@ BrowserElementParent.prototype = {
|
|||
_childVisibilityChange: function(data) {
|
||||
debug("_childVisibilityChange(" + data.json.visible + ")");
|
||||
this._frameLoader.visible = data.json.visible;
|
||||
|
||||
this._fireEventFromMsg(data);
|
||||
},
|
||||
|
||||
_exitFullscreen: function() {
|
||||
|
|
|
@ -28,7 +28,6 @@ MOCHITEST_FILES = \
|
|||
browserElement_DataURI.js \
|
||||
test_browserElement_inproc_DataURI.html \
|
||||
browserElement_ErrorSecurity.js \
|
||||
test_browserElement_inproc_ErrorSecurity.html \
|
||||
browserElement_Titlechange.js \
|
||||
test_browserElement_inproc_Titlechange.html \
|
||||
browserElement_TopBarrier.js \
|
||||
|
@ -161,6 +160,8 @@ MOCHITEST_FILES = \
|
|||
test_browserElement_inproc_PurgeHistory.html \
|
||||
browserElement_DocumentFirstPaint.js \
|
||||
test_browserElement_inproc_DocumentFirstPaint.html \
|
||||
browserElement_VisibilityChange.js \
|
||||
test_browserElement_inproc_VisibilityChange.html \
|
||||
$(NULL)
|
||||
|
||||
# Disabled due to https://bugzilla.mozilla.org/show_bug.cgi?id=774100
|
||||
|
@ -169,6 +170,9 @@ MOCHITEST_FILES = \
|
|||
# Disabled due to focus issues (no bug that I'm aware of)
|
||||
# test_browserElement_oop_KeyEvents.html \
|
||||
|
||||
# Disable due to certificate issue (no bug that I'm aware of)
|
||||
# test_browserElement_inproc_ErrorSecurity.html \
|
||||
|
||||
# OOP tests don't work on native-fennec (bug 774939).
|
||||
#
|
||||
# Both the "inproc" and "oop" versions of OpenMixedProcess open remote frames,
|
||||
|
@ -179,6 +183,7 @@ MOCHITEST_FILES += \
|
|||
browserElement_OpenMixedProcess.js \
|
||||
file_browserElement_OpenMixedProcess.html \
|
||||
test_browserElement_inproc_OpenMixedProcess.html \
|
||||
test_browserElement_inproc_ErrorSecurity.html \
|
||||
test_browserElement_oop_OpenMixedProcess.html \
|
||||
test_browserElement_oop_LoadEvents.html \
|
||||
test_browserElement_oop_DataURI.html \
|
||||
|
@ -230,6 +235,7 @@ MOCHITEST_FILES += \
|
|||
test_browserElement_oop_ReloadPostRequest.html \
|
||||
test_browserElement_oop_PurgeHistory.html \
|
||||
test_browserElement_oop_DocumentFirstPaint.html \
|
||||
test_browserElement_oop_VisibilityChange.html \
|
||||
$(NULL)
|
||||
|
||||
endif #}
|
||||
|
|
|
@ -1,142 +1,222 @@
|
|||
"use strict";
|
||||
'use strict';
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
browserElementTestHelpers.setEnabledPref(true);
|
||||
browserElementTestHelpers.addPermission();
|
||||
|
||||
var iframeScript = function() {
|
||||
|
||||
content.fireContextMenu = function(element) {
|
||||
var ev = content.document.createEvent('HTMLEvents');
|
||||
ev.initEvent('contextmenu', true, false);
|
||||
element.dispatchEvent(ev);
|
||||
};
|
||||
|
||||
XPCNativeWrapper.unwrap(content).ctxCallbackFired = function(data) {
|
||||
sendAsyncMessage('test:callbackfired', {data: data});
|
||||
};
|
||||
|
||||
XPCNativeWrapper.unwrap(content).onerror = function(e) {
|
||||
sendAsyncMessage('test:errorTriggered', {data: e});
|
||||
};
|
||||
|
||||
content.fireContextMenu(content.document.body);
|
||||
content.fireContextMenu(content.document.getElementById('menu1-trigger'));
|
||||
content.fireContextMenu(content.document.getElementById('inner-link').childNodes[0]);
|
||||
content.fireContextMenu(content.document.getElementById('menu2-trigger'));
|
||||
function runTests() {
|
||||
createIframe(function onIframeLoaded() {
|
||||
checkEmptyContextMenu();
|
||||
});
|
||||
}
|
||||
|
||||
var trigger1 = function() {
|
||||
content.fireContextMenu(content.document.getElementById('menu1-trigger'));
|
||||
function checkEmptyContextMenu() {
|
||||
sendContextMenuTo('body', function onContextMenu(detail) {
|
||||
is(detail.contextmenu, null, 'Body context clicks have no context menu');
|
||||
|
||||
checkInnerContextMenu();
|
||||
});
|
||||
}
|
||||
|
||||
function checkInnerContextMenu() {
|
||||
sendContextMenuTo('#inner-link', function onContextMenu(detail) {
|
||||
is(detail.systemTargets.length, 1, 'Includes anchor data');
|
||||
is(detail.contextmenu.items.length, 2, 'Inner clicks trigger correct menu');
|
||||
|
||||
checkCustomContextMenu();
|
||||
});
|
||||
}
|
||||
|
||||
function checkCustomContextMenu() {
|
||||
sendContextMenuTo('#menu1-trigger', function onContextMenu(detail) {
|
||||
is(detail.contextmenu.items.length, 2, 'trigger custom contextmenu');
|
||||
|
||||
checkNestedContextMenu();
|
||||
});
|
||||
}
|
||||
|
||||
function checkNestedContextMenu() {
|
||||
sendContextMenuTo('#menu2-trigger', function onContextMenu(detail) {
|
||||
var innerMenu = detail.contextmenu.items.filter(function(x) {
|
||||
return x.type === 'menu';
|
||||
});
|
||||
is(detail.systemTargets.length, 2, 'Includes anchor and img data');
|
||||
ok(innerMenu.length > 0, 'Menu contains a nested menu');
|
||||
|
||||
checkPreviousContextMenuHandler();
|
||||
});
|
||||
}
|
||||
|
||||
// Finished testing the data passed to the contextmenu handler,
|
||||
// now we start selecting contextmenu items
|
||||
function checkPreviousContextMenuHandler() {
|
||||
// This is previously triggered contextmenu data, since we have
|
||||
// fired subsequent contextmenus this should not be mistaken
|
||||
// for a current menuitem
|
||||
var detail = previousContextMenuDetail;
|
||||
var previousId = detail.contextmenu.items[0].id;
|
||||
checkContextMenuCallbackForId(detail, previousId, function onCallbackFired(label) {
|
||||
is(label, null, 'Callback label should be empty since this handler is old');
|
||||
|
||||
checkCurrentContextMenuHandler();
|
||||
});
|
||||
}
|
||||
|
||||
function checkCurrentContextMenuHandler() {
|
||||
// This triggers a current menuitem
|
||||
var detail = currentContextMenuDetail;
|
||||
|
||||
var innerMenu = detail.contextmenu.items.filter(function(x) {
|
||||
return x.type === 'menu';
|
||||
});
|
||||
|
||||
var currentId = innerMenu[0].items[1].id;
|
||||
checkContextMenuCallbackForId(detail, currentId, function onCallbackFired(label) {
|
||||
is(label, 'inner 2', 'Callback label should be set correctly');
|
||||
|
||||
checkAgainCurrentContextMenuHandler();
|
||||
});
|
||||
}
|
||||
|
||||
function checkAgainCurrentContextMenuHandler() {
|
||||
// Once an item it selected, subsequent selections are ignored
|
||||
var detail = currentContextMenuDetail;
|
||||
|
||||
var innerMenu = detail.contextmenu.items.filter(function(x) {
|
||||
return x.type === 'menu';
|
||||
});
|
||||
|
||||
var currentId = innerMenu[0].items[1].id;
|
||||
checkContextMenuCallbackForId(detail, currentId, function onCallbackFired(label) {
|
||||
is(label, null, 'Callback label should be empty since this handler has already been used');
|
||||
|
||||
checkCallbackWithPreventDefault();
|
||||
});
|
||||
};
|
||||
|
||||
function runTest() {
|
||||
var iframe1 = document.createElement('iframe');
|
||||
SpecialPowers.wrap(iframe1).mozbrowser = true;
|
||||
document.body.appendChild(iframe1);
|
||||
iframe1.src = 'data:text/html,<html>' +
|
||||
// Finished testing callbacks if the embedder calls preventDefault() on the
|
||||
// mozbrowsercontextmenu event, now we start checking for some cases where the embedder
|
||||
// does not want to call preventDefault() for some reasons.
|
||||
function checkCallbackWithPreventDefault() {
|
||||
sendContextMenuTo('#menu1-trigger', function onContextMenu(detail) {
|
||||
var id = detail.contextmenu.items[0].id;
|
||||
checkContextMenuCallbackForId(detail, id, function onCallbackFired(label) {
|
||||
is(label, 'foo', 'Callback label should be set correctly');
|
||||
|
||||
checkCallbackWithoutPreventDefault();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function checkCallbackWithoutPreventDefault() {
|
||||
sendContextMenuTo('#menu1-trigger', function onContextMenu(detail) {
|
||||
var id = detail.contextmenu.items[0].id;
|
||||
checkContextMenuCallbackForId(detail, id, function onCallbackFired(label) {
|
||||
is(label, null, 'Callback label should be null');
|
||||
|
||||
SimpleTest.finish();
|
||||
});
|
||||
}, /* ignorePreventDefault */ true);
|
||||
}
|
||||
|
||||
|
||||
/* Helpers */
|
||||
var mm = null;
|
||||
var previousContextMenuDetail = null;
|
||||
var currentContextMenuDetail = null;
|
||||
|
||||
function sendContextMenuTo(selector, callback, ignorePreventDefault) {
|
||||
iframe.addEventListener('mozbrowsercontextmenu', function oncontextmenu(e) {
|
||||
iframe.removeEventListener(e.type, oncontextmenu);
|
||||
|
||||
// The embedder should call preventDefault() on the event if it will handle
|
||||
// it. Not calling preventDefault() means it won't handle the event and
|
||||
// should not be able to deal with context menu callbacks.
|
||||
if (ignorePreventDefault !== true) {
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
// Keep a reference to previous/current contextmenu event details.
|
||||
previousContextMenuDetail = currentContextMenuDetail;
|
||||
currentContextMenuDetail = e.detail;
|
||||
|
||||
setTimeout(function() { callback(e.detail); });
|
||||
});
|
||||
|
||||
mm.sendAsyncMessage('contextmenu', { 'selector': selector });
|
||||
}
|
||||
|
||||
function checkContextMenuCallbackForId(detail, id, callback) {
|
||||
mm.addMessageListener('test:callbackfired', function onCallbackFired(msg) {
|
||||
mm.removeMessageListener('test:callbackfired', onCallbackFired);
|
||||
|
||||
msg = SpecialPowers.wrap(msg);
|
||||
setTimeout(function() { callback(msg.data.label); });
|
||||
});
|
||||
|
||||
detail.contextMenuItemSelected(id);
|
||||
}
|
||||
|
||||
|
||||
var iframe = null;
|
||||
function createIframe(callback) {
|
||||
iframe = document.createElement('iframe');
|
||||
SpecialPowers.wrap(iframe).mozbrowser = true;
|
||||
|
||||
iframe.src = 'data:text/html,<html>' +
|
||||
'<body>' +
|
||||
'<menu type="context" id="menu1" label="firstmenu">' +
|
||||
'<menuitem label="foo" onclick="window.ctxCallbackFired(\'foo\')"></menuitem>' +
|
||||
'<menuitem label="bar" onclick="throw(\'anerror\')"></menuitem>' +
|
||||
'<menuitem label="foo" onclick="window.onContextMenuCallbackFired(event)"></menuitem>' +
|
||||
'<menuitem label="bar" onclick="window.onContextMenuCallbackFired(event)"></menuitem>' +
|
||||
'</menu>' +
|
||||
'<menu type="context" id="menu2" label="secondmenu">' +
|
||||
'<menuitem label="outer" onclick="window.ctxCallbackFired(\'err\')"></menuitem>' +
|
||||
'<menuitem label="outer" onclick="window.onContextMenuCallbackFired(event)"></menuitem>' +
|
||||
'<menu>' +
|
||||
'<menuitem label="inner 1"></menuitem>' +
|
||||
'<menuitem label="inner 2" onclick="window.ctxCallbackFired(\'inner2\')"></menuitem>' +
|
||||
'<menuitem label="inner 2" onclick="window.onContextMenuCallbackFired(event)"></menuitem>' +
|
||||
'</menu>' +
|
||||
'</menu>' +
|
||||
'<div id="menu1-trigger" contextmenu="menu1"><a id="inner-link" href="foo.html">Menu 1</a></div>' +
|
||||
'<a href="bar.html" contextmenu="menu2"><img id="menu2-trigger" src="example.png" /></a>' +
|
||||
'</body></html>';
|
||||
document.body.appendChild(iframe);
|
||||
|
||||
var mm;
|
||||
var numIframeLoaded = 0;
|
||||
var ctxMenuEvents = 0;
|
||||
var ctxCallbackEvents = 0;
|
||||
// The following code will be included in the child
|
||||
// =========================================================================
|
||||
function iframeScript() {
|
||||
addMessageListener('contextmenu', function onContextMenu(msg) {
|
||||
var document = content.document;
|
||||
var evt = document.createEvent('HTMLEvents');
|
||||
evt.initEvent('contextmenu', true, true);
|
||||
document.querySelector(msg.data.selector).dispatchEvent(evt);
|
||||
});
|
||||
|
||||
var cachedCtxDetail = null;
|
||||
addMessageListener('browser-element-api:call', function onCallback(msg) {
|
||||
if (msg.data.msg_name != 'fire-ctx-callback')
|
||||
return;
|
||||
|
||||
// We fire off various contextmenu events to check the data that gets
|
||||
// passed to the handler
|
||||
function iframeContextmenuHandler(e) {
|
||||
var detail = e.detail;
|
||||
ctxMenuEvents++;
|
||||
if (ctxMenuEvents === 1) {
|
||||
ok(detail.contextmenu === null, 'body context clicks have no context menu');
|
||||
} else if (ctxMenuEvents === 2) {
|
||||
cachedCtxDetail = detail;
|
||||
ok(detail.contextmenu.items.length === 2, 'trigger custom contextmenu');
|
||||
} else if (ctxMenuEvents === 3) {
|
||||
ok(detail.systemTargets.length === 1, 'Includes anchor data');
|
||||
ok(detail.contextmenu.items.length === 2, 'Inner clicks trigger correct menu');
|
||||
} else if (ctxMenuEvents === 4) {
|
||||
var innerMenu = detail.contextmenu.items.filter(function(x) {
|
||||
return x.type === 'menu';
|
||||
/* Use setTimeout in order to react *after* the platform */
|
||||
content.setTimeout(function() {
|
||||
sendAsyncMessage('test:callbackfired', { label: label });
|
||||
label = null;
|
||||
});
|
||||
ok(detail.systemTargets.length === 2, 'Includes anchor and img data');
|
||||
ok(innerMenu.length > 0, 'Menu contains a nested menu');
|
||||
ok(true, 'Got correct number of contextmenu events');
|
||||
// Finished testing the data passed to the contextmenu handler,
|
||||
// now we start selecting contextmenu items
|
||||
});
|
||||
|
||||
// This is previously triggered contextmenu data, since we have
|
||||
// fired subsequent contextmenus this should not be mistaken
|
||||
// for a current menuitem
|
||||
var prevId = cachedCtxDetail.contextmenu.items[0].id;
|
||||
cachedCtxDetail.contextMenuItemSelected(prevId);
|
||||
// This triggers a current menuitem
|
||||
detail.contextMenuItemSelected(innerMenu[0].items[1].id);
|
||||
// Once an item it selected, subsequent selections are ignored
|
||||
detail.contextMenuItemSelected(innerMenu[0].items[0].id);
|
||||
} else if (ctxMenuEvents === 5) {
|
||||
ok(detail.contextmenu.label === 'firstmenu', 'Correct menu enabled');
|
||||
detail.contextMenuItemSelected(detail.contextmenu.items[0].id);
|
||||
} else if (ctxMenuEvents === 6) {
|
||||
detail.contextMenuItemSelected(detail.contextmenu.items[1].id);
|
||||
} else if (ctxMenuEvents > 6) {
|
||||
ok(false, 'Too many events');
|
||||
}
|
||||
var label = null;
|
||||
XPCNativeWrapper.unwrap(content).onContextMenuCallbackFired = function(e) {
|
||||
label = e.target.getAttribute('label');
|
||||
};
|
||||
}
|
||||
// =========================================================================
|
||||
|
||||
function ctxCallbackRecieved(msg) {
|
||||
msg = SpecialPowers.wrap(msg);
|
||||
ctxCallbackEvents++;
|
||||
if (ctxCallbackEvents === 1) {
|
||||
ok(msg.json.data === 'inner2', 'Callback function got fired correctly');
|
||||
mm.loadFrameScript('data:,(' + trigger1.toString() + ')();', false);
|
||||
} else if (ctxCallbackEvents === 2) {
|
||||
ok(msg.json.data === 'foo', 'Callback function got fired correctly');
|
||||
mm.loadFrameScript('data:,(' + trigger1.toString() + ')();', false);
|
||||
} else if (ctxCallbackEvents > 2) {
|
||||
ok(false, 'Too many callback events');
|
||||
}
|
||||
}
|
||||
iframe.addEventListener('mozbrowserloadend', function onload(e) {
|
||||
iframe.removeEventListener(e.type, onload);
|
||||
mm = SpecialPowers.getBrowserFrameMessageManager(iframe);
|
||||
mm.loadFrameScript('data:,(' + iframeScript.toString() + ')();', false);
|
||||
|
||||
var gotError = false;
|
||||
function errorTriggered(msg) {
|
||||
if (gotError) {
|
||||
return;
|
||||
}
|
||||
|
||||
gotError = true;
|
||||
ok(true, 'An error in the callback triggers window.onerror');
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function iframeLoadedHandler() {
|
||||
numIframeLoaded++;
|
||||
if (numIframeLoaded === 2) {
|
||||
mm = SpecialPowers.getBrowserFrameMessageManager(iframe1);
|
||||
mm.addMessageListener('test:callbackfired', ctxCallbackRecieved);
|
||||
mm.addMessageListener('test:errorTriggered', errorTriggered);
|
||||
mm.loadFrameScript('data:,(' + iframeScript.toString() + ')();', false);
|
||||
}
|
||||
}
|
||||
|
||||
iframe1.addEventListener('mozbrowsercontextmenu', iframeContextmenuHandler);
|
||||
iframe1.addEventListener('mozbrowserloadend', iframeLoadedHandler);
|
||||
// Now we're ready, let's start testing.
|
||||
callback();
|
||||
});
|
||||
}
|
||||
|
||||
addEventListener('testready', runTest);
|
||||
addEventListener('testready', runTests);
|
||||
|
|
|
@ -9,18 +9,50 @@ SimpleTest.waitForExplicitFinish();
|
|||
browserElementTestHelpers.setEnabledPref(true);
|
||||
browserElementTestHelpers.addPermission();
|
||||
|
||||
var iframe = null;
|
||||
function runTest() {
|
||||
var iframe = document.createElement('iframe');
|
||||
iframe = document.createElement('iframe');
|
||||
SpecialPowers.wrap(iframe).mozbrowser = true;
|
||||
document.body.appendChild(iframe);
|
||||
|
||||
iframe.addEventListener("mozbrowsererror", function(e) {
|
||||
checkForGenericError();
|
||||
}
|
||||
|
||||
function checkForGenericError() {
|
||||
iframe.addEventListener("mozbrowsererror", function onGenericError(e) {
|
||||
iframe.removeEventListener(e.type, onGenericError);
|
||||
ok(true, "Got mozbrowsererror event.");
|
||||
ok(e.detail.type, "Event's detail has a |type| param.");
|
||||
SimpleTest.finish();
|
||||
ok(e.detail.type == "other", "Event's detail has a |type| param with the value '" + e.detail.type + "'.");
|
||||
|
||||
checkForExpiredCertificateError();
|
||||
});
|
||||
|
||||
iframe.src = "http://this_is_not_a_domain.example.com";
|
||||
}
|
||||
|
||||
function checkForExpiredCertificateError() {
|
||||
iframe.addEventListener("mozbrowsererror", function onCertError(e) {
|
||||
iframe.removeEventListener(e.type, onCertError);
|
||||
ok(true, "Got mozbrowsererror event.");
|
||||
ok(e.detail.type == "certerror", "Event's detail has a |type| param with the value '" + e.detail.type + "'.");
|
||||
|
||||
checkForNoCertificateError();
|
||||
});
|
||||
|
||||
iframe.src = "https://expired.example.com";
|
||||
document.body.appendChild(iframe);
|
||||
}
|
||||
|
||||
|
||||
function checkForNoCertificateError() {
|
||||
iframe.addEventListener("mozbrowsererror", function onCertError(e) {
|
||||
iframe.removeEventListener(e.type, onCertError);
|
||||
ok(true, "Got mozbrowsererror event.");
|
||||
ok(e.detail.type == "certerror", "Event's detail has a |type| param with the value '" + e.detail.type + "'.");
|
||||
|
||||
SimpleTest.finish();
|
||||
});
|
||||
|
||||
iframe.src = "https://nocert.example.com";
|
||||
}
|
||||
|
||||
addEventListener('testready', runTest);
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
/* Any copyright is dedicated to the public domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Test that the onmozbrowservisibilitychange event works.
|
||||
'use strict';
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
browserElementTestHelpers.setEnabledPref(true);
|
||||
browserElementTestHelpers.addPermission();
|
||||
|
||||
var iframe1 = null;
|
||||
function runTest() {
|
||||
iframe1 = document.createElement('iframe');
|
||||
SpecialPowers.wrap(iframe1).mozbrowser = true;
|
||||
document.body.appendChild(iframe1);
|
||||
|
||||
iframe1.src = 'data:text/html,<html><head><title>Title</title></head><body></body></html>';
|
||||
checkVisibilityFalse();
|
||||
}
|
||||
|
||||
function checkVisibilityFalse() {
|
||||
iframe1.addEventListener('mozbrowservisibilitychange', function onvisibilitychange(e) {
|
||||
iframe1.removeEventListener(e.type, onvisibilitychange);
|
||||
|
||||
is(e.detail.visible, false, 'Visibility should be false');
|
||||
checkVisibilityTrue();
|
||||
});
|
||||
|
||||
iframe1.setVisible(false);
|
||||
}
|
||||
|
||||
function checkVisibilityTrue() {
|
||||
iframe1.addEventListener('mozbrowservisibilitychange', function onvisibilitychange(e) {
|
||||
iframe1.removeEventListener(e.type, onvisibilitychange);
|
||||
|
||||
is(e.detail.visible, true, 'Visibility should be true');
|
||||
SimpleTest.finish();
|
||||
});
|
||||
|
||||
iframe1.setVisible(true);
|
||||
}
|
||||
|
||||
addEventListener('testready', runTest);
|
|
@ -0,0 +1,19 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=868816
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 868816</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="browserElementTestHelpers.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=868816">Mozilla Bug 868816</a>
|
||||
|
||||
<script type="application/javascript;version=1.7" src='browserElement_VisibilityChange.js'>
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,19 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=868816
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 868816</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="browserElementTestHelpers.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=868816">Mozilla Bug 868816</a>
|
||||
|
||||
<script type="application/javascript;version=1.7" src='browserElement_VisibilityChange.js'>
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -2031,7 +2031,6 @@ public:
|
|||
r = new PostResultEvent(mRequest, totalUsage);
|
||||
}
|
||||
NS_DispatchToMainThread(r);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -2778,6 +2777,7 @@ nsDOMDeviceStorage::AddNamed(nsIDOMBlob *aBlob,
|
|||
NS_ADDREF(*_retval = request);
|
||||
r = new PostErrorEvent(request, POST_ERROR_EVENT_UNKNOWN);
|
||||
NS_DispatchToMainThread(r);
|
||||
return NS_OK;
|
||||
}
|
||||
return ds->AddNamed(aBlob, storagePath, _retval);
|
||||
}
|
||||
|
|
|
@ -251,7 +251,7 @@ void SystemMessageHandledObserver::Init()
|
|||
mozilla::services::GetObserverService();
|
||||
|
||||
if (os) {
|
||||
os->AddObserver(this, "SystemMessageManager:HandleMessageDone",
|
||||
os->AddObserver(this, "handle-system-messages-done",
|
||||
/* ownsWeak */ false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1608,11 +1608,8 @@ TabChild::RecvMouseEvent(const nsString& aType,
|
|||
const int32_t& aModifiers,
|
||||
const bool& aIgnoreRootScrollFrame)
|
||||
{
|
||||
nsCOMPtr<nsIDOMWindowUtils> utils(GetDOMWindowUtils());
|
||||
NS_ENSURE_TRUE(utils, true);
|
||||
bool ignored = false;
|
||||
utils->SendMouseEvent(aType, aX, aY, aButton, aClickCount, aModifiers,
|
||||
aIgnoreRootScrollFrame, 0, 0, &ignored);
|
||||
DispatchMouseEvent(aType, aX, aY, aButton, aClickCount, aModifiers,
|
||||
aIgnoreRootScrollFrame);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1749,8 +1746,21 @@ void
|
|||
TabChild::FireContextMenuEvent()
|
||||
{
|
||||
MOZ_ASSERT(mTapHoldTimer && mActivePointerId >= 0);
|
||||
RecvHandleLongTap(mGestureDownPoint);
|
||||
CancelTapTracking();
|
||||
bool defaultPrevented = DispatchMouseEvent(NS_LITERAL_STRING("contextmenu"),
|
||||
mGestureDownPoint.x, mGestureDownPoint.y,
|
||||
2 /* Right button */,
|
||||
1 /* Click count */,
|
||||
0 /* Modifiers */,
|
||||
false /* Ignore root scroll frame */);
|
||||
|
||||
// Fire a click event if someone didn't call preventDefault() on the context
|
||||
// menu event.
|
||||
if (defaultPrevented) {
|
||||
CancelTapTracking();
|
||||
} else if (mTapHoldTimer) {
|
||||
mTapHoldTimer->Cancel();
|
||||
mTapHoldTimer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -2222,6 +2232,24 @@ TabChild::IsAsyncPanZoomEnabled()
|
|||
return mScrolling == ASYNC_PAN_ZOOM;
|
||||
}
|
||||
|
||||
bool
|
||||
TabChild::DispatchMouseEvent(const nsString& aType,
|
||||
const float& aX,
|
||||
const float& aY,
|
||||
const int32_t& aButton,
|
||||
const int32_t& aClickCount,
|
||||
const int32_t& aModifiers,
|
||||
const bool& aIgnoreRootScrollFrame)
|
||||
{
|
||||
nsCOMPtr<nsIDOMWindowUtils> utils(GetDOMWindowUtils());
|
||||
NS_ENSURE_TRUE(utils, true);
|
||||
|
||||
bool defaultPrevented = false;
|
||||
utils->SendMouseEvent(aType, aX, aY, aButton, aClickCount, aModifiers,
|
||||
aIgnoreRootScrollFrame, 0, 0, &defaultPrevented);
|
||||
return defaultPrevented;
|
||||
}
|
||||
|
||||
void
|
||||
TabChild::MakeVisible()
|
||||
{
|
||||
|
|
|
@ -306,6 +306,17 @@ public:
|
|||
|
||||
bool IsAsyncPanZoomEnabled();
|
||||
|
||||
/** Return a boolean indicating if the page has called preventDefault on
|
||||
* the event.
|
||||
*/
|
||||
bool DispatchMouseEvent(const nsString& aType,
|
||||
const float& aX,
|
||||
const float& aY,
|
||||
const int32_t& aButton,
|
||||
const int32_t& aClickCount,
|
||||
const int32_t& aModifiers,
|
||||
const bool& aIgnoreRootScrollFrame);
|
||||
|
||||
/**
|
||||
* Signal to this TabChild that it should be made visible:
|
||||
* activated widget, retained layer tree, etc. (Respectively,
|
||||
|
|
|
@ -21,6 +21,10 @@ XPCOMUtils.defineLazyServiceGetter(this, "gUUIDGenerator",
|
|||
"@mozilla.org/uuid-generator;1",
|
||||
"nsIUUIDGenerator");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "powerManagerService",
|
||||
"@mozilla.org/power/powermanagerservice;1",
|
||||
"nsIPowerManagerService");
|
||||
|
||||
// Limit the number of pending messages for a given page.
|
||||
let kMaxPendingMessages;
|
||||
try {
|
||||
|
@ -36,6 +40,7 @@ const kMessages =["SystemMessageManager:GetPendingMessages",
|
|||
"SystemMessageManager:Unregister",
|
||||
"SystemMessageManager:Message:Return:OK",
|
||||
"SystemMessageManager:AskReadyToRegister",
|
||||
"SystemMessageManager:HandleMessagesDone",
|
||||
"child-process-shutdown"]
|
||||
|
||||
function debug(aMsg) {
|
||||
|
@ -59,6 +64,8 @@ function SystemMessageInternal() {
|
|||
this._webappsRegistryReady = false;
|
||||
this._bufferedSysMsgs = [];
|
||||
|
||||
this._cpuWakeLocks = {};
|
||||
|
||||
Services.obs.addObserver(this, "xpcom-shutdown", false);
|
||||
Services.obs.addObserver(this, "webapps-registry-start", false);
|
||||
Services.obs.addObserver(this, "webapps-registry-ready", false);
|
||||
|
@ -70,6 +77,57 @@ function SystemMessageInternal() {
|
|||
}
|
||||
|
||||
SystemMessageInternal.prototype = {
|
||||
|
||||
_cancelCpuWakeLock: function _cancelCpuWakeLock(aPageKey) {
|
||||
let cpuWakeLock = this._cpuWakeLocks[aPageKey];
|
||||
if (cpuWakeLock) {
|
||||
debug("Releasing the CPU wake lock for page key = " + aPageKey);
|
||||
cpuWakeLock.wakeLock.unlock();
|
||||
cpuWakeLock.timer.cancel();
|
||||
delete this._cpuWakeLocks[aPageKey];
|
||||
}
|
||||
},
|
||||
|
||||
_acquireCpuWakeLock: function _acquireCpuWakeLock(aPageKey) {
|
||||
let cpuWakeLock = this._cpuWakeLocks[aPageKey];
|
||||
if (!cpuWakeLock) {
|
||||
// We have to ensure the CPU doesn't sleep during the process of the page
|
||||
// handling the system messages, so that they can be handled on time.
|
||||
debug("Acquiring a CPU wake lock for page key = " + aPageKey);
|
||||
cpuWakeLock = this._cpuWakeLocks[aPageKey] = {
|
||||
wakeLock: powerManagerService.newWakeLock("cpu"),
|
||||
timer: Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer),
|
||||
lockCount: 1
|
||||
};
|
||||
} else {
|
||||
// We've already acquired the CPU wake lock for this page,
|
||||
// so just add to the lock count and extend the timeout.
|
||||
cpuWakeLock.lockCount++;
|
||||
}
|
||||
|
||||
// Set a watchdog to avoid locking the CPU wake lock too long,
|
||||
// because it'd exhaust the battery quickly which is very bad.
|
||||
// This could probably happen if the app failed to launch or
|
||||
// handle the system messages due to any unexpected reasons.
|
||||
cpuWakeLock.timer.initWithCallback(function timerCb() {
|
||||
debug("Releasing the CPU wake lock because the system messages " +
|
||||
"were not handled by its registered page before time out.");
|
||||
this._cancelCpuWakeLock(aPageKey);
|
||||
}.bind(this), 30000, Ci.nsITimer.TYPE_ONE_SHOT);
|
||||
},
|
||||
|
||||
_releaseCpuWakeLock: function _releaseCpuWakeLock(aPageKey, aHandledCount) {
|
||||
let cpuWakeLock = this._cpuWakeLocks[aPageKey];
|
||||
if (cpuWakeLock) {
|
||||
cpuWakeLock.lockCount -= aHandledCount;
|
||||
if (cpuWakeLock.lockCount <= 0) {
|
||||
debug("Unlocking the CPU wake lock now that the system messages " +
|
||||
"have been successfully handled by its registered page.");
|
||||
this._cancelCpuWakeLock(aPageKey);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
sendMessage: function sendMessage(aType, aMessage, aPageURI, aManifestURI) {
|
||||
// Buffer system messages until the webapps' registration is ready,
|
||||
// so that we can know the correct pages registered to be sent.
|
||||
|
@ -224,7 +282,8 @@ SystemMessageInternal.prototype = {
|
|||
"SystemMessageManager:Unregister",
|
||||
"SystemMessageManager:GetPendingMessages",
|
||||
"SystemMessageManager:HasPendingMessages",
|
||||
"SystemMessageManager:Message:Return:OK"].indexOf(aMessage.name) != -1) {
|
||||
"SystemMessageManager:Message:Return:OK",
|
||||
"SystemMessageManager:HandleMessagesDone"].indexOf(aMessage.name) != -1) {
|
||||
if (!aMessage.target.assertContainApp(msg.manifest)) {
|
||||
debug("Got message from a child process containing illegal manifest URL.");
|
||||
return null;
|
||||
|
@ -237,13 +296,15 @@ SystemMessageInternal.prototype = {
|
|||
break;
|
||||
case "SystemMessageManager:Register":
|
||||
{
|
||||
debug("Got Register from " + msg.manifest);
|
||||
debug("Got Register from " + msg.uri + " @ " + msg.manifest);
|
||||
let targets, index;
|
||||
if (!(targets = this._listeners[msg.manifest])) {
|
||||
this._listeners[msg.manifest] = [{ target: aMessage.target,
|
||||
uri: msg.uri,
|
||||
winCount: 1 }];
|
||||
} else if ((index = this._findTargetIndex(targets, aMessage.target)) === -1) {
|
||||
targets.push({ target: aMessage.target,
|
||||
uri: msg.uri,
|
||||
winCount: 1 });
|
||||
} else {
|
||||
targets[index].winCount++;
|
||||
|
@ -301,7 +362,6 @@ SystemMessageInternal.prototype = {
|
|||
aMessage.target.sendAsyncMessage("SystemMessageManager:GetPendingMessages:Return",
|
||||
{ type: msg.type,
|
||||
manifest: msg.manifest,
|
||||
uri: msg.uri,
|
||||
msgQueue: pendingMessages });
|
||||
break;
|
||||
}
|
||||
|
@ -348,6 +408,16 @@ SystemMessageInternal.prototype = {
|
|||
}, this);
|
||||
break;
|
||||
}
|
||||
case "SystemMessageManager:HandleMessagesDone":
|
||||
{
|
||||
debug("received SystemMessageManager:HandleMessagesDone " + msg.type +
|
||||
" with " + msg.handledCount + " for " + msg.uri + " @ " + msg.manifest);
|
||||
|
||||
// A page has finished handling some of its system messages, so we try
|
||||
// to release the CPU wake lock we acquired on behalf of that page.
|
||||
this._releaseCpuWakeLock(this._createKeyForPage(msg), msg.handledCount);
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -440,19 +510,45 @@ SystemMessageInternal.prototype = {
|
|||
return false;
|
||||
}
|
||||
|
||||
let appPageIsRunning = false;
|
||||
let pageKey = this._createKeyForPage({ type: aType,
|
||||
manifest: aManifestURI,
|
||||
uri: aPageURI })
|
||||
|
||||
let targets = this._listeners[aManifestURI];
|
||||
if (targets) {
|
||||
for (let index = 0; index < targets.length; ++index) {
|
||||
let manager = targets[index].target;
|
||||
manager.sendAsyncMessage("SystemMessageManager:Message",
|
||||
{ type: aType,
|
||||
msg: aMessage,
|
||||
manifest: aManifestURI,
|
||||
uri: aPageURI,
|
||||
msgID: aMessageID });
|
||||
let target = targets[index];
|
||||
// We only need to send the system message to the targets which match
|
||||
// the manifest URL and page URL of the destination of system message.
|
||||
if (target.uri != aPageURI) {
|
||||
continue;
|
||||
}
|
||||
|
||||
appPageIsRunning = true;
|
||||
// We need to acquire a CPU wake lock for that page and expect that
|
||||
// we'll receive a "SystemMessageManager:HandleMessagesDone" message
|
||||
// when the page finishes handling the system message. At that point,
|
||||
// we'll release the lock we acquired.
|
||||
this._acquireCpuWakeLock(pageKey);
|
||||
|
||||
let manager = target.target;
|
||||
manager.sendAsyncMessage("SystemMessageManager:Message",
|
||||
{ type: aType,
|
||||
msg: aMessage,
|
||||
msgID: aMessageID });
|
||||
}
|
||||
}
|
||||
|
||||
if (!appPageIsRunning) {
|
||||
// The app page isn't running and relies on the 'open-app' chrome event to
|
||||
// wake it up. We still need to acquire a CPU wake lock for that page and
|
||||
// expect that we will receive a "SystemMessageManager:HandleMessagesDone"
|
||||
// message when the page finishes handling the system message with other
|
||||
// pending messages. At that point, we'll release the lock we acquired.
|
||||
this._acquireCpuWakeLock(pageKey);
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
|
|
|
@ -74,10 +74,6 @@ SystemMessageManager.prototype = {
|
|||
|
||||
aHandler.handleMessage(wrapped ? aMessage
|
||||
: ObjectWrapper.wrap(aMessage, this._window));
|
||||
|
||||
Services.obs.notifyObservers(/* aSubject */ null,
|
||||
"SystemMessageManager:HandleMessageDone",
|
||||
/* aData */ null);
|
||||
},
|
||||
|
||||
mozSetMessageHandler: function sysMessMgr_setMessageHandler(aType, aHandler) {
|
||||
|
@ -148,44 +144,59 @@ SystemMessageManager.prototype = {
|
|||
|
||||
cpmm.sendAsyncMessage("SystemMessageManager:Unregister",
|
||||
{ manifest: this._manifest,
|
||||
innerWindowID: this.innerWindowID
|
||||
});
|
||||
innerWindowID: this.innerWindowID });
|
||||
},
|
||||
|
||||
// Possible messages:
|
||||
//
|
||||
// - SystemMessageManager:Message
|
||||
// This one will only be received when the child process is alive when
|
||||
// the message is initially sent.
|
||||
//
|
||||
// - SystemMessageManager:GetPendingMessages:Return
|
||||
// This one will be received when the starting child process wants to
|
||||
// retrieve the pending system messages from the parent (i.e. after
|
||||
// sending SystemMessageManager:GetPendingMessages).
|
||||
receiveMessage: function sysMessMgr_receiveMessage(aMessage) {
|
||||
debug("receiveMessage " + aMessage.name + " for [" + aMessage.data.type + "] " +
|
||||
"with manifest = " + aMessage.data.manifest + " (" + this._manifest + ") " +
|
||||
"and uri = " + aMessage.data.uri + " (" + this._uri + ")");
|
||||
"with manifest = " + this._manifest + " and uri = " + this._uri);
|
||||
|
||||
let msg = aMessage.data;
|
||||
if (msg.manifest != this._manifest || msg.uri != this._uri) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aMessage.name == "SystemMessageManager:Message") {
|
||||
// Send an acknowledgement to parent to clean up the pending message,
|
||||
// so a re-launched app won't handle it again, which is redundant.
|
||||
cpmm.sendAsyncMessage(
|
||||
"SystemMessageManager:Message:Return:OK",
|
||||
{ type: msg.type,
|
||||
manifest: msg.manifest,
|
||||
uri: msg.uri,
|
||||
msgID: msg.msgID });
|
||||
}
|
||||
|
||||
// Bail out if we have no handlers registered for this type.
|
||||
if (!(msg.type in this._handlers)) {
|
||||
debug("No handler for this type");
|
||||
return;
|
||||
cpmm.sendAsyncMessage("SystemMessageManager:Message:Return:OK",
|
||||
{ type: msg.type,
|
||||
manifest: this._manifest,
|
||||
uri: this._uri,
|
||||
msgID: msg.msgID });
|
||||
}
|
||||
|
||||
let messages = (aMessage.name == "SystemMessageManager:Message")
|
||||
? [msg.msg]
|
||||
: msg.msgQueue;
|
||||
|
||||
messages.forEach(function(aMsg) {
|
||||
this._dispatchMessage(msg.type, this._handlers[msg.type], aMsg);
|
||||
}, this);
|
||||
// We only dispatch messages when a handler is registered.
|
||||
let handler = this._handlers[msg.type];
|
||||
if (handler) {
|
||||
messages.forEach(function(aMsg) {
|
||||
this._dispatchMessage(msg.type, handler, aMsg);
|
||||
}, this);
|
||||
}
|
||||
|
||||
// We need to notify the parent the system messages have been handled,
|
||||
// even if there are no handlers registered for them, so the parent can
|
||||
// release the CPU wake lock it took on our behalf.
|
||||
cpmm.sendAsyncMessage("SystemMessageManager:HandleMessagesDone",
|
||||
{ type: msg.type,
|
||||
manifest: this._manifest,
|
||||
uri: this._uri,
|
||||
handledCount: messages.length });
|
||||
|
||||
Services.obs.notifyObservers(/* aSubject */ null,
|
||||
"handle-system-messages-done",
|
||||
/* aData */ null);
|
||||
},
|
||||
|
||||
// nsIDOMGlobalPropertyInitializer implementation.
|
||||
|
@ -239,8 +250,9 @@ SystemMessageManager.prototype = {
|
|||
if (!this._registerManifestReady) {
|
||||
cpmm.sendAsyncMessage("SystemMessageManager:Register",
|
||||
{ manifest: this._manifest,
|
||||
innerWindowID: this.innerWindowID
|
||||
});
|
||||
uri: this._uri,
|
||||
innerWindowID: this.innerWindowID });
|
||||
|
||||
this._registerManifestReady = true;
|
||||
}
|
||||
},
|
||||
|
|
|
@ -718,19 +718,8 @@ function SendTransaction(msg) {
|
|||
if (DEBUG) debug("Check max values parameters fail.");
|
||||
throw new Error("Check max values parameters fail.");
|
||||
}
|
||||
let messageSize = 0;
|
||||
|
||||
if (msg.content) {
|
||||
messageSize = msg.content.length;
|
||||
} else if (msg.parts) {
|
||||
for (let i = 0; i < msg.parts.length; i++) {
|
||||
if (msg.parts[i].content.size) {
|
||||
messageSize += msg.parts[i].content.size;
|
||||
} else {
|
||||
messageSize += msg.parts[i].content.length;
|
||||
}
|
||||
}
|
||||
|
||||
if (msg.parts) {
|
||||
let contentType = {
|
||||
params: {
|
||||
// `The type parameter must be specified and its value is the MIME
|
||||
|
@ -757,10 +746,6 @@ function SendTransaction(msg) {
|
|||
msg.headers["content-type"] = contentType;
|
||||
}
|
||||
|
||||
// Assign to X-Mms-Message-Size
|
||||
msg.headers["x-mms-message-size"] = messageSize;
|
||||
// TODO: bug 809832 - support customizable max incoming/outgoing message size
|
||||
|
||||
if (DEBUG) debug("msg: " + JSON.stringify(msg));
|
||||
|
||||
this.msg = msg;
|
||||
|
|
|
@ -32,3 +32,4 @@ qemu = true
|
|||
[test_outgoing_max_segments.js]
|
||||
[test_update_thread_record_in_delete.js]
|
||||
[test_massive_incoming_delete.js]
|
||||
[test_getsegmentinfofortext.js]
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
MARIONETTE_TIMEOUT = 60000;
|
||||
|
||||
// Copied from dom/system/gonk/ril_consts.js.
|
||||
const PDU_MAX_USER_DATA_7BIT = 160;
|
||||
|
||||
SpecialPowers.setBoolPref("dom.sms.enabled", true);
|
||||
SpecialPowers.addPermission("sms", true, document);
|
||||
|
||||
let sms = window.navigator.mozSms;
|
||||
ok(sms instanceof MozSmsManager, "mozSmsManager");
|
||||
|
||||
let tasks = {
|
||||
// List of test fuctions. Each of them should call |tasks.next()| when
|
||||
// completed or |tasks.finish()| to jump to the last one.
|
||||
_tasks: [],
|
||||
_nextTaskIndex: 0,
|
||||
|
||||
push: function push(func) {
|
||||
this._tasks.push(func);
|
||||
},
|
||||
|
||||
next: function next() {
|
||||
let index = this._nextTaskIndex++;
|
||||
let task = this._tasks[index];
|
||||
try {
|
||||
task();
|
||||
} catch (ex) {
|
||||
ok(false, "test task[" + index + "] throws: " + ex);
|
||||
// Run last task as clean up if possible.
|
||||
if (index != this._tasks.length - 1) {
|
||||
this.finish();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
finish: function finish() {
|
||||
this._tasks[this._tasks.length - 1]();
|
||||
},
|
||||
|
||||
run: function run() {
|
||||
this.next();
|
||||
}
|
||||
};
|
||||
|
||||
function addTest(text, segments, charsPerSegment, charsAvailableInLastSegment) {
|
||||
tasks.push(function () {
|
||||
log("Testing '" + text + "' ...");
|
||||
let info = sms.getSegmentInfoForText(text);
|
||||
is(info.segments, segments, "info.segments");
|
||||
is(info.charsPerSegment, charsPerSegment, "info.charsPerSegment");
|
||||
is(info.charsAvailableInLastSegment, charsAvailableInLastSegment,
|
||||
"info.charsAvailableInLastSegment");
|
||||
|
||||
tasks.next();
|
||||
});
|
||||
}
|
||||
|
||||
function addTestThrows(text) {
|
||||
tasks.push(function () {
|
||||
log("Testing '" + text + "' ...");
|
||||
try {
|
||||
let info = sms.getSegmentInfoForText(text);
|
||||
|
||||
ok(false, "Not thrown");
|
||||
tasks.finish();
|
||||
} catch (e) {
|
||||
tasks.next();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
addTestThrows(null);
|
||||
|
||||
// Testing "undefined".
|
||||
addTest(undefined, 1, PDU_MAX_USER_DATA_7BIT,
|
||||
PDU_MAX_USER_DATA_7BIT - "undefined".length);
|
||||
|
||||
// Testing numeric values.
|
||||
addTest(0, 1, PDU_MAX_USER_DATA_7BIT, PDU_MAX_USER_DATA_7BIT - "0".length);
|
||||
addTest(1.0, 1, PDU_MAX_USER_DATA_7BIT, PDU_MAX_USER_DATA_7BIT - "1".length);
|
||||
|
||||
// Testing empty object. The empty object extends to "[object Object]" and both
|
||||
// '[' and ']' are in default single shift table, so each of them takes two
|
||||
// septets.
|
||||
addTest({}, 1, PDU_MAX_USER_DATA_7BIT,
|
||||
PDU_MAX_USER_DATA_7BIT - (("" + {}).length + 2));
|
||||
|
||||
// Testing Date object.
|
||||
let date = new Date();
|
||||
addTest(date, 1, PDU_MAX_USER_DATA_7BIT,
|
||||
PDU_MAX_USER_DATA_7BIT - ("" + date).length);
|
||||
|
||||
addTest("", 0, PDU_MAX_USER_DATA_7BIT,
|
||||
PDU_MAX_USER_DATA_7BIT - "".length);
|
||||
|
||||
// WARNING: All tasks should be pushed before this!!!
|
||||
tasks.push(function cleanUp() {
|
||||
SpecialPowers.removePermission("sms", document);
|
||||
SpecialPowers.clearUserPref("dom.sms.enabled");
|
||||
finish();
|
||||
});
|
||||
|
||||
tasks.run();
|
|
@ -269,8 +269,8 @@ NetworkStatsDB.prototype = {
|
|||
this.fillResultSamples(start, end, data);
|
||||
|
||||
txn.result.connectionType = aOptions.connectionType;
|
||||
txn.result.start = new Date(aOptions.start);
|
||||
txn.result.end = new Date(aOptions.end);
|
||||
txn.result.start = aOptions.start;
|
||||
txn.result.end = aOptions.end;
|
||||
txn.result.data = data;
|
||||
}.bind(this);
|
||||
}.bind(this), aResultCb);
|
||||
|
@ -315,8 +315,8 @@ NetworkStatsDB.prototype = {
|
|||
this.fillResultSamples(start, end, data);
|
||||
|
||||
txn.result.connectionType = aOptions.connectionType;
|
||||
txn.result.start = new Date(aOptions.start);
|
||||
txn.result.end = new Date(aOptions.end);
|
||||
txn.result.start = aOptions.start;
|
||||
txn.result.end = aOptions.end;
|
||||
txn.result.data = data;
|
||||
}.bind(this);
|
||||
}.bind(this), aResultCb);
|
||||
|
|
|
@ -51,9 +51,8 @@ function test() {
|
|||
}
|
||||
|
||||
function checkDataDates(data, start, end, sampleRate){
|
||||
var offset = new Date().getTimezoneOffset() * 60 * 1000;
|
||||
start = Math.floor((start.getTime() - offset) / sampleRate) * sampleRate + offset;
|
||||
end = Math.floor((end.getTime() - offset) / sampleRate) * sampleRate + offset;
|
||||
start = Math.floor(start.getTime() / sampleRate) * sampleRate;
|
||||
end = Math.floor(end.getTime() / sampleRate) * sampleRate;
|
||||
|
||||
var counter = 0;
|
||||
var date = start;
|
||||
|
@ -150,8 +149,7 @@ var steps = [
|
|||
// Get samplerate in millis
|
||||
var sampleRate = netStats.sampleRate * 1000;
|
||||
// Get date with samplerate's precision
|
||||
var offset = new Date().getTimezoneOffset() * 60 * 1000;
|
||||
var endDate = new Date(Math.floor((new Date().getTime() - offset) / sampleRate) * sampleRate + offset);
|
||||
var endDate = new Date(Math.floor(new Date().getTime() / sampleRate) * sampleRate);
|
||||
var startDate = new Date(endDate.getTime() - (sampleRate * diff));
|
||||
// Calculate the number of samples that should be returned based on the
|
||||
// the samplerate and including final and initial samples.
|
||||
|
@ -181,8 +179,7 @@ var steps = [
|
|||
// Get samplerate in millis
|
||||
var sampleRate = netStats.sampleRate * 1000;
|
||||
// Get date with samplerate's precision
|
||||
var offset = new Date().getTimezoneOffset() * 60 * 1000;
|
||||
var endDate = new Date(Math.floor((new Date().getTime() - offset) / sampleRate) * sampleRate + offset);
|
||||
var endDate = new Date(Math.floor(new Date().getTime() / sampleRate) * sampleRate);
|
||||
var startDate = new Date(endDate.getTime() - (sampleRate * diff));
|
||||
// Calculate the number of samples that should be returned based on the
|
||||
// the samplerate and including final and initial samples.
|
||||
|
|
|
@ -52,7 +52,7 @@ static int sMaxStreamVolumeTbl[AUDIO_STREAM_CNT] = {
|
|||
15, // FM
|
||||
};
|
||||
// A bitwise variable for recording what kind of headset is attached.
|
||||
static int sHeadsetState = SWITCH_STATE_OFF;
|
||||
static int sHeadsetState;
|
||||
static int kBtSampleRate = 8000;
|
||||
|
||||
class RecoverTask : public nsRunnable
|
||||
|
|
|
@ -2726,11 +2726,16 @@ RadioInterfaceLayer.prototype = {
|
|||
}
|
||||
|
||||
let options = this._fragmentText(text, null, strict7BitEncoding);
|
||||
let lastSegment = options.segments[options.segmentMaxSeq - 1];
|
||||
let charsInLastSegment = lastSegment.encodedBodyLength;
|
||||
if (options.dcs == RIL.PDU_DCS_MSG_CODING_16BITS_ALPHABET) {
|
||||
// In UCS2 encoding, encodedBodyLength is in octets.
|
||||
charsInLastSegment /= 2;
|
||||
let charsInLastSegment;
|
||||
if (options.segmentMaxSeq) {
|
||||
let lastSegment = options.segments[options.segmentMaxSeq - 1];
|
||||
charsInLastSegment = lastSegment.encodedBodyLength;
|
||||
if (options.dcs == RIL.PDU_DCS_MSG_CODING_16BITS_ALPHABET) {
|
||||
// In UCS2 encoding, encodedBodyLength is in octets.
|
||||
charsInLastSegment /= 2;
|
||||
}
|
||||
} else {
|
||||
charsInLastSegment = 0;
|
||||
}
|
||||
|
||||
let result = gMobileMessageService.createSmsSegmentInfo(options.segmentMaxSeq,
|
||||
|
|
|
@ -188,7 +188,7 @@ if test -n "$gonkdir" ; then
|
|||
;;
|
||||
esac
|
||||
|
||||
CPPFLAGS="-DANDROID -isystem $gonkdir/bionic/libc/$ARCH_DIR/include -isystem $gonkdir/bionic/libc/include/ -isystem $gonkdir/bionic/libc/kernel/common -isystem $gonkdir/bionic/libc/kernel/$ARCH_DIR -isystem $gonkdir/bionic/libm/include -I$gonkdir/frameworks/base/native/include -I$gonkdir/system/core/include -isystem $gonkdir/bionic $CPPFLAGS"
|
||||
CPPFLAGS="-DANDROID -isystem $gonkdir/bionic/libc/$ARCH_DIR/include -isystem $gonkdir/bionic/libc/include/ -isystem $gonkdir/bionic/libc/kernel/common -isystem $gonkdir/bionic/libc/kernel/$ARCH_DIR -isystem $gonkdir/bionic/libm/include -I$gonkdir/frameworks/base/native/include -I$gonkdir/system/core/include -isystem $gonkdir/bionic $CPPFLAGS -I$gonkdir/external/valgrind"
|
||||
CFLAGS="-mandroid -fno-short-enums -fno-exceptions $CFLAGS"
|
||||
CXXFLAGS="-mandroid -fno-short-enums -fno-exceptions -Wno-psabi $CXXFLAGS $STLPORT_CPPFLAGS"
|
||||
LIBS="$LIBS $STLPORT_LIBS"
|
||||
|
|
|
@ -158,7 +158,7 @@ skip-if(B2G) == filter-scaled-02.html filter-scaled-02-ref.html
|
|||
skip-if(B2G) == foreignObject-ancestor-style-change-01.svg foreignObject-ancestor-style-change-01-ref.svg
|
||||
skip-if(B2G) == foreignObject-change-transform-01.svg pass.svg
|
||||
== foreignObject-display-01.svg pass.svg
|
||||
== foreignObject-form-theme.svg foreignObject-form-theme-ref.html
|
||||
fails-if(B2G) == foreignObject-form-theme.svg foreignObject-form-theme-ref.html
|
||||
== foreignObject-img-form-theme.html foreignObject-img-form-theme-ref.html
|
||||
skip-if(B2G) == foreignObject-move-repaint-01.svg pass.svg
|
||||
== foreignObject-overflow-01.svg pass.svg
|
||||
|
|
Загрузка…
Ссылка в новой задаче