mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge m-c to inbound.
This commit is contained in:
commit
323496ebfb
@ -5,7 +5,7 @@
|
|||||||
"use strict"
|
"use strict"
|
||||||
|
|
||||||
function debug(str) {
|
function debug(str) {
|
||||||
//dump("-*- ContentPermissionPrompt: " + s + "\n");
|
//dump("-*- ContentPermissionPrompt: " + str + "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
const Ci = Components.interfaces;
|
const Ci = Components.interfaces;
|
||||||
@ -13,11 +13,14 @@ const Cr = Components.results;
|
|||||||
const Cu = Components.utils;
|
const Cu = Components.utils;
|
||||||
const Cc = Components.classes;
|
const Cc = Components.classes;
|
||||||
|
|
||||||
const PROMPT_FOR_UNKNOWN = ["geolocation", "desktop-notification",
|
const PROMPT_FOR_UNKNOWN = ["audio-capture",
|
||||||
"audio-capture"];
|
"desktop-notification",
|
||||||
|
"geolocation",
|
||||||
|
"video-capture"];
|
||||||
// Due to privary issue, permission requests like GetUserMedia should prompt
|
// Due to privary issue, permission requests like GetUserMedia should prompt
|
||||||
// every time instead of providing session persistence.
|
// every time instead of providing session persistence.
|
||||||
const PERMISSION_NO_SESSION = ["audio-capture"];
|
const PERMISSION_NO_SESSION = ["audio-capture", "video-capture"];
|
||||||
|
const ALLOW_MULTIPLE_REQUESTS = ["audio-capture", "video-capture"];
|
||||||
|
|
||||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
Cu.import("resource://gre/modules/Services.jsm");
|
Cu.import("resource://gre/modules/Services.jsm");
|
||||||
@ -41,7 +44,21 @@ XPCOMUtils.defineLazyServiceGetter(this,
|
|||||||
"@mozilla.org/telephony/audiomanager;1",
|
"@mozilla.org/telephony/audiomanager;1",
|
||||||
"nsIAudioManager");
|
"nsIAudioManager");
|
||||||
|
|
||||||
function rememberPermission(aPermission, aPrincipal, aSession)
|
/**
|
||||||
|
* aTypesInfo is an array of {permission, access, action, deny} which keeps
|
||||||
|
* the information of each permission. This arrary is initialized in
|
||||||
|
* ContentPermissionPrompt.prompt and used among functions.
|
||||||
|
*
|
||||||
|
* aTypesInfo[].permission : permission name
|
||||||
|
* aTypesInfo[].access : permission name + request.access
|
||||||
|
* aTypesInfo[].action : the default action of this permission
|
||||||
|
* aTypesInfo[].deny : true if security manager denied this app's origin
|
||||||
|
* principal.
|
||||||
|
* Note:
|
||||||
|
* aTypesInfo[].permission will be sent to prompt only when
|
||||||
|
* aTypesInfo[].action is PROMPT_ACTION and aTypesInfo[].deny is false.
|
||||||
|
*/
|
||||||
|
function rememberPermission(aTypesInfo, aPrincipal, aSession)
|
||||||
{
|
{
|
||||||
function convertPermToAllow(aPerm, aPrincipal)
|
function convertPermToAllow(aPerm, aPrincipal)
|
||||||
{
|
{
|
||||||
@ -49,12 +66,13 @@ function rememberPermission(aPermission, aPrincipal, aSession)
|
|||||||
permissionManager.testExactPermissionFromPrincipal(aPrincipal, aPerm);
|
permissionManager.testExactPermissionFromPrincipal(aPrincipal, aPerm);
|
||||||
if (type == Ci.nsIPermissionManager.PROMPT_ACTION ||
|
if (type == Ci.nsIPermissionManager.PROMPT_ACTION ||
|
||||||
(type == Ci.nsIPermissionManager.UNKNOWN_ACTION &&
|
(type == Ci.nsIPermissionManager.UNKNOWN_ACTION &&
|
||||||
PROMPT_FOR_UNKNOWN.indexOf(aPermission) >= 0)) {
|
PROMPT_FOR_UNKNOWN.indexOf(aPerm) >= 0)) {
|
||||||
|
debug("add " + aPerm + " to permission manager with ALLOW_ACTION");
|
||||||
if (!aSession) {
|
if (!aSession) {
|
||||||
permissionManager.addFromPrincipal(aPrincipal,
|
permissionManager.addFromPrincipal(aPrincipal,
|
||||||
aPerm,
|
aPerm,
|
||||||
Ci.nsIPermissionManager.ALLOW_ACTION);
|
Ci.nsIPermissionManager.ALLOW_ACTION);
|
||||||
} else if (PERMISSION_NO_SESSION.indexOf(aPermission) < 0) {
|
} else if (PERMISSION_NO_SESSION.indexOf(aPerm) < 0) {
|
||||||
permissionManager.addFromPrincipal(aPrincipal,
|
permissionManager.addFromPrincipal(aPrincipal,
|
||||||
aPerm,
|
aPerm,
|
||||||
Ci.nsIPermissionManager.ALLOW_ACTION,
|
Ci.nsIPermissionManager.ALLOW_ACTION,
|
||||||
@ -63,14 +81,18 @@ function rememberPermission(aPermission, aPrincipal, aSession)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expand the permission to see if we have multiple access properties to convert
|
for (let i in aTypesInfo) {
|
||||||
let access = PermissionsTable[aPermission].access;
|
// Expand the permission to see if we have multiple access properties
|
||||||
if (access) {
|
// to convert
|
||||||
for (let idx in access) {
|
let perm = aTypesInfo[i].permission;
|
||||||
convertPermToAllow(aPermission + "-" + access[idx], aPrincipal);
|
let access = PermissionsTable[perm].access;
|
||||||
|
if (access) {
|
||||||
|
for (let idx in access) {
|
||||||
|
convertPermToAllow(perm + "-" + access[idx], aPrincipal);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
convertPermToAllow(perm, aPrincipal);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
convertPermToAllow(aPermission, aPrincipal);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,23 +100,63 @@ function ContentPermissionPrompt() {}
|
|||||||
|
|
||||||
ContentPermissionPrompt.prototype = {
|
ContentPermissionPrompt.prototype = {
|
||||||
|
|
||||||
handleExistingPermission: function handleExistingPermission(request) {
|
handleExistingPermission: function handleExistingPermission(request,
|
||||||
let access = (request.access && request.access !== "unused") ? request.type + "-" + request.access :
|
typesInfo) {
|
||||||
request.type;
|
typesInfo.forEach(function(type) {
|
||||||
let result = Services.perms.testExactPermissionFromPrincipal(request.principal, access);
|
type.action =
|
||||||
if (result == Ci.nsIPermissionManager.ALLOW_ACTION) {
|
Services.perms.testExactPermissionFromPrincipal(request.principal,
|
||||||
|
type.access);
|
||||||
|
});
|
||||||
|
|
||||||
|
// If all permissions are allowed already, call allow() without prompting.
|
||||||
|
let checkAllowPermission = function(type) {
|
||||||
|
if (type.action == Ci.nsIPermissionManager.ALLOW_ACTION) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (typesInfo.every(checkAllowPermission)) {
|
||||||
|
debug("all permission requests are allowed");
|
||||||
request.allow();
|
request.allow();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (result == Ci.nsIPermissionManager.DENY_ACTION ||
|
|
||||||
result == Ci.nsIPermissionManager.UNKNOWN_ACTION && PROMPT_FOR_UNKNOWN.indexOf(access) < 0) {
|
// If all permissions are DENY_ACTION or UNKNOWN_ACTION, call cancel()
|
||||||
|
// without prompting.
|
||||||
|
let checkDenyPermission = function(type) {
|
||||||
|
if (type.action == Ci.nsIPermissionManager.DENY_ACTION ||
|
||||||
|
type.action == Ci.nsIPermissionManager.UNKNOWN_ACTION &&
|
||||||
|
PROMPT_FOR_UNKNOWN.indexOf(type.access) < 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (typesInfo.every(checkDenyPermission)) {
|
||||||
|
debug("all permission requests are denied");
|
||||||
request.cancel();
|
request.cancel();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
handledByApp: function handledByApp(request) {
|
// multiple requests should be audio and video
|
||||||
|
checkMultipleRequest: function checkMultipleRequest(typesInfo) {
|
||||||
|
if (typesInfo.length == 1) {
|
||||||
|
return true;
|
||||||
|
} else if (typesInfo.length > 1) {
|
||||||
|
let checkIfAllowMultiRequest = function(type) {
|
||||||
|
return (ALLOW_MULTIPLE_REQUESTS.indexOf(type.access) !== -1);
|
||||||
|
}
|
||||||
|
if (typesInfo.every(checkIfAllowMultiRequest)) {
|
||||||
|
debug("legal multiple requests");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
handledByApp: function handledByApp(request, typesInfo) {
|
||||||
if (request.principal.appId == Ci.nsIScriptSecurityManager.NO_APP_ID ||
|
if (request.principal.appId == Ci.nsIScriptSecurityManager.NO_APP_ID ||
|
||||||
request.principal.appId == Ci.nsIScriptSecurityManager.UNKNOWN_APP_ID) {
|
request.principal.appId == Ci.nsIScriptSecurityManager.UNKNOWN_APP_ID) {
|
||||||
// This should not really happen
|
// This should not really happen
|
||||||
@ -106,49 +168,94 @@ ContentPermissionPrompt.prototype = {
|
|||||||
.getService(Ci.nsIAppsService);
|
.getService(Ci.nsIAppsService);
|
||||||
let app = appsService.getAppByLocalId(request.principal.appId);
|
let app = appsService.getAppByLocalId(request.principal.appId);
|
||||||
|
|
||||||
let url = Services.io.newURI(app.origin, null, null);
|
// Check each permission if it's denied by permission manager with app's
|
||||||
let principal = secMan.getAppCodebasePrincipal(url, request.principal.appId,
|
// URL.
|
||||||
/*mozbrowser*/false);
|
let checkIfDenyAppPrincipal = function(type) {
|
||||||
let access = (request.access && request.access !== "unused") ? request.type + "-" + request.access :
|
let url = Services.io.newURI(app.origin, null, null);
|
||||||
request.type;
|
let principal = secMan.getAppCodebasePrincipal(url,
|
||||||
let result = Services.perms.testExactPermissionFromPrincipal(principal, access);
|
request.principal.appId,
|
||||||
|
/*mozbrowser*/false);
|
||||||
|
let result = Services.perms.testExactPermissionFromPrincipal(principal,
|
||||||
|
type.access);
|
||||||
|
|
||||||
if (result == Ci.nsIPermissionManager.ALLOW_ACTION ||
|
if (result == Ci.nsIPermissionManager.ALLOW_ACTION ||
|
||||||
result == Ci.nsIPermissionManager.PROMPT_ACTION) {
|
result == Ci.nsIPermissionManager.PROMPT_ACTION) {
|
||||||
return false;
|
type.deny = false;
|
||||||
|
}
|
||||||
|
return type.deny;
|
||||||
|
}
|
||||||
|
if (typesInfo.every(checkIfDenyAppPrincipal)) {
|
||||||
|
request.cancel();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
request.cancel();
|
return false;
|
||||||
return true;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
handledByPermissionType: function handledByPermissionType(request) {
|
handledByPermissionType: function handledByPermissionType(request, typesInfo) {
|
||||||
return permissionSpecificChecker.hasOwnProperty(request.type)
|
for (let i in typesInfo) {
|
||||||
? permissionSpecificChecker[request.type](request)
|
if (permissionSpecificChecker.hasOwnProperty(typesInfo[i].permission) &&
|
||||||
: false;
|
permissionSpecificChecker[typesInfo[i].permission](request)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
_id: 0,
|
_id: 0,
|
||||||
prompt: function(request) {
|
prompt: function(request) {
|
||||||
if (secMan.isSystemPrincipal(request.principal)) {
|
if (secMan.isSystemPrincipal(request.principal)) {
|
||||||
request.allow();
|
request.allow();
|
||||||
return true;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.handledByApp(request) ||
|
// Initialize the typesInfo and set the default value.
|
||||||
this.handledByPermissionType(request)) {
|
let typesInfo = [];
|
||||||
|
let perms = request.types.QueryInterface(Ci.nsIArray);
|
||||||
|
for (let idx = 0; idx < perms.length; idx++) {
|
||||||
|
let perm = perms.queryElementAt(idx, Ci.nsIContentPermissionType);
|
||||||
|
let tmp = {
|
||||||
|
permission: perm.type,
|
||||||
|
access: (perm.access && perm.access !== "unused") ?
|
||||||
|
perm.type + "-" + perm.access : perm.type,
|
||||||
|
deny: true,
|
||||||
|
action: Ci.nsIPermissionManager.UNKNOWN_ACTION
|
||||||
|
};
|
||||||
|
typesInfo.push(tmp);
|
||||||
|
}
|
||||||
|
if (typesInfo.length == 0) {
|
||||||
|
request.cancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!this.checkMultipleRequest(typesInfo)) {
|
||||||
|
request.cancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.handledByApp(request, typesInfo) ||
|
||||||
|
this.handledByPermissionType(request, typesInfo)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns true if the request was handled
|
// returns true if the request was handled
|
||||||
if (this.handleExistingPermission(request))
|
if (this.handleExistingPermission(request, typesInfo)) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// prompt PROMPT_ACTION request only.
|
||||||
|
typesInfo.forEach(function(aType, aIndex) {
|
||||||
|
if (aType.action != Ci.nsIPermissionManager.PROMPT_ACTION || aType.deny) {
|
||||||
|
typesInfo.splice(aIndex);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
let frame = request.element;
|
let frame = request.element;
|
||||||
let requestId = this._id++;
|
let requestId = this._id++;
|
||||||
|
|
||||||
if (!frame) {
|
if (!frame) {
|
||||||
this.delegatePrompt(request, requestId);
|
this.delegatePrompt(request, requestId, typesInfo);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -163,7 +270,7 @@ ContentPermissionPrompt.prototype = {
|
|||||||
if (evt.detail.visible === true)
|
if (evt.detail.visible === true)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
self.cancelPrompt(request, requestId);
|
self.cancelPrompt(request, requestId, typesInfo);
|
||||||
cancelRequest();
|
cancelRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,7 +287,7 @@ ContentPermissionPrompt.prototype = {
|
|||||||
// away but the request is still here.
|
// away but the request is still here.
|
||||||
frame.addEventListener("mozbrowservisibilitychange", onVisibilityChange);
|
frame.addEventListener("mozbrowservisibilitychange", onVisibilityChange);
|
||||||
|
|
||||||
self.delegatePrompt(request, requestId, function onCallback() {
|
self.delegatePrompt(request, requestId, typesInfo, function onCallback() {
|
||||||
frame.removeEventListener("mozbrowservisibilitychange", onVisibilityChange);
|
frame.removeEventListener("mozbrowservisibilitychange", onVisibilityChange);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -191,22 +298,17 @@ ContentPermissionPrompt.prototype = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
cancelPrompt: function(request, requestId) {
|
cancelPrompt: function(request, requestId, typesInfo) {
|
||||||
this.sendToBrowserWindow("cancel-permission-prompt", request, requestId);
|
this.sendToBrowserWindow("cancel-permission-prompt", request, requestId,
|
||||||
|
typesInfo);
|
||||||
},
|
},
|
||||||
|
|
||||||
delegatePrompt: function(request, requestId, callback) {
|
delegatePrompt: function(request, requestId, typesInfo, callback) {
|
||||||
let access = (request.access && request.access !== "unused") ? request.type + "-" + request.access :
|
|
||||||
request.type;
|
|
||||||
let principal = request.principal;
|
|
||||||
|
|
||||||
this._permission = access;
|
this.sendToBrowserWindow("permission-prompt", request, requestId, typesInfo,
|
||||||
this._uri = principal.URI.spec;
|
function(type, remember) {
|
||||||
this._origin = principal.origin;
|
|
||||||
|
|
||||||
this.sendToBrowserWindow("permission-prompt", request, requestId, function(type, remember) {
|
|
||||||
if (type == "permission-allow") {
|
if (type == "permission-allow") {
|
||||||
rememberPermission(request.type, principal, !remember);
|
rememberPermission(typesInfo, request.principal, !remember);
|
||||||
if (callback) {
|
if (callback) {
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
@ -214,14 +316,20 @@ ContentPermissionPrompt.prototype = {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (remember) {
|
let addDenyPermission = function(type) {
|
||||||
Services.perms.addFromPrincipal(principal, access,
|
debug("add " + type.permission +
|
||||||
Ci.nsIPermissionManager.DENY_ACTION);
|
" to permission manager with DENY_ACTION");
|
||||||
} else {
|
if (remember) {
|
||||||
Services.perms.addFromPrincipal(principal, access,
|
Services.perms.addFromPrincipal(request.principal, type.access,
|
||||||
Ci.nsIPermissionManager.DENY_ACTION,
|
Ci.nsIPermissionManager.DENY_ACTION);
|
||||||
Ci.nsIPermissionManager.EXPIRE_SESSION, 0);
|
} else {
|
||||||
|
Services.perms.addFromPrincipal(request.principal, type.access,
|
||||||
|
Ci.nsIPermissionManager.DENY_ACTION,
|
||||||
|
Ci.nsIPermissionManager.EXPIRE_SESSION,
|
||||||
|
0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
typesInfo.forEach(addDenyPermission);
|
||||||
|
|
||||||
if (callback) {
|
if (callback) {
|
||||||
callback();
|
callback();
|
||||||
@ -230,7 +338,7 @@ ContentPermissionPrompt.prototype = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
sendToBrowserWindow: function(type, request, requestId, callback) {
|
sendToBrowserWindow: function(type, request, requestId, typesInfo, callback) {
|
||||||
let browser = Services.wm.getMostRecentWindow("navigator:browser");
|
let browser = Services.wm.getMostRecentWindow("navigator:browser");
|
||||||
let content = browser.getContentWindow();
|
let content = browser.getContentWindow();
|
||||||
if (!content)
|
if (!content)
|
||||||
@ -253,10 +361,15 @@ ContentPermissionPrompt.prototype = {
|
|||||||
principal.appStatus == Ci.nsIPrincipal.APP_STATUS_CERTIFIED)
|
principal.appStatus == Ci.nsIPrincipal.APP_STATUS_CERTIFIED)
|
||||||
? true
|
? true
|
||||||
: request.remember;
|
: request.remember;
|
||||||
|
let permissions = [];
|
||||||
|
for (let i in typesInfo) {
|
||||||
|
debug("prompt " + typesInfo[i].permission);
|
||||||
|
permissions.push(typesInfo[i].permission);
|
||||||
|
}
|
||||||
|
|
||||||
let details = {
|
let details = {
|
||||||
type: type,
|
type: type,
|
||||||
permission: request.type,
|
permissions: permissions,
|
||||||
id: requestId,
|
id: requestId,
|
||||||
origin: principal.origin,
|
origin: principal.origin,
|
||||||
isApp: isApp,
|
isApp: isApp,
|
||||||
@ -289,6 +402,5 @@ ContentPermissionPrompt.prototype = {
|
|||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
|
||||||
//module initialization
|
//module initialization
|
||||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([ContentPermissionPrompt]);
|
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([ContentPermissionPrompt]);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
{
|
{
|
||||||
"revision": "9c89bc252dca005ec14f54d6d8524b44917322b2",
|
"revision": "53c6a2b0bf4c238d39ee0096b79d911aec2de0fc",
|
||||||
"repo_path": "/integration/gaia-central"
|
"repo_path": "/integration/gaia-central"
|
||||||
}
|
}
|
||||||
|
@ -244,6 +244,7 @@ pref("lightweightThemes.update.enabled", true);
|
|||||||
|
|
||||||
// UI tour experience.
|
// UI tour experience.
|
||||||
pref("browser.uitour.enabled", true);
|
pref("browser.uitour.enabled", true);
|
||||||
|
pref("browser.uitour.requireSecure", true);
|
||||||
pref("browser.uitour.themeOrigin", "https://addons.mozilla.org/%LOCALE%/firefox/themes/");
|
pref("browser.uitour.themeOrigin", "https://addons.mozilla.org/%LOCALE%/firefox/themes/");
|
||||||
pref("browser.uitour.pinnedTabUrl", "https://support.mozilla.org/%LOCALE%/kb/pinned-tabs-keep-favorite-websites-open");
|
pref("browser.uitour.pinnedTabUrl", "https://support.mozilla.org/%LOCALE%/kb/pinned-tabs-keep-favorite-websites-open");
|
||||||
pref("browser.uitour.whitelist.add.260", "www.mozilla.org,support.mozilla.org");
|
pref("browser.uitour.whitelist.add.260", "www.mozilla.org,support.mozilla.org");
|
||||||
|
@ -146,7 +146,8 @@ let gPage = {
|
|||||||
handleEvent: function Page_handleEvent(aEvent) {
|
handleEvent: function Page_handleEvent(aEvent) {
|
||||||
switch (aEvent.type) {
|
switch (aEvent.type) {
|
||||||
case "unload":
|
case "unload":
|
||||||
this._mutationObserver.disconnect();
|
if (this._mutationObserver)
|
||||||
|
this._mutationObserver.disconnect();
|
||||||
gAllPages.unregister(this);
|
gAllPages.unregister(this);
|
||||||
break;
|
break;
|
||||||
case "click":
|
case "click":
|
||||||
|
@ -15,24 +15,20 @@ function test() {
|
|||||||
// Verify that about:preferences tab is displayed when
|
// Verify that about:preferences tab is displayed when
|
||||||
// browser.preferences.inContent is set to true
|
// browser.preferences.inContent is set to true
|
||||||
Services.prefs.setBoolPref("browser.preferences.inContent", true);
|
Services.prefs.setBoolPref("browser.preferences.inContent", true);
|
||||||
|
|
||||||
gBrowser.tabContainer.addEventListener("TabOpen", function(aEvent) {
|
// Open a new tab.
|
||||||
|
whenNewTabLoaded(window, testPreferences);
|
||||||
gBrowser.tabContainer.removeEventListener("TabOpen", arguments.callee, true);
|
}
|
||||||
let browser = aEvent.originalTarget.linkedBrowser;
|
|
||||||
browser.addEventListener("load", function(aEvent) {
|
function testPreferences() {
|
||||||
browser.removeEventListener("load", arguments.callee, true);
|
whenTabLoaded(gBrowser.selectedTab, function () {
|
||||||
|
is(Services.prefs.getBoolPref("browser.preferences.inContent"), true, "In-content prefs are enabled");
|
||||||
is(Services.prefs.getBoolPref("browser.preferences.inContent"), true, "In-content prefs are enabled");
|
is(content.location.href, "about:preferences", "Checking if the preferences tab was opened");
|
||||||
is(browser.contentWindow.location.href, "about:preferences", "Checking if the preferences tab was opened");
|
|
||||||
|
gBrowser.removeCurrentTab();
|
||||||
gBrowser.removeCurrentTab();
|
Services.prefs.setBoolPref("browser.preferences.inContent", false);
|
||||||
Services.prefs.setBoolPref("browser.preferences.inContent", false);
|
openPreferences();
|
||||||
openPreferences();
|
});
|
||||||
|
|
||||||
}, true);
|
|
||||||
}, true);
|
|
||||||
|
|
||||||
|
|
||||||
let observer = {
|
let observer = {
|
||||||
observe: function(aSubject, aTopic, aData) {
|
observe: function(aSubject, aTopic, aData) {
|
||||||
|
@ -237,9 +237,14 @@ function whenNewTabLoaded(aWindow, aCallback) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
whenTabLoaded(aWindow.gBrowser.selectedTab, aCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
function whenTabLoaded(aTab, aCallback) {
|
||||||
|
let browser = aTab.linkedBrowser;
|
||||||
browser.addEventListener("load", function onLoad() {
|
browser.addEventListener("load", function onLoad() {
|
||||||
browser.removeEventListener("load", onLoad, true);
|
browser.removeEventListener("load", onLoad, true);
|
||||||
aCallback();
|
executeSoon(aCallback);
|
||||||
}, true);
|
}, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -473,8 +473,37 @@ function openAboutDialog() {
|
|||||||
|
|
||||||
function openPreferences(paneID, extraArgs)
|
function openPreferences(paneID, extraArgs)
|
||||||
{
|
{
|
||||||
if (Services.prefs.getBoolPref("browser.preferences.inContent")) {
|
function switchToAdvancedSubPane(doc) {
|
||||||
openUILinkIn("about:preferences", "tab");
|
if (extraArgs && extraArgs["advancedTab"]) {
|
||||||
|
let advancedPaneTabs = doc.getElementById("advancedPrefs");
|
||||||
|
advancedPaneTabs.selectedTab = doc.getElementById(extraArgs["advancedTab"]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getBoolPref("browser.preferences.inContent")) {
|
||||||
|
let win = Services.wm.getMostRecentWindow("navigator:browser");
|
||||||
|
if (!win) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let newLoad = !win.switchToTabHavingURI("about:preferences", true);
|
||||||
|
let browser = win.gBrowser.selectedBrowser;
|
||||||
|
|
||||||
|
function switchToPane() {
|
||||||
|
if (paneID) {
|
||||||
|
browser.contentWindow.selectCategory(paneID);
|
||||||
|
}
|
||||||
|
switchToAdvancedSubPane(browser.contentDocument);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newLoad) {
|
||||||
|
browser.addEventListener("load", function onload() {
|
||||||
|
browser.removeEventListener("load", onload, true);
|
||||||
|
switchToPane();
|
||||||
|
}, true);
|
||||||
|
} else {
|
||||||
|
switchToPane();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
var instantApply = getBoolPref("browser.preferences.instantApply", false);
|
var instantApply = getBoolPref("browser.preferences.instantApply", false);
|
||||||
var features = "chrome,titlebar,toolbar,centerscreen" + (instantApply ? ",dialog=no" : ",modal");
|
var features = "chrome,titlebar,toolbar,centerscreen" + (instantApply ? ",dialog=no" : ",modal");
|
||||||
@ -487,16 +516,11 @@ function openPreferences(paneID, extraArgs)
|
|||||||
win.document.documentElement.showPane(pane);
|
win.document.documentElement.showPane(pane);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (extraArgs && extraArgs["advancedTab"]) {
|
switchToAdvancedSubPane(win.document);
|
||||||
var advancedPaneTabs = win.document.getElementById("advancedPrefs");
|
} else {
|
||||||
advancedPaneTabs.selectedTab = win.document.getElementById(extraArgs["advancedTab"]);
|
openDialog("chrome://browser/content/preferences/preferences.xul",
|
||||||
}
|
"Preferences", features, paneID, extraArgs);
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
openDialog("chrome://browser/content/preferences/preferences.xul",
|
|
||||||
"Preferences", features, paneID, extraArgs);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -452,8 +452,10 @@ nsBrowserContentHandler.prototype = {
|
|||||||
var chromeParam = cmdLine.handleFlagWithParam("chrome", false);
|
var chromeParam = cmdLine.handleFlagWithParam("chrome", false);
|
||||||
if (chromeParam) {
|
if (chromeParam) {
|
||||||
|
|
||||||
// Handle the old preference dialog URL separately (bug 285416)
|
// Handle old preference dialog URLs.
|
||||||
if (chromeParam == "chrome://browser/content/pref/pref.xul") {
|
if (chromeParam == "chrome://browser/content/pref/pref.xul" ||
|
||||||
|
(Services.prefs.getBoolPref("browser.preferences.inContent") &&
|
||||||
|
chromeParam == "chrome://browser/content/preferences/preferences.xul")) {
|
||||||
openPreferences();
|
openPreferences();
|
||||||
cmdLine.preventDefault = true;
|
cmdLine.preventDefault = true;
|
||||||
} else try {
|
} else try {
|
||||||
|
@ -1995,13 +1995,21 @@ ContentPermissionPrompt.prototype = {
|
|||||||
|
|
||||||
prompt: function CPP_prompt(request) {
|
prompt: function CPP_prompt(request) {
|
||||||
|
|
||||||
|
// Only allow exactly one permission rquest here.
|
||||||
|
let types = request.types.QueryInterface(Ci.nsIArray);
|
||||||
|
if (types.length != 1) {
|
||||||
|
request.cancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let perm = types.queryElementAt(0, Ci.nsIContentPermissionType);
|
||||||
|
|
||||||
const kFeatureKeys = { "geolocation" : "geo",
|
const kFeatureKeys = { "geolocation" : "geo",
|
||||||
"desktop-notification" : "desktop-notification",
|
"desktop-notification" : "desktop-notification",
|
||||||
"pointerLock" : "pointerLock",
|
"pointerLock" : "pointerLock",
|
||||||
};
|
};
|
||||||
|
|
||||||
// Make sure that we support the request.
|
// Make sure that we support the request.
|
||||||
if (!(request.type in kFeatureKeys)) {
|
if (!(perm.type in kFeatureKeys)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2013,7 +2021,7 @@ ContentPermissionPrompt.prototype = {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
var autoAllow = false;
|
var autoAllow = false;
|
||||||
var permissionKey = kFeatureKeys[request.type];
|
var permissionKey = kFeatureKeys[perm.type];
|
||||||
var result = Services.perms.testExactPermissionFromPrincipal(requestingPrincipal, permissionKey);
|
var result = Services.perms.testExactPermissionFromPrincipal(requestingPrincipal, permissionKey);
|
||||||
|
|
||||||
if (result == Ci.nsIPermissionManager.DENY_ACTION) {
|
if (result == Ci.nsIPermissionManager.DENY_ACTION) {
|
||||||
@ -2024,14 +2032,14 @@ ContentPermissionPrompt.prototype = {
|
|||||||
if (result == Ci.nsIPermissionManager.ALLOW_ACTION) {
|
if (result == Ci.nsIPermissionManager.ALLOW_ACTION) {
|
||||||
autoAllow = true;
|
autoAllow = true;
|
||||||
// For pointerLock, we still want to show a warning prompt.
|
// For pointerLock, we still want to show a warning prompt.
|
||||||
if (request.type != "pointerLock") {
|
if (perm.type != "pointerLock") {
|
||||||
request.allow();
|
request.allow();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show the prompt.
|
// Show the prompt.
|
||||||
switch (request.type) {
|
switch (perm.type) {
|
||||||
case "geolocation":
|
case "geolocation":
|
||||||
this._promptGeo(request);
|
this._promptGeo(request);
|
||||||
break;
|
break;
|
||||||
|
@ -2,11 +2,11 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
richlistitem {
|
#handlersView > richlistitem {
|
||||||
-moz-binding: url("chrome://browser/content/preferences/handlers.xml#handler");
|
-moz-binding: url("chrome://browser/content/preferences/handlers.xml#handler");
|
||||||
}
|
}
|
||||||
|
|
||||||
richlistitem[selected="true"] {
|
#handlersView > richlistitem[selected="true"] {
|
||||||
-moz-binding: url("chrome://browser/content/preferences/handlers.xml#handler-selected");
|
-moz-binding: url("chrome://browser/content/preferences/handlers.xml#handler-selected");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,11 +128,6 @@
|
|||||||
#endif
|
#endif
|
||||||
<stringbundle id="bundlePreferences" src="chrome://browser/locale/preferences/preferences.properties"/>
|
<stringbundle id="bundlePreferences" src="chrome://browser/locale/preferences/preferences.properties"/>
|
||||||
|
|
||||||
<hbox class="heading" data-category="paneAdvanced" hidden="true">
|
|
||||||
<image class="preference-icon" type="advanced"/>
|
|
||||||
<html:h1>&paneAdvanced.title;</html:h1>
|
|
||||||
</hbox>
|
|
||||||
|
|
||||||
<tabbox id="advancedPrefs" flex="1"
|
<tabbox id="advancedPrefs" flex="1"
|
||||||
data-category="paneAdvanced" hidden="true"
|
data-category="paneAdvanced" hidden="true"
|
||||||
onselect="gAdvancedPane.tabSelectionChanged();">
|
onselect="gAdvancedPane.tabSelectionChanged();">
|
||||||
|
@ -55,11 +55,6 @@
|
|||||||
<key key="&focusSearch2.key;" modifiers="accel" oncommand="gApplicationsPane.focusFilterBox();"/>
|
<key key="&focusSearch2.key;" modifiers="accel" oncommand="gApplicationsPane.focusFilterBox();"/>
|
||||||
</keyset>
|
</keyset>
|
||||||
|
|
||||||
<hbox class="heading" data-category="paneApplications" hidden="true">
|
|
||||||
<image class="preference-icon" type="applications"/>
|
|
||||||
<html:h1>&paneApplications.title;</html:h1>
|
|
||||||
</hbox>
|
|
||||||
|
|
||||||
<vbox data-category="paneApplications" hidden="true" flex="1">
|
<vbox data-category="paneApplications" hidden="true" flex="1">
|
||||||
<hbox>
|
<hbox>
|
||||||
<textbox id="filter" flex="1"
|
<textbox id="filter" flex="1"
|
||||||
|
@ -21,12 +21,9 @@
|
|||||||
<script type="application/javascript"
|
<script type="application/javascript"
|
||||||
src="chrome://browser/content/preferences/in-content/content.js"/>
|
src="chrome://browser/content/preferences/in-content/content.js"/>
|
||||||
|
|
||||||
<hbox class="heading" data-category="paneContent" hidden="true">
|
|
||||||
<image class="preference-icon" type="content"/>
|
|
||||||
<html:h1>&paneContent.title;</html:h1>
|
|
||||||
</hbox>
|
|
||||||
|
|
||||||
<groupbox id="miscGroup" data-category="paneContent" hidden="true">
|
<groupbox id="miscGroup" data-category="paneContent" hidden="true">
|
||||||
|
<caption label="&popups.label;"/>
|
||||||
|
|
||||||
<grid id="contentGrid">
|
<grid id="contentGrid">
|
||||||
<columns>
|
<columns>
|
||||||
<column flex="1"/>
|
<column flex="1"/>
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
browser.jar:
|
browser.jar:
|
||||||
content/browser/preferences/in-content/preferences.js
|
content/browser/preferences/in-content/preferences.js
|
||||||
content/browser/preferences/in-content/landing.xul
|
|
||||||
* content/browser/preferences/in-content/preferences.xul
|
* content/browser/preferences/in-content/preferences.xul
|
||||||
* content/browser/preferences/in-content/main.xul
|
* content/browser/preferences/in-content/main.xul
|
||||||
* content/browser/preferences/in-content/main.js
|
* content/browser/preferences/in-content/main.js
|
||||||
|
@ -1,55 +0,0 @@
|
|||||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
- License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
||||||
- You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
|
||||||
|
|
||||||
<vbox data-category="landing">
|
|
||||||
<html:h1 class="indent-small">&brandShortName;</html:h1>
|
|
||||||
|
|
||||||
<hbox id="preferences-home" flex="1">
|
|
||||||
|
|
||||||
<button label="&paneGeneral.title;" class="landingButton"
|
|
||||||
oncommand="gotoPref('paneGeneral');">
|
|
||||||
<image class="landingButton-icon" type="general"/>
|
|
||||||
<label class="landingButton-label">&paneGeneral.title;</label>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<button label="&paneContent.title;" class="landingButton"
|
|
||||||
oncommand="gotoPref('paneContent');">
|
|
||||||
<image class="landingButton-icon" type="content"/>
|
|
||||||
<label class="landingButton-label">&paneContent.title;</label>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button label="&paneApplications.title;" class="landingButton"
|
|
||||||
oncommand="gotoPref('paneApplications');">
|
|
||||||
<image class="landingButton-icon" type="applications"/>
|
|
||||||
<label class="landingButton-label">&paneApplications.title;</label>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button label="&panePrivacy.title;" class="landingButton"
|
|
||||||
oncommand="gotoPref('panePrivacy');">
|
|
||||||
<image class="landingButton-icon" type="privacy"/>
|
|
||||||
<label class="landingButton-label">&panePrivacy.title;</label>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button label="&paneSecurity.title;" class="landingButton"
|
|
||||||
oncommand="gotoPref('paneSecurity');">
|
|
||||||
<image class="landingButton-icon" type="security"/>
|
|
||||||
<label class="landingButton-label">&paneSecurity.title;</label>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button label="&paneSync.title;" class="landingButton"
|
|
||||||
oncommand="gotoPref('paneSync');">
|
|
||||||
<image class="landingButton-icon" type="sync"/>
|
|
||||||
<label class="landingButton-label">&paneSync.title;</label>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button label="&paneAdvanced.title;" class="landingButton"
|
|
||||||
oncommand="gotoPref('paneAdvanced');">
|
|
||||||
<image class="landingButton-icon" type="advanced"/>
|
|
||||||
<label class="landingButton-label">&paneAdvanced.title;</label>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
</hbox>
|
|
||||||
</vbox>
|
|
@ -85,13 +85,8 @@
|
|||||||
#endif
|
#endif
|
||||||
</preferences>
|
</preferences>
|
||||||
|
|
||||||
<hbox class="heading" data-category="paneGeneral" hidden="true">
|
|
||||||
<image class="preference-icon" type="general"/>
|
|
||||||
<html:h1>&paneGeneral.title;</html:h1>
|
|
||||||
</hbox>
|
|
||||||
|
|
||||||
<!-- Startup -->
|
<!-- Startup -->
|
||||||
<groupbox id="startupGroup" data-category="paneGeneral" hidden="true">
|
<groupbox id="startupGroup" data-category="paneGeneral">
|
||||||
<caption label="&startup.label;"/>
|
<caption label="&startup.label;"/>
|
||||||
|
|
||||||
<hbox align="center">
|
<hbox align="center">
|
||||||
@ -150,7 +145,7 @@
|
|||||||
</groupbox>
|
</groupbox>
|
||||||
|
|
||||||
<!-- Downloads -->
|
<!-- Downloads -->
|
||||||
<groupbox id="downloadsGroup" data-category="paneGeneral" hidden="true">
|
<groupbox id="downloadsGroup" data-category="paneGeneral">
|
||||||
<caption label="&downloads.label;"/>
|
<caption label="&downloads.label;"/>
|
||||||
|
|
||||||
<radiogroup id="saveWhere"
|
<radiogroup id="saveWhere"
|
||||||
@ -189,7 +184,7 @@
|
|||||||
</groupbox>
|
</groupbox>
|
||||||
|
|
||||||
<!-- Tab preferences -->
|
<!-- Tab preferences -->
|
||||||
<groupbox data-category="paneGeneral" hidden="true">
|
<groupbox data-category="paneGeneral">
|
||||||
<caption label="&tabsGroup.label;"/>
|
<caption label="&tabsGroup.label;"/>
|
||||||
<checkbox id="linkTargeting" label="&newWindowsAsTabs.label;"
|
<checkbox id="linkTargeting" label="&newWindowsAsTabs.label;"
|
||||||
accesskey="&newWindowsAsTabs.accesskey;"
|
accesskey="&newWindowsAsTabs.accesskey;"
|
||||||
|
@ -12,11 +12,13 @@ const Cr = Components.results;
|
|||||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
Cu.import("resource://gre/modules/Services.jsm");
|
Cu.import("resource://gre/modules/Services.jsm");
|
||||||
|
|
||||||
|
addEventListener("DOMContentLoaded", function onLoad() {
|
||||||
|
removeEventListener("DOMContentLoaded", onLoad);
|
||||||
|
init_all();
|
||||||
|
});
|
||||||
|
|
||||||
function init_all() {
|
function init_all() {
|
||||||
document.documentElement.instantApply = true;
|
document.documentElement.instantApply = true;
|
||||||
window.history.replaceState("landing", document.title);
|
|
||||||
window.addEventListener("popstate", onStatePopped, true);
|
|
||||||
updateCommands();
|
|
||||||
gMainPane.init();
|
gMainPane.init();
|
||||||
gPrivacyPane.init();
|
gPrivacyPane.init();
|
||||||
gAdvancedPane.init();
|
gAdvancedPane.init();
|
||||||
@ -27,12 +29,32 @@ function init_all() {
|
|||||||
var initFinished = document.createEvent("Event");
|
var initFinished = document.createEvent("Event");
|
||||||
initFinished.initEvent("Initialized", true, true);
|
initFinished.initEvent("Initialized", true, true);
|
||||||
document.dispatchEvent(initFinished);
|
document.dispatchEvent(initFinished);
|
||||||
|
|
||||||
|
let categories = document.getElementById("categories");
|
||||||
|
categories.addEventListener("select", event => gotoPref(event.target.value));
|
||||||
|
window.addEventListener("popstate", event => selectCategory(event.state));
|
||||||
|
|
||||||
|
if (history.length > 1 && history.state) {
|
||||||
|
updateCommands();
|
||||||
|
selectCategory(history.state);
|
||||||
|
} else {
|
||||||
|
history.replaceState("paneGeneral", document.title);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function selectCategory(name) {
|
||||||
|
let categories = document.getElementById("categories");
|
||||||
|
let item = categories.querySelector(".category[value=" + name + "]");
|
||||||
|
categories.selectedItem = item;
|
||||||
}
|
}
|
||||||
|
|
||||||
function gotoPref(page) {
|
function gotoPref(page) {
|
||||||
search(page, "data-category");
|
if (history.state != page) {
|
||||||
window.history.pushState(page, document.title);
|
window.history.pushState(page, document.title);
|
||||||
|
}
|
||||||
|
|
||||||
updateCommands();
|
updateCommands();
|
||||||
|
search(page, "data-category");
|
||||||
}
|
}
|
||||||
|
|
||||||
function cmd_back() {
|
function cmd_back() {
|
||||||
@ -43,11 +65,6 @@ function cmd_forward() {
|
|||||||
window.history.forward();
|
window.history.forward();
|
||||||
}
|
}
|
||||||
|
|
||||||
function onStatePopped(aEvent) {
|
|
||||||
updateCommands();
|
|
||||||
search(aEvent.state, "data-category");
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateCommands() {
|
function updateCommands() {
|
||||||
document.getElementById("back-btn").disabled = !canGoBack();
|
document.getElementById("back-btn").disabled = !canGoBack();
|
||||||
document.getElementById("forward-btn").disabled = !canGoForward();
|
document.getElementById("forward-btn").disabled = !canGoForward();
|
||||||
|
@ -54,8 +54,7 @@
|
|||||||
#define USE_WIN_TITLE_STYLE
|
#define USE_WIN_TITLE_STYLE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
<page onload="init_all();"
|
<page xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
|
||||||
xmlns:html="http://www.w3.org/1999/xhtml"
|
xmlns:html="http://www.w3.org/1999/xhtml"
|
||||||
#ifdef USE_WIN_TITLE_STYLE
|
#ifdef USE_WIN_TITLE_STYLE
|
||||||
title="&prefWindow.titleWin;">
|
title="&prefWindow.titleWin;">
|
||||||
@ -86,10 +85,58 @@
|
|||||||
oncommand="cmd_forward()" tooltiptext="&buttonForward.tooltip;"
|
oncommand="cmd_forward()" tooltiptext="&buttonForward.tooltip;"
|
||||||
disabled="true"/>
|
disabled="true"/>
|
||||||
</hbox>
|
</hbox>
|
||||||
|
|
||||||
<hbox class="main-content" flex="1">
|
<hbox flex="1">
|
||||||
<prefpane flex="1" id="mainPrefPane">
|
|
||||||
#include landing.xul
|
<!-- category list -->
|
||||||
|
<richlistbox id="categories">
|
||||||
|
<richlistitem id="category-general" class="category" align="center"
|
||||||
|
value="paneGeneral" tooltiptext="&paneGeneral.title;">
|
||||||
|
<image class="category-icon"/>
|
||||||
|
<label class="category-name" flex="1" value="&paneGeneral.title;"/>
|
||||||
|
</richlistitem>
|
||||||
|
|
||||||
|
<richlistitem id="category-content" class="category" align="center"
|
||||||
|
value="paneContent" tooltiptext="&paneContent.title;">
|
||||||
|
<image class="category-icon"/>
|
||||||
|
<label class="category-name" flex="1" value="&paneContent.title;"/>
|
||||||
|
</richlistitem>
|
||||||
|
|
||||||
|
<richlistitem id="category-application" class="category" align="center"
|
||||||
|
value="paneApplications" tooltiptext="&paneApplications.title;">
|
||||||
|
<image class="category-icon"/>
|
||||||
|
<label class="category-name" flex="1" value="&paneApplications.title;"/>
|
||||||
|
</richlistitem>
|
||||||
|
|
||||||
|
<richlistitem id="category-privacy" class="category" align="center"
|
||||||
|
value="panePrivacy" tooltiptext="&panePrivacy.title;">
|
||||||
|
<image class="category-icon"/>
|
||||||
|
<label class="category-name" flex="1" value="&panePrivacy.title;"/>
|
||||||
|
</richlistitem>
|
||||||
|
|
||||||
|
<richlistitem id="category-security" class="category" align="center"
|
||||||
|
value="paneSecurity" tooltiptext="&paneSecurity.title;">
|
||||||
|
<image class="category-icon"/>
|
||||||
|
<label class="category-name" flex="1" value="&paneSecurity.title;"/>
|
||||||
|
</richlistitem>
|
||||||
|
|
||||||
|
#ifdef MOZ_SERVICES_SYNC
|
||||||
|
<richlistitem id="category-sync" class="category" align="center"
|
||||||
|
value="paneSync" tooltiptext="&paneSync.title;">
|
||||||
|
<image class="category-icon"/>
|
||||||
|
<label class="category-name" flex="1" value="&paneSync.title;"/>
|
||||||
|
</richlistitem>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
<richlistitem id="category-advanced" class="category" align="center"
|
||||||
|
value="paneAdvanced" tooltiptext="&paneAdvanced.title;">
|
||||||
|
<image class="category-icon"/>
|
||||||
|
<label class="category-name" flex="1" value="&paneAdvanced.title;"/>
|
||||||
|
</richlistitem>
|
||||||
|
</richlistbox>
|
||||||
|
|
||||||
|
<box class="main-content" flex="1">
|
||||||
|
<prefpane flex="1" id="mainPrefPane">
|
||||||
#include main.xul
|
#include main.xul
|
||||||
#include privacy.xul
|
#include privacy.xul
|
||||||
#include advanced.xul
|
#include advanced.xul
|
||||||
@ -99,7 +146,8 @@
|
|||||||
#ifdef MOZ_SERVICES_SYNC
|
#ifdef MOZ_SERVICES_SYNC
|
||||||
#include sync.xul
|
#include sync.xul
|
||||||
#endif
|
#endif
|
||||||
</prefpane>
|
</prefpane>
|
||||||
|
</box>
|
||||||
|
|
||||||
</hbox>
|
</hbox>
|
||||||
|
|
||||||
</page>
|
</page>
|
||||||
|
@ -65,11 +65,6 @@
|
|||||||
|
|
||||||
</preferences>
|
</preferences>
|
||||||
|
|
||||||
<hbox class="heading" data-category="panePrivacy" hidden="true">
|
|
||||||
<image class="preference-icon" type="privacy"/>
|
|
||||||
<html:h1>&panePrivacy.title;</html:h1>
|
|
||||||
</hbox>
|
|
||||||
|
|
||||||
<!-- Tracking -->
|
<!-- Tracking -->
|
||||||
<groupbox id="trackingGroup" data-category="panePrivacy" hidden="true" align="start">
|
<groupbox id="trackingGroup" data-category="panePrivacy" hidden="true" align="start">
|
||||||
<caption label="&tracking.label;"/>
|
<caption label="&tracking.label;"/>
|
||||||
|
@ -30,13 +30,10 @@
|
|||||||
|
|
||||||
</preferences>
|
</preferences>
|
||||||
|
|
||||||
<hbox class="heading" data-category="paneSecurity" hidden="true">
|
|
||||||
<image class="preference-icon" type="security"/>
|
|
||||||
<html:h1>&paneSecurity.title;</html:h1>
|
|
||||||
</hbox>
|
|
||||||
|
|
||||||
<!-- addons, forgery (phishing) UI -->
|
<!-- addons, forgery (phishing) UI -->
|
||||||
<groupbox id="addonsPhishingGroup" data-category="paneSecurity" hidden="true">
|
<groupbox id="addonsPhishingGroup" data-category="paneSecurity" hidden="true">
|
||||||
|
<caption label="&general.label;"/>
|
||||||
|
|
||||||
<hbox id="addonInstallBox">
|
<hbox id="addonInstallBox">
|
||||||
<checkbox id="warnAddonInstall" flex="1"
|
<checkbox id="warnAddonInstall" flex="1"
|
||||||
label="&warnAddonInstall.label;"
|
label="&warnAddonInstall.label;"
|
||||||
|
@ -28,11 +28,6 @@
|
|||||||
<script type="application/javascript"
|
<script type="application/javascript"
|
||||||
src="chrome://browser/content/sync/utils.js"/>
|
src="chrome://browser/content/sync/utils.js"/>
|
||||||
|
|
||||||
<hbox class="heading" data-category="paneSync" hidden="true">
|
|
||||||
<image class="preference-icon" type="sync"/>
|
|
||||||
<html:h1>&paneSync.title;</html:h1>
|
|
||||||
</hbox>
|
|
||||||
|
|
||||||
<deck id="weavePrefsDeck" data-category="paneSync" hidden="true">
|
<deck id="weavePrefsDeck" data-category="paneSync" hidden="true">
|
||||||
<vbox id="noAccount" align="center">
|
<vbox id="noAccount" align="center">
|
||||||
<spacer flex="1"/>
|
<spacer flex="1"/>
|
||||||
|
@ -149,7 +149,7 @@ AppValidator.prototype.validateLaunchPath = function (manifest) {
|
|||||||
try {
|
try {
|
||||||
indexURL = Services.io.newURI(path, null, Services.io.newURI(origin, null, null)).spec;
|
indexURL = Services.io.newURI(path, null, Services.io.newURI(origin, null, null)).spec;
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
this.error(strings.formatStringFromName("validator.invalidLaunchPath", [origin + path], 1));
|
this.error(strings.formatStringFromName("validator.accessFailedLaunchPath", [origin + path], 1));
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
return deferred.promise;
|
return deferred.promise;
|
||||||
}
|
}
|
||||||
@ -158,25 +158,25 @@ AppValidator.prototype.validateLaunchPath = function (manifest) {
|
|||||||
try {
|
try {
|
||||||
req.open("HEAD", indexURL, true);
|
req.open("HEAD", indexURL, true);
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
this.error(strings.formatStringFromName("validator.invalidLaunchPath", [indexURL], 1));
|
this.error(strings.formatStringFromName("validator.accessFailedLaunchPath", [indexURL], 1));
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
return deferred.promise;
|
return deferred.promise;
|
||||||
}
|
}
|
||||||
req.channel.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE | Ci.nsIRequest.INHIBIT_CACHING;
|
req.channel.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE | Ci.nsIRequest.INHIBIT_CACHING;
|
||||||
req.onload = () => {
|
req.onload = () => {
|
||||||
if (req.status >= 400)
|
if (req.status >= 400)
|
||||||
this.error(strings.formatStringFromName("validator.invalidLaunchPathBadHttpCode", [indexURL, req.status], 2));
|
this.error(strings.formatStringFromName("validator.accessFailedLaunchPathBadHttpCode", [indexURL, req.status], 2));
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
};
|
};
|
||||||
req.onerror = () => {
|
req.onerror = () => {
|
||||||
this.error(strings.formatStringFromName("validator.invalidLaunchPath", [indexURL], 1));
|
this.error(strings.formatStringFromName("validator.accessFailedLaunchPath", [indexURL], 1));
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
req.send(null);
|
req.send(null);
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
this.error(strings.formatStringFromName("validator.invalidLaunchPath", [indexURL], 1));
|
this.error(strings.formatStringFromName("validator.accessFailedLaunchPath", [indexURL], 1));
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,7 +99,7 @@
|
|||||||
let validator = createHosted("wrong-launch-path");
|
let validator = createHosted("wrong-launch-path");
|
||||||
validator.validate().then(() => {
|
validator.validate().then(() => {
|
||||||
is(validator.errors.length, 1, "app with non-existant launch path got an error");
|
is(validator.errors.length, 1, "app with non-existant launch path got an error");
|
||||||
is(validator.errors[0], strings.formatStringFromName("validator.invalidLaunchPathBadHttpCode", [origin + "wrong-path.html", 404], 2),
|
is(validator.errors[0], strings.formatStringFromName("validator.accessFailedLaunchPathBadHttpCode", [origin + "wrong-path.html", 404], 2),
|
||||||
"with the right error message");
|
"with the right error message");
|
||||||
is(validator.warnings.length, 0, "but no warning");
|
is(validator.warnings.length, 0, "but no warning");
|
||||||
next();
|
next();
|
||||||
@ -112,7 +112,7 @@
|
|||||||
let file = nsFile(validator.project.location);
|
let file = nsFile(validator.project.location);
|
||||||
file.append("wrong-path.html");
|
file.append("wrong-path.html");
|
||||||
let url = Services.io.newFileURI(file);
|
let url = Services.io.newFileURI(file);
|
||||||
is(validator.errors[0], strings.formatStringFromName("validator.invalidLaunchPath", [url.spec], 1),
|
is(validator.errors[0], strings.formatStringFromName("validator.accessFailedLaunchPath", [url.spec], 1),
|
||||||
"with the expected message");
|
"with the expected message");
|
||||||
is(validator.warnings.length, 0, "but no warning");
|
is(validator.warnings.length, 0, "but no warning");
|
||||||
|
|
||||||
|
@ -358,6 +358,9 @@ InspectorPanel.prototype = {
|
|||||||
|
|
||||||
this._initMarkup();
|
this._initMarkup();
|
||||||
this.once("markuploaded", () => {
|
this.once("markuploaded", () => {
|
||||||
|
if (this._destroyPromise) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.markup.expandNode(this.selection.nodeFront);
|
this.markup.expandNode(this.selection.nodeFront);
|
||||||
this.setupSearchBox();
|
this.setupSearchBox();
|
||||||
this.emit("new-root");
|
this.emit("new-root");
|
||||||
|
@ -14,6 +14,7 @@ const COLLAPSE_ATTRIBUTE_LENGTH = 120;
|
|||||||
const COLLAPSE_DATA_URL_REGEX = /^data.+base64/;
|
const COLLAPSE_DATA_URL_REGEX = /^data.+base64/;
|
||||||
const COLLAPSE_DATA_URL_LENGTH = 60;
|
const COLLAPSE_DATA_URL_LENGTH = 60;
|
||||||
const CONTAINER_FLASHING_DURATION = 500;
|
const CONTAINER_FLASHING_DURATION = 500;
|
||||||
|
const IMAGE_PREVIEW_MAX_DIM = 400;
|
||||||
|
|
||||||
const {UndoStack} = require("devtools/shared/undo");
|
const {UndoStack} = require("devtools/shared/undo");
|
||||||
const {editableField, InplaceEditor} = require("devtools/shared/inplace-editor");
|
const {editableField, InplaceEditor} = require("devtools/shared/inplace-editor");
|
||||||
@ -99,6 +100,10 @@ function MarkupView(aInspector, aFrame, aControllerWindow) {
|
|||||||
gDevTools.on("pref-changed", this._handlePrefChange);
|
gDevTools.on("pref-changed", this._handlePrefChange);
|
||||||
|
|
||||||
this._initPreview();
|
this._initPreview();
|
||||||
|
|
||||||
|
this.tooltip = new Tooltip(this._inspector.panelDoc);
|
||||||
|
this.tooltip.startTogglingOnHover(this._elt,
|
||||||
|
this._buildTooltipContent.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.MarkupView = MarkupView;
|
exports.MarkupView = MarkupView;
|
||||||
@ -148,6 +153,25 @@ MarkupView.prototype = {
|
|||||||
updateChildren(documentElement);
|
updateChildren(documentElement);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_buildTooltipContent: function(target) {
|
||||||
|
// From the target passed here, let's find the parent MarkupContainer
|
||||||
|
// and ask it if the tooltip should be shown
|
||||||
|
let parent = target, container;
|
||||||
|
while (parent !== this.doc.body) {
|
||||||
|
if (parent.container) {
|
||||||
|
container = parent.container;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
parent = parent.parentNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (container) {
|
||||||
|
// With the newly found container, delegate the tooltip content creation
|
||||||
|
// and decision to show or not the tooltip
|
||||||
|
return container._buildTooltipContent(target, this.tooltip);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Highlight the inspector selected node.
|
* Highlight the inspector selected node.
|
||||||
*/
|
*/
|
||||||
@ -954,6 +978,9 @@ MarkupView.prototype = {
|
|||||||
container.destroy();
|
container.destroy();
|
||||||
}
|
}
|
||||||
delete this._containers;
|
delete this._containers;
|
||||||
|
|
||||||
|
this.tooltip.destroy();
|
||||||
|
delete this.tooltip;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1099,8 +1126,8 @@ function MarkupContainer(aMarkupView, aNode, aInspector) {
|
|||||||
this._onMouseDown = this._onMouseDown.bind(this);
|
this._onMouseDown = this._onMouseDown.bind(this);
|
||||||
this.elt.addEventListener("mousedown", this._onMouseDown, false);
|
this.elt.addEventListener("mousedown", this._onMouseDown, false);
|
||||||
|
|
||||||
this.tooltip = null;
|
// Prepare the image preview tooltip data if any
|
||||||
this._attachTooltipIfNeeded();
|
this._prepareImagePreview();
|
||||||
}
|
}
|
||||||
|
|
||||||
MarkupContainer.prototype = {
|
MarkupContainer.prototype = {
|
||||||
@ -1108,36 +1135,43 @@ MarkupContainer.prototype = {
|
|||||||
return "[MarkupContainer for " + this.node + "]";
|
return "[MarkupContainer for " + this.node + "]";
|
||||||
},
|
},
|
||||||
|
|
||||||
_attachTooltipIfNeeded: function() {
|
_prepareImagePreview: function() {
|
||||||
if (this.node.tagName) {
|
if (this.node.tagName) {
|
||||||
let tagName = this.node.tagName.toLowerCase();
|
let tagName = this.node.tagName.toLowerCase();
|
||||||
let isImage = tagName === "img" &&
|
let srcAttr = this.editor.getAttributeElement("src");
|
||||||
this.editor.getAttributeElement("src");
|
let isImage = tagName === "img" && srcAttr;
|
||||||
let isCanvas = tagName && tagName === "canvas";
|
let isCanvas = tagName === "canvas";
|
||||||
|
|
||||||
// Get the image data for later so that when the user actually hovers over
|
// Get the image data for later so that when the user actually hovers over
|
||||||
// the element, the tooltip does contain the image
|
// the element, the tooltip does contain the image
|
||||||
if (isImage || isCanvas) {
|
if (isImage || isCanvas) {
|
||||||
this.tooltip = new Tooltip(this._inspector.panelDoc);
|
let def = promise.defer();
|
||||||
|
|
||||||
this.node.getImageData().then(data => {
|
this.tooltipData = {
|
||||||
|
target: isImage ? srcAttr : this.editor.tag,
|
||||||
|
data: def.promise
|
||||||
|
};
|
||||||
|
|
||||||
|
this.node.getImageData(IMAGE_PREVIEW_MAX_DIM).then(data => {
|
||||||
if (data) {
|
if (data) {
|
||||||
data.string().then(str => {
|
data.data.string().then(str => {
|
||||||
this.tooltip.setImageContent(str);
|
// Resolving the data promise and, to always keep tooltipData.data
|
||||||
|
// as a promise, create a new one that resolves immediately
|
||||||
|
def.resolve(str, data.size);
|
||||||
|
this.tooltipData.data = promise.resolve(str, data.size);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
// If it's an image, show the tooltip on the src attribute
|
_buildTooltipContent: function(target, tooltip) {
|
||||||
if (isImage) {
|
if (this.tooltipData && target === this.tooltipData.target) {
|
||||||
this.tooltip.startTogglingOnHover(this.editor.getAttributeElement("src"));
|
this.tooltipData.data.then((data, size) => {
|
||||||
}
|
tooltip.setImageContent(data, size);
|
||||||
|
});
|
||||||
// If it's a canvas, show it on the tag
|
return true;
|
||||||
if (isCanvas) {
|
|
||||||
this.tooltip.startTogglingOnHover(this.editor.tag);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -1375,12 +1409,6 @@ MarkupContainer.prototype = {
|
|||||||
|
|
||||||
// Destroy my editor
|
// Destroy my editor
|
||||||
this.editor.destroy();
|
this.editor.destroy();
|
||||||
|
|
||||||
// Destroy the tooltip if any
|
|
||||||
if (this.tooltip) {
|
|
||||||
this.tooltip.destroy();
|
|
||||||
this.tooltip = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -88,14 +88,14 @@ function testImageTooltip(index) {
|
|||||||
target = container.editor.getAttributeElement("src");
|
target = container.editor.getAttributeElement("src");
|
||||||
}
|
}
|
||||||
|
|
||||||
assertTooltipShownOn(container.tooltip, target, () => {
|
assertTooltipShownOn(target, () => {
|
||||||
let images = container.tooltip.panel.getElementsByTagName("image");
|
let images = markup.tooltip.panel.getElementsByTagName("image");
|
||||||
is(images.length, 1, "Tooltip for [" + TEST_NODES[index] + "] contains an image");
|
is(images.length, 1, "Tooltip for [" + TEST_NODES[index] + "] contains an image");
|
||||||
if (isImg) {
|
if (isImg) {
|
||||||
compareImageData(node, images[0].src);
|
compareImageData(node, images[0].src);
|
||||||
}
|
}
|
||||||
|
|
||||||
container.tooltip.hide();
|
markup.tooltip.hide();
|
||||||
|
|
||||||
testImageTooltip(index + 1);
|
testImageTooltip(index + 1);
|
||||||
});
|
});
|
||||||
@ -115,17 +115,17 @@ function compareImageData(img, imgData) {
|
|||||||
is(data, imgData, "Tooltip image has the right content");
|
is(data, imgData, "Tooltip image has the right content");
|
||||||
}
|
}
|
||||||
|
|
||||||
function assertTooltipShownOn(tooltip, element, cb) {
|
function assertTooltipShownOn(element, cb) {
|
||||||
// If there is indeed a show-on-hover on element, the xul panel will be shown
|
// If there is indeed a show-on-hover on element, the xul panel will be shown
|
||||||
tooltip.panel.addEventListener("popupshown", function shown() {
|
markup.tooltip.panel.addEventListener("popupshown", function shown() {
|
||||||
tooltip.panel.removeEventListener("popupshown", shown, true);
|
markup.tooltip.panel.removeEventListener("popupshown", shown, true);
|
||||||
|
|
||||||
// Poll until the image gets loaded in the tooltip. This is required because
|
// Poll until the image gets loaded in the tooltip. This is required because
|
||||||
// markup containers only load images in their associated tooltips when
|
// markup containers only load images in their associated tooltips when
|
||||||
// the image data comes back from the server. However, this test is executed
|
// the image data comes back from the server. However, this test is executed
|
||||||
// synchronously as soon as "inspector-updated" is fired, which is before
|
// synchronously as soon as "inspector-updated" is fired, which is before
|
||||||
// the data for images is known.
|
// the data for images is known.
|
||||||
let hasImage = () => tooltip.panel.getElementsByTagName("image").length;
|
let hasImage = () => markup.tooltip.panel.getElementsByTagName("image").length;
|
||||||
let poll = setInterval(() => {
|
let poll = setInterval(() => {
|
||||||
if (hasImage()) {
|
if (hasImage()) {
|
||||||
clearInterval(poll);
|
clearInterval(poll);
|
||||||
@ -133,5 +133,5 @@ function assertTooltipShownOn(tooltip, element, cb) {
|
|||||||
}
|
}
|
||||||
}, 200);
|
}, 200);
|
||||||
}, true);
|
}, true);
|
||||||
tooltip._showOnHover(element);
|
markup.tooltip._showOnHover(element);
|
||||||
}
|
}
|
||||||
|
@ -159,7 +159,7 @@ var Scratchpad = {
|
|||||||
{
|
{
|
||||||
this._dirty = aValue;
|
this._dirty = aValue;
|
||||||
if (!aValue && this.editor)
|
if (!aValue && this.editor)
|
||||||
this.editor.markClean();
|
this.editor.setClean();
|
||||||
this._updateTitle();
|
this._updateTitle();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ Cu.import("resource:///modules/devtools/ViewHelpers.jsm");
|
|||||||
const require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require;
|
const require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require;
|
||||||
const promise = require("sdk/core/promise");
|
const promise = require("sdk/core/promise");
|
||||||
const EventEmitter = require("devtools/shared/event-emitter");
|
const EventEmitter = require("devtools/shared/event-emitter");
|
||||||
|
const {Tooltip} = require("devtools/shared/widgets/Tooltip");
|
||||||
const Editor = require("devtools/sourceeditor/editor");
|
const Editor = require("devtools/sourceeditor/editor");
|
||||||
|
|
||||||
// The panel's window global is an EventEmitter firing the following events:
|
// The panel's window global is an EventEmitter firing the following events:
|
||||||
@ -31,12 +32,14 @@ const EVENTS = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const STRINGS_URI = "chrome://browser/locale/devtools/shadereditor.properties"
|
const STRINGS_URI = "chrome://browser/locale/devtools/shadereditor.properties"
|
||||||
const HIGHLIGHT_COLOR = [1, 0, 0, 1];
|
const HIGHLIGHT_COLOR = [1, 0, 0, 1]; // rgba
|
||||||
const BLACKBOX_COLOR = [0, 0, 0, 0];
|
const TYPING_MAX_DELAY = 500; // ms
|
||||||
const TYPING_MAX_DELAY = 500;
|
|
||||||
const SHADERS_AUTOGROW_ITEMS = 4;
|
const SHADERS_AUTOGROW_ITEMS = 4;
|
||||||
|
const GUTTER_ERROR_PANEL_OFFSET_X = 7; // px
|
||||||
|
const GUTTER_ERROR_PANEL_DELAY = 100; // ms
|
||||||
const DEFAULT_EDITOR_CONFIG = {
|
const DEFAULT_EDITOR_CONFIG = {
|
||||||
mode: Editor.modes.text,
|
mode: Editor.modes.text,
|
||||||
|
gutters: ["errors"],
|
||||||
lineNumbers: true,
|
lineNumbers: true,
|
||||||
showAnnotationRuler: true
|
showAnnotationRuler: true
|
||||||
};
|
};
|
||||||
@ -174,25 +177,25 @@ let ShadersListView = Heritage.extend(WidgetMethods, {
|
|||||||
showItemCheckboxes: true
|
showItemCheckboxes: true
|
||||||
});
|
});
|
||||||
|
|
||||||
this._onShaderSelect = this._onShaderSelect.bind(this);
|
this._onProgramSelect = this._onProgramSelect.bind(this);
|
||||||
this._onShaderCheck = this._onShaderCheck.bind(this);
|
this._onProgramCheck = this._onProgramCheck.bind(this);
|
||||||
this._onShaderMouseEnter = this._onShaderMouseEnter.bind(this);
|
this._onProgramMouseEnter = this._onProgramMouseEnter.bind(this);
|
||||||
this._onShaderMouseLeave = this._onShaderMouseLeave.bind(this);
|
this._onProgramMouseLeave = this._onProgramMouseLeave.bind(this);
|
||||||
|
|
||||||
this.widget.addEventListener("select", this._onShaderSelect, false);
|
this.widget.addEventListener("select", this._onProgramSelect, false);
|
||||||
this.widget.addEventListener("check", this._onShaderCheck, false);
|
this.widget.addEventListener("check", this._onProgramCheck, false);
|
||||||
this.widget.addEventListener("mouseenter", this._onShaderMouseEnter, true);
|
this.widget.addEventListener("mouseenter", this._onProgramMouseEnter, true);
|
||||||
this.widget.addEventListener("mouseleave", this._onShaderMouseLeave, true);
|
this.widget.addEventListener("mouseleave", this._onProgramMouseLeave, true);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destruction function, called when the tool is closed.
|
* Destruction function, called when the tool is closed.
|
||||||
*/
|
*/
|
||||||
destroy: function() {
|
destroy: function() {
|
||||||
this.widget.removeEventListener("select", this._onShaderSelect, false);
|
this.widget.removeEventListener("select", this._onProgramSelect, false);
|
||||||
this.widget.removeEventListener("check", this._onShaderCheck, false);
|
this.widget.removeEventListener("check", this._onProgramCheck, false);
|
||||||
this.widget.removeEventListener("mouseenter", this._onShaderMouseEnter, true);
|
this.widget.removeEventListener("mouseenter", this._onProgramMouseEnter, true);
|
||||||
this.widget.removeEventListener("mouseleave", this._onShaderMouseLeave, true);
|
this.widget.removeEventListener("mouseleave", this._onProgramMouseLeave, true);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -248,9 +251,9 @@ let ShadersListView = Heritage.extend(WidgetMethods, {
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The select listener for the sources container.
|
* The select listener for the programs container.
|
||||||
*/
|
*/
|
||||||
_onShaderSelect: function({ detail: sourceItem }) {
|
_onProgramSelect: function({ detail: sourceItem }) {
|
||||||
if (!sourceItem) {
|
if (!sourceItem) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -280,19 +283,19 @@ let ShadersListView = Heritage.extend(WidgetMethods, {
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The check listener for the sources container.
|
* The check listener for the programs container.
|
||||||
*/
|
*/
|
||||||
_onShaderCheck: function({ detail: { checked }, target }) {
|
_onProgramCheck: function({ detail: { checked }, target }) {
|
||||||
let sourceItem = this.getItemForElement(target);
|
let sourceItem = this.getItemForElement(target);
|
||||||
let attachment = sourceItem.attachment;
|
let attachment = sourceItem.attachment;
|
||||||
attachment.isBlackBoxed = !checked;
|
attachment.isBlackBoxed = !checked;
|
||||||
attachment.programActor[checked ? "unhighlight" : "highlight"](BLACKBOX_COLOR);
|
attachment.programActor[checked ? "unblackbox" : "blackbox"]();
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The mouseenter listener for the sources container.
|
* The mouseenter listener for the programs container.
|
||||||
*/
|
*/
|
||||||
_onShaderMouseEnter: function(e) {
|
_onProgramMouseEnter: function(e) {
|
||||||
let sourceItem = this.getItemForElement(e.target, { noSiblings: true });
|
let sourceItem = this.getItemForElement(e.target, { noSiblings: true });
|
||||||
if (sourceItem && !sourceItem.attachment.isBlackBoxed) {
|
if (sourceItem && !sourceItem.attachment.isBlackBoxed) {
|
||||||
sourceItem.attachment.programActor.highlight(HIGHLIGHT_COLOR);
|
sourceItem.attachment.programActor.highlight(HIGHLIGHT_COLOR);
|
||||||
@ -305,9 +308,9 @@ let ShadersListView = Heritage.extend(WidgetMethods, {
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The mouseleave listener for the sources container.
|
* The mouseleave listener for the programs container.
|
||||||
*/
|
*/
|
||||||
_onShaderMouseLeave: function(e) {
|
_onProgramMouseLeave: function(e) {
|
||||||
let sourceItem = this.getItemForElement(e.target, { noSiblings: true });
|
let sourceItem = this.getItemForElement(e.target, { noSiblings: true });
|
||||||
if (sourceItem && !sourceItem.attachment.isBlackBoxed) {
|
if (sourceItem && !sourceItem.attachment.isBlackBoxed) {
|
||||||
sourceItem.attachment.programActor.unhighlight();
|
sourceItem.attachment.programActor.unhighlight();
|
||||||
@ -427,6 +430,9 @@ let ShadersEditorsView = {
|
|||||||
*/
|
*/
|
||||||
_onChanged: function(type) {
|
_onChanged: function(type) {
|
||||||
setNamedTimeout("gl-typed", TYPING_MAX_DELAY, () => this._doCompile(type));
|
setNamedTimeout("gl-typed", TYPING_MAX_DELAY, () => this._doCompile(type));
|
||||||
|
|
||||||
|
// Remove all the gutter markers and line classes from the editor.
|
||||||
|
this._cleanEditor(type);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -443,13 +449,117 @@ let ShadersEditorsView = {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
yield shaderActor.compile(editor.getText());
|
yield shaderActor.compile(editor.getText());
|
||||||
window.emit(EVENTS.SHADER_COMPILED, null);
|
this._onSuccessfulCompilation();
|
||||||
// TODO: remove error gutter markers, after bug 919709 lands.
|
} catch (e) {
|
||||||
} catch (error) {
|
this._onFailedCompilation(type, editor, e);
|
||||||
window.emit(EVENTS.SHADER_COMPILED, error);
|
|
||||||
// TODO: add error gutter markers, after bug 919709 lands.
|
|
||||||
}
|
}
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called uppon a successful shader compilation.
|
||||||
|
*/
|
||||||
|
_onSuccessfulCompilation: function() {
|
||||||
|
// Signal that the shader was compiled successfully.
|
||||||
|
window.emit(EVENTS.SHADER_COMPILED, null);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called uppon an unsuccessful shader compilation.
|
||||||
|
*/
|
||||||
|
_onFailedCompilation: function(type, editor, errors) {
|
||||||
|
let lineCount = editor.lineCount();
|
||||||
|
let currentLine = editor.getCursor().line;
|
||||||
|
let listeners = { mouseenter: this._onMarkerMouseEnter };
|
||||||
|
|
||||||
|
function matchLinesAndMessages(string) {
|
||||||
|
return {
|
||||||
|
// First number that is not equal to 0.
|
||||||
|
lineMatch: string.match(/\d{2,}|[1-9]/),
|
||||||
|
// The string after all the numbers, semicolons and spaces.
|
||||||
|
textMatch: string.match(/[^\s\d:][^\r\n|]*/)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function discardInvalidMatches(e) {
|
||||||
|
// Discard empty line and text matches.
|
||||||
|
return e.lineMatch && e.textMatch;
|
||||||
|
}
|
||||||
|
function sanitizeValidMatches(e) {
|
||||||
|
return {
|
||||||
|
// Drivers might yield retarded line numbers under some obscure
|
||||||
|
// circumstances. Don't throw the errors away in those cases,
|
||||||
|
// just display them on the currently edited line.
|
||||||
|
line: e.lineMatch[0] > lineCount ? currentLine : e.lineMatch[0] - 1,
|
||||||
|
// Trim whitespace from the beginning and the end of the message,
|
||||||
|
// and replace all other occurences of double spaces to a single space.
|
||||||
|
text: e.textMatch[0].trim().replace(/\s{2,}/g, " ")
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function sortByLine(first, second) {
|
||||||
|
// Sort all the errors ascending by their corresponding line number.
|
||||||
|
return first.line > second.line ? 1 : -1;
|
||||||
|
}
|
||||||
|
function groupSameLineMessages(accumulator, current) {
|
||||||
|
// Group errors corresponding to the same line number to a single object.
|
||||||
|
let previous = accumulator[accumulator.length - 1];
|
||||||
|
if (!previous || previous.line != current.line) {
|
||||||
|
return [...accumulator, {
|
||||||
|
line: current.line,
|
||||||
|
messages: [current.text]
|
||||||
|
}];
|
||||||
|
} else {
|
||||||
|
previous.messages.push(current.text);
|
||||||
|
return accumulator;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function displayErrors({ line, messages }) {
|
||||||
|
// Add gutter markers and line classes for every error in the source.
|
||||||
|
editor.addMarker(line, "errors", "error");
|
||||||
|
editor.setMarkerListeners(line, "errors", "error", listeners, messages);
|
||||||
|
editor.addLineClass(line, "error-line");
|
||||||
|
}
|
||||||
|
|
||||||
|
(this._errors[type] = errors.link
|
||||||
|
.split("ERROR")
|
||||||
|
.map(matchLinesAndMessages)
|
||||||
|
.filter(discardInvalidMatches)
|
||||||
|
.map(sanitizeValidMatches)
|
||||||
|
.sort(sortByLine)
|
||||||
|
.reduce(groupSameLineMessages, []))
|
||||||
|
.forEach(displayErrors);
|
||||||
|
|
||||||
|
// Signal that the shader wasn't compiled successfully.
|
||||||
|
window.emit(EVENTS.SHADER_COMPILED, errors);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event listener for the 'mouseenter' event on a marker in the editor gutter.
|
||||||
|
*/
|
||||||
|
_onMarkerMouseEnter: function(line, node, messages) {
|
||||||
|
if (node._markerErrorsTooltip) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let tooltip = node._markerErrorsTooltip = new Tooltip(document);
|
||||||
|
tooltip.defaultOffsetX = GUTTER_ERROR_PANEL_OFFSET_X;
|
||||||
|
tooltip.setTextContent.apply(tooltip, messages);
|
||||||
|
tooltip.startTogglingOnHover(node, () => true, GUTTER_ERROR_PANEL_DELAY);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes all the gutter markers and line classes from the editor.
|
||||||
|
*/
|
||||||
|
_cleanEditor: function(type) {
|
||||||
|
this._getEditor(type).then(editor => {
|
||||||
|
editor.removeAllMarkers("errors");
|
||||||
|
this._errors[type].forEach(e => editor.removeLineClass(e.line));
|
||||||
|
this._errors[type].length = 0;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
_errors: {
|
||||||
|
vs: [],
|
||||||
|
fs: []
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
[DEFAULT]
|
[DEFAULT]
|
||||||
support-files =
|
support-files =
|
||||||
doc_multiple-contexts.html
|
doc_multiple-contexts.html
|
||||||
|
doc_overlapping-geometry.html
|
||||||
doc_shader-order.html
|
doc_shader-order.html
|
||||||
doc_simple-canvas.html
|
doc_simple-canvas.html
|
||||||
head.js
|
head.js
|
||||||
@ -8,6 +9,8 @@ support-files =
|
|||||||
[browser_se_aaa_run_first_leaktest.js]
|
[browser_se_aaa_run_first_leaktest.js]
|
||||||
[browser_se_bfcache.js]
|
[browser_se_bfcache.js]
|
||||||
[browser_se_editors-contents.js]
|
[browser_se_editors-contents.js]
|
||||||
|
[browser_se_editors-error-gutter.js]
|
||||||
|
[browser_se_editors-error-tooltip.js]
|
||||||
[browser_se_editors-lazy-init.js]
|
[browser_se_editors-lazy-init.js]
|
||||||
[browser_se_first-run.js]
|
[browser_se_first-run.js]
|
||||||
[browser_se_navigation.js]
|
[browser_se_navigation.js]
|
||||||
@ -34,3 +37,4 @@ support-files =
|
|||||||
[browser_webgl-actor-test-14.js]
|
[browser_webgl-actor-test-14.js]
|
||||||
[browser_webgl-actor-test-15.js]
|
[browser_webgl-actor-test-15.js]
|
||||||
[browser_webgl-actor-test-16.js]
|
[browser_webgl-actor-test-16.js]
|
||||||
|
[browser_webgl-actor-test-17.js]
|
||||||
|
@ -0,0 +1,156 @@
|
|||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests if error indicators are shown in the editor's gutter and text area
|
||||||
|
* when there's a shader compilation error.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function ifWebGLSupported() {
|
||||||
|
let [target, debuggee, panel] = yield initShaderEditor(SIMPLE_CANVAS_URL);
|
||||||
|
let { gFront, EVENTS, ShadersEditorsView } = panel.panelWin;
|
||||||
|
|
||||||
|
reload(target);
|
||||||
|
yield once(gFront, "program-linked");
|
||||||
|
|
||||||
|
let vsEditor = yield ShadersEditorsView._getEditor("vs");
|
||||||
|
let fsEditor = yield ShadersEditorsView._getEditor("fs");
|
||||||
|
|
||||||
|
vsEditor.replaceText("vec3", { line: 7, ch: 22 }, { line: 7, ch: 26 });
|
||||||
|
let vertError = yield once(panel.panelWin, EVENTS.SHADER_COMPILED);
|
||||||
|
checkHasVertFirstError(true, vertError);
|
||||||
|
checkHasVertSecondError(false, vertError);
|
||||||
|
info("Error marks added in the vertex shader editor.");
|
||||||
|
|
||||||
|
vsEditor.insertText(" ", { line: 1, ch: 0 });
|
||||||
|
is(vsEditor.getText(1), " precision lowp float;", "Typed space.");
|
||||||
|
checkHasVertFirstError(false, vertError);
|
||||||
|
checkHasVertSecondError(false, vertError);
|
||||||
|
info("Error marks removed while typing in the vertex shader editor.");
|
||||||
|
|
||||||
|
let vertError = yield once(panel.panelWin, EVENTS.SHADER_COMPILED);
|
||||||
|
checkHasVertFirstError(true, vertError);
|
||||||
|
checkHasVertSecondError(false, vertError);
|
||||||
|
info("Error marks were re-added after recompiling the vertex shader.");
|
||||||
|
|
||||||
|
fsEditor.replaceText("vec4", { line: 2, ch: 14 }, { line: 2, ch: 18 });
|
||||||
|
let fragError = yield once(panel.panelWin, EVENTS.SHADER_COMPILED);
|
||||||
|
checkHasVertFirstError(true, vertError);
|
||||||
|
checkHasVertSecondError(false, vertError);
|
||||||
|
checkHasFragError(true, fragError);
|
||||||
|
info("Error marks added in the fragment shader editor.");
|
||||||
|
|
||||||
|
fsEditor.insertText(" ", { line: 1, ch: 0 });
|
||||||
|
is(fsEditor.getText(1), " precision lowp float;", "Typed space.");
|
||||||
|
checkHasVertFirstError(true, vertError);
|
||||||
|
checkHasVertSecondError(false, vertError);
|
||||||
|
checkHasFragError(false, fragError);
|
||||||
|
info("Error marks removed while typing in the fragment shader editor.");
|
||||||
|
|
||||||
|
let fragError = yield once(panel.panelWin, EVENTS.SHADER_COMPILED);
|
||||||
|
checkHasVertFirstError(true, vertError);
|
||||||
|
checkHasVertSecondError(false, vertError);
|
||||||
|
checkHasFragError(true, fragError);
|
||||||
|
info("Error marks were re-added after recompiling the fragment shader.");
|
||||||
|
|
||||||
|
vsEditor.replaceText("2", { line: 3, ch: 19 }, { line: 3, ch: 20 });
|
||||||
|
checkHasVertFirstError(false, vertError);
|
||||||
|
checkHasVertSecondError(false, vertError);
|
||||||
|
checkHasFragError(true, fragError);
|
||||||
|
info("Error marks removed while typing in the vertex shader editor again.");
|
||||||
|
|
||||||
|
let vertError = yield once(panel.panelWin, EVENTS.SHADER_COMPILED);
|
||||||
|
checkHasVertFirstError(true, vertError);
|
||||||
|
checkHasVertSecondError(true, vertError);
|
||||||
|
checkHasFragError(true, fragError);
|
||||||
|
info("Error marks were re-added after recompiling the fragment shader again.");
|
||||||
|
|
||||||
|
yield teardown(panel);
|
||||||
|
finish();
|
||||||
|
|
||||||
|
function checkHasVertFirstError(bool, error) {
|
||||||
|
ok(error, "Vertex shader compiled with errors.");
|
||||||
|
isnot(error.link, "", "The linkage status should not be empty.");
|
||||||
|
|
||||||
|
let line = 7;
|
||||||
|
info("Checking first vertex shader error on line " + line + "...");
|
||||||
|
|
||||||
|
is(vsEditor.hasMarker(line, "errors", "error"), bool,
|
||||||
|
"Error is " + (bool ? "" : "not ") + "shown in the editor's gutter.");
|
||||||
|
is(vsEditor.hasLineClass(line, "error-line"), bool,
|
||||||
|
"Error style is " + (bool ? "" : "not ") + "applied to the faulty line.");
|
||||||
|
|
||||||
|
let parsed = ShadersEditorsView._errors.vs;
|
||||||
|
is(parsed.length >= 1, bool,
|
||||||
|
"There's " + (bool ? ">= 1" : "< 1") + " parsed vertex shader error(s).");
|
||||||
|
|
||||||
|
if (bool) {
|
||||||
|
is(parsed[0].line, line,
|
||||||
|
"The correct line was parsed.");
|
||||||
|
is(parsed[0].messages.length, 2,
|
||||||
|
"There are 2 parsed messages.");
|
||||||
|
ok(parsed[0].messages[0].contains("'constructor' : too many arguments"),
|
||||||
|
"The correct first message was parsed.");
|
||||||
|
ok(parsed[0].messages[1].contains("'assign' : cannot convert from"),
|
||||||
|
"The correct second message was parsed.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkHasVertSecondError(bool, error) {
|
||||||
|
ok(error, "Vertex shader compiled with errors.");
|
||||||
|
isnot(error.link, "", "The linkage status should not be empty.");
|
||||||
|
|
||||||
|
let line = 8;
|
||||||
|
info("Checking second vertex shader error on line " + line + "...");
|
||||||
|
|
||||||
|
is(vsEditor.hasMarker(line, "errors", "error"), bool,
|
||||||
|
"Error is " + (bool ? "" : "not ") + "shown in the editor's gutter.");
|
||||||
|
is(vsEditor.hasLineClass(line, "error-line"), bool,
|
||||||
|
"Error style is " + (bool ? "" : "not ") + "applied to the faulty line.");
|
||||||
|
|
||||||
|
let parsed = ShadersEditorsView._errors.vs;
|
||||||
|
is(parsed.length >= 2, bool,
|
||||||
|
"There's " + (bool ? ">= 2" : "< 2") + " parsed vertex shader error(s).");
|
||||||
|
|
||||||
|
if (bool) {
|
||||||
|
is(parsed[1].line, line,
|
||||||
|
"The correct line was parsed.");
|
||||||
|
is(parsed[1].messages.length, 1,
|
||||||
|
"There is 1 parsed message.");
|
||||||
|
ok(parsed[1].messages[0].contains("'assign' : cannot convert from"),
|
||||||
|
"The correct message was parsed.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkHasFragError(bool, error) {
|
||||||
|
ok(error, "Fragment shader compiled with errors.");
|
||||||
|
isnot(error.link, "", "The linkage status should not be empty.");
|
||||||
|
|
||||||
|
let line = 5;
|
||||||
|
info("Checking first vertex shader error on line " + line + "...");
|
||||||
|
|
||||||
|
is(fsEditor.hasMarker(line, "errors", "error"), bool,
|
||||||
|
"Error is " + (bool ? "" : "not ") + "shown in the editor's gutter.");
|
||||||
|
is(fsEditor.hasLineClass(line, "error-line"), bool,
|
||||||
|
"Error style is " + (bool ? "" : "not ") + "applied to the faulty line.");
|
||||||
|
|
||||||
|
let parsed = ShadersEditorsView._errors.fs;
|
||||||
|
is(parsed.length >= 1, bool,
|
||||||
|
"There's " + (bool ? ">= 2" : "< 1") + " parsed fragment shader error(s).");
|
||||||
|
|
||||||
|
if (bool) {
|
||||||
|
is(parsed[0].line, line,
|
||||||
|
"The correct line was parsed.");
|
||||||
|
is(parsed[0].messages.length, 1,
|
||||||
|
"There is 1 parsed message.");
|
||||||
|
ok(parsed[0].messages[0].contains("'constructor' : too many arguments"),
|
||||||
|
"The correct message was parsed.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function once(aTarget, aEvent) {
|
||||||
|
let deferred = promise.defer();
|
||||||
|
aTarget.once(aEvent, (aName, aData) => deferred.resolve(aData));
|
||||||
|
return deferred.promise;
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests if error tooltips can be opened from the editor's gutter when there's
|
||||||
|
* a shader compilation error.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function ifWebGLSupported() {
|
||||||
|
let [target, debuggee, panel] = yield initShaderEditor(SIMPLE_CANVAS_URL);
|
||||||
|
let { gFront, EVENTS, ShadersEditorsView } = panel.panelWin;
|
||||||
|
|
||||||
|
reload(target);
|
||||||
|
yield once(gFront, "program-linked");
|
||||||
|
|
||||||
|
let vsEditor = yield ShadersEditorsView._getEditor("vs");
|
||||||
|
let fsEditor = yield ShadersEditorsView._getEditor("fs");
|
||||||
|
|
||||||
|
vsEditor.replaceText("vec3", { line: 7, ch: 22 }, { line: 7, ch: 26 });
|
||||||
|
yield once(panel.panelWin, EVENTS.SHADER_COMPILED);
|
||||||
|
|
||||||
|
// Synthesizing 'mouseenter' events doesn't work, hack around this by
|
||||||
|
// manually calling the event listener with the expected arguments.
|
||||||
|
let editorDocument = vsEditor.container.contentDocument;
|
||||||
|
let marker = editorDocument.querySelector(".error");
|
||||||
|
let parsed = ShadersEditorsView._errors.vs[0].messages;
|
||||||
|
ShadersEditorsView._onMarkerMouseEnter(7, marker, parsed);
|
||||||
|
|
||||||
|
let tooltip = marker._markerErrorsTooltip;
|
||||||
|
ok(tooltip, "A tooltip was created successfully.");
|
||||||
|
|
||||||
|
let content = tooltip.content;
|
||||||
|
ok(tooltip.content,
|
||||||
|
"Some tooltip's content was set.");
|
||||||
|
is(tooltip.content.className, "devtools-tooltip-simple-text-container",
|
||||||
|
"The tooltip's content container was created correctly.");
|
||||||
|
|
||||||
|
let messages = content.childNodes;
|
||||||
|
is(messages.length, 2,
|
||||||
|
"There are two messages displayed in the tooltip.");
|
||||||
|
is(messages[0].className, "devtools-tooltip-simple-text",
|
||||||
|
"The first message was created correctly.");
|
||||||
|
is(messages[1].className, "devtools-tooltip-simple-text",
|
||||||
|
"The second message was created correctly.");
|
||||||
|
|
||||||
|
ok(messages[0].textContent.contains("'constructor' : too many arguments"),
|
||||||
|
"The first message contains the correct text.");
|
||||||
|
ok(messages[1].textContent.contains("'assign' : cannot convert"),
|
||||||
|
"The second message contains the correct text.");
|
||||||
|
|
||||||
|
yield teardown(panel);
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
function once(aTarget, aEvent) {
|
||||||
|
let deferred = promise.defer();
|
||||||
|
aTarget.once(aEvent, (aName, aData) => deferred.resolve(aData));
|
||||||
|
return deferred.promise;
|
||||||
|
}
|
@ -55,9 +55,9 @@ function ifWebGLSupported() {
|
|||||||
is(getBlackBoxCheckbox(panel, 1).checked, true,
|
is(getBlackBoxCheckbox(panel, 1).checked, true,
|
||||||
"The second blackbox checkbox should still be checked.");
|
"The second blackbox checkbox should still be checked.");
|
||||||
|
|
||||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 0 }, true, "#canvas1");
|
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 255 }, true, "#canvas1");
|
||||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 0, b: 0, a: 0 }, true, "#canvas1");
|
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 0, b: 0, a: 255 }, true, "#canvas1");
|
||||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||||
ok(true, "The first program was correctly blackboxed.");
|
ok(true, "The first program was correctly blackboxed.");
|
||||||
|
|
||||||
@ -72,35 +72,35 @@ function ifWebGLSupported() {
|
|||||||
is(getBlackBoxCheckbox(panel, 1).checked, false,
|
is(getBlackBoxCheckbox(panel, 1).checked, false,
|
||||||
"The second blackbox checkbox should now be unchecked.");
|
"The second blackbox checkbox should now be unchecked.");
|
||||||
|
|
||||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 0 }, true, "#canvas1");
|
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 255 }, true, "#canvas1");
|
||||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 0 }, true, "#canvas2");
|
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 255 }, true, "#canvas2");
|
||||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 0, b: 0, a: 0 }, true, "#canvas1");
|
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 0, b: 0, a: 255 }, true, "#canvas1");
|
||||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 0, b: 0, a: 0 }, true, "#canvas2");
|
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 0, b: 0, a: 255 }, true, "#canvas2");
|
||||||
ok(true, "The second program was correctly blackboxed.");
|
ok(true, "The second program was correctly blackboxed.");
|
||||||
|
|
||||||
ShadersListView._onShaderMouseEnter({ target: getItemLabel(panel, 0) });
|
ShadersListView._onProgramMouseEnter({ target: getItemLabel(panel, 0) });
|
||||||
|
|
||||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 0 }, true, "#canvas1");
|
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 255 }, true, "#canvas1");
|
||||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 0 }, true, "#canvas2");
|
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 255 }, true, "#canvas2");
|
||||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 0, b: 0, a: 0 }, true, "#canvas1");
|
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 0, b: 0, a: 255 }, true, "#canvas1");
|
||||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 0, b: 0, a: 0 }, true, "#canvas2");
|
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 0, b: 0, a: 255 }, true, "#canvas2");
|
||||||
ok(true, "Highlighting didn't work while blackboxed (1).");
|
ok(true, "Highlighting didn't work while blackboxed (1).");
|
||||||
|
|
||||||
ShadersListView._onShaderMouseLeave({ target: getItemLabel(panel, 0) });
|
ShadersListView._onProgramMouseLeave({ target: getItemLabel(panel, 0) });
|
||||||
ShadersListView._onShaderMouseEnter({ target: getItemLabel(panel, 1) });
|
ShadersListView._onProgramMouseEnter({ target: getItemLabel(panel, 1) });
|
||||||
|
|
||||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 0 }, true, "#canvas1");
|
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 255 }, true, "#canvas1");
|
||||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 0 }, true, "#canvas2");
|
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 255 }, true, "#canvas2");
|
||||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 0, b: 0, a: 0 }, true, "#canvas1");
|
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 0, b: 0, a: 255 }, true, "#canvas1");
|
||||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 0, b: 0, a: 0 }, true, "#canvas2");
|
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 0, b: 0, a: 255 }, true, "#canvas2");
|
||||||
ok(true, "Highlighting didn't work while blackboxed (2).");
|
ok(true, "Highlighting didn't work while blackboxed (2).");
|
||||||
|
|
||||||
ShadersListView._onShaderMouseLeave({ target: getItemLabel(panel, 1) });
|
ShadersListView._onProgramMouseLeave({ target: getItemLabel(panel, 1) });
|
||||||
|
|
||||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 0 }, true, "#canvas1");
|
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 255 }, true, "#canvas1");
|
||||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 0 }, true, "#canvas2");
|
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 255 }, true, "#canvas2");
|
||||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 0, b: 0, a: 0 }, true, "#canvas1");
|
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 0, b: 0, a: 255 }, true, "#canvas1");
|
||||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 0, b: 0, a: 0 }, true, "#canvas2");
|
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 0, b: 0, a: 255 }, true, "#canvas2");
|
||||||
ok(true, "Highlighting didn't work while blackboxed (3).");
|
ok(true, "Highlighting didn't work while blackboxed (3).");
|
||||||
|
|
||||||
getBlackBoxCheckbox(panel, 0).click();
|
getBlackBoxCheckbox(panel, 0).click();
|
||||||
@ -121,7 +121,7 @@ function ifWebGLSupported() {
|
|||||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||||
ok(true, "The two programs were correctly unblackboxed.");
|
ok(true, "The two programs were correctly unblackboxed.");
|
||||||
|
|
||||||
ShadersListView._onShaderMouseEnter({ target: getItemLabel(panel, 0) });
|
ShadersListView._onProgramMouseEnter({ target: getItemLabel(panel, 0) });
|
||||||
|
|
||||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true, "#canvas1");
|
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true, "#canvas1");
|
||||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||||
@ -129,8 +129,8 @@ function ifWebGLSupported() {
|
|||||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||||
ok(true, "The first program was correctly highlighted.");
|
ok(true, "The first program was correctly highlighted.");
|
||||||
|
|
||||||
ShadersListView._onShaderMouseLeave({ target: getItemLabel(panel, 0) });
|
ShadersListView._onProgramMouseLeave({ target: getItemLabel(panel, 0) });
|
||||||
ShadersListView._onShaderMouseEnter({ target: getItemLabel(panel, 1) });
|
ShadersListView._onProgramMouseEnter({ target: getItemLabel(panel, 1) });
|
||||||
|
|
||||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 255, b: 0, a: 255 }, true, "#canvas1");
|
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 255, b: 0, a: 255 }, true, "#canvas1");
|
||||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true, "#canvas2");
|
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true, "#canvas2");
|
||||||
@ -138,7 +138,7 @@ function ifWebGLSupported() {
|
|||||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 255, g: 0, b: 0, a: 255 }, true, "#canvas2");
|
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 255, g: 0, b: 0, a: 255 }, true, "#canvas2");
|
||||||
ok(true, "The second program was correctly highlighted.");
|
ok(true, "The second program was correctly highlighted.");
|
||||||
|
|
||||||
ShadersListView._onShaderMouseLeave({ target: getItemLabel(panel, 1) });
|
ShadersListView._onProgramMouseLeave({ target: getItemLabel(panel, 1) });
|
||||||
|
|
||||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 255, b: 0, a: 255 }, true, "#canvas1");
|
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 255, b: 0, a: 255 }, true, "#canvas1");
|
||||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||||
|
@ -35,7 +35,7 @@ function ifWebGLSupported() {
|
|||||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 255, g: 255, b: 0, a: 255 }, true, "#canvas1");
|
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 255, g: 255, b: 0, a: 255 }, true, "#canvas1");
|
||||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||||
|
|
||||||
ShadersListView._onShaderMouseEnter({ target: getItemLabel(panel, 0) });
|
ShadersListView._onProgramMouseEnter({ target: getItemLabel(panel, 0) });
|
||||||
|
|
||||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true, "#canvas1");
|
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true, "#canvas1");
|
||||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||||
@ -43,8 +43,8 @@ function ifWebGLSupported() {
|
|||||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||||
ok(true, "The first program was correctly highlighted.");
|
ok(true, "The first program was correctly highlighted.");
|
||||||
|
|
||||||
ShadersListView._onShaderMouseLeave({ target: getItemLabel(panel, 0) });
|
ShadersListView._onProgramMouseLeave({ target: getItemLabel(panel, 0) });
|
||||||
ShadersListView._onShaderMouseEnter({ target: getItemLabel(panel, 1) });
|
ShadersListView._onProgramMouseEnter({ target: getItemLabel(panel, 1) });
|
||||||
|
|
||||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 255, b: 0, a: 255 }, true, "#canvas1");
|
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 255, b: 0, a: 255 }, true, "#canvas1");
|
||||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true, "#canvas2");
|
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true, "#canvas2");
|
||||||
@ -52,7 +52,7 @@ function ifWebGLSupported() {
|
|||||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 255, g: 0, b: 0, a: 255 }, true, "#canvas2");
|
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 255, g: 0, b: 0, a: 255 }, true, "#canvas2");
|
||||||
ok(true, "The second program was correctly highlighted.");
|
ok(true, "The second program was correctly highlighted.");
|
||||||
|
|
||||||
ShadersListView._onShaderMouseLeave({ target: getItemLabel(panel, 1) });
|
ShadersListView._onProgramMouseLeave({ target: getItemLabel(panel, 1) });
|
||||||
|
|
||||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 255, b: 0, a: 255 }, true, "#canvas1");
|
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 255, b: 0, a: 255 }, true, "#canvas1");
|
||||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||||
@ -60,7 +60,7 @@ function ifWebGLSupported() {
|
|||||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||||
ok(true, "The two programs were correctly unhighlighted.");
|
ok(true, "The two programs were correctly unhighlighted.");
|
||||||
|
|
||||||
ShadersListView._onShaderMouseEnter({ target: getBlackBoxCheckbox(panel, 0) });
|
ShadersListView._onProgramMouseEnter({ target: getBlackBoxCheckbox(panel, 0) });
|
||||||
|
|
||||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 255, b: 0, a: 255 }, true, "#canvas1");
|
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 255, b: 0, a: 255 }, true, "#canvas1");
|
||||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||||
@ -68,7 +68,7 @@ function ifWebGLSupported() {
|
|||||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||||
ok(true, "The two programs were left unchanged after hovering a blackbox checkbox.");
|
ok(true, "The two programs were left unchanged after hovering a blackbox checkbox.");
|
||||||
|
|
||||||
ShadersListView._onShaderMouseLeave({ target: getBlackBoxCheckbox(panel, 0) });
|
ShadersListView._onProgramMouseLeave({ target: getBlackBoxCheckbox(panel, 0) });
|
||||||
|
|
||||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 255, b: 0, a: 255 }, true, "#canvas1");
|
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 255, b: 0, a: 255 }, true, "#canvas1");
|
||||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||||
|
@ -2,7 +2,8 @@
|
|||||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests if editing a vertex and a fragment shader works properly.
|
* Tests if editing a vertex and a fragment shader would permanently store
|
||||||
|
* their new source on the backend and reshow it in the frontend when required.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function ifWebGLSupported() {
|
function ifWebGLSupported() {
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests that the highlight/unhighlight operations on program actors
|
* Tests that the highlight/unhighlight and blackbox/unblackbox operations on
|
||||||
* work as expected.
|
* program actors work as expected.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function ifWebGLSupported() {
|
function ifWebGLSupported() {
|
||||||
@ -17,19 +17,31 @@ function ifWebGLSupported() {
|
|||||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true);
|
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true);
|
||||||
yield ensurePixelIs(debuggee, { x: 511, y: 511 }, { r: 0, g: 255, b: 0, a: 255 }, true);
|
yield ensurePixelIs(debuggee, { x: 511, y: 511 }, { r: 0, g: 255, b: 0, a: 255 }, true);
|
||||||
yield checkShaderSource("The shader sources are correct before highlighting.");
|
yield checkShaderSource("The shader sources are correct before highlighting.");
|
||||||
ok(true, "The top left pixel color was correct before highlighting.");
|
ok(true, "The corner pixel colors are correct before highlighting.");
|
||||||
|
|
||||||
yield programActor.highlight([0, 0, 1, 1]);
|
yield programActor.highlight([0, 0, 1, 1]);
|
||||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 255, a: 255 }, true);
|
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 255, a: 255 }, true);
|
||||||
yield ensurePixelIs(debuggee, { x: 511, y: 511 }, { r: 0, g: 0, b: 255, a: 255 }, true);
|
yield ensurePixelIs(debuggee, { x: 511, y: 511 }, { r: 0, g: 0, b: 255, a: 255 }, true);
|
||||||
yield checkShaderSource("The shader sources are preserved after highlighting.");
|
yield checkShaderSource("The shader sources are preserved after highlighting.");
|
||||||
ok(true, "The top left pixel color is correct after highlighting.");
|
ok(true, "The corner pixel colors are correct after highlighting.");
|
||||||
|
|
||||||
yield programActor.unhighlight();
|
yield programActor.unhighlight();
|
||||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true);
|
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true);
|
||||||
yield ensurePixelIs(debuggee, { x: 511, y: 511 }, { r: 0, g: 255, b: 0, a: 255 }, true);
|
yield ensurePixelIs(debuggee, { x: 511, y: 511 }, { r: 0, g: 255, b: 0, a: 255 }, true);
|
||||||
yield checkShaderSource("The shader sources are correct after unhighlighting.");
|
yield checkShaderSource("The shader sources are correct after unhighlighting.");
|
||||||
ok(true, "The top left pixel color is correct after unhighlighting.");
|
ok(true, "The corner pixel colors are correct after unhighlighting.");
|
||||||
|
|
||||||
|
yield programActor.blackbox();
|
||||||
|
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 255 }, true);
|
||||||
|
yield ensurePixelIs(debuggee, { x: 511, y: 511 }, { r: 0, g: 0, b: 0, a: 255 }, true);
|
||||||
|
yield checkShaderSource("The shader sources are preserved after blackboxing.");
|
||||||
|
ok(true, "The corner pixel colors are correct after blackboxing.");
|
||||||
|
|
||||||
|
yield programActor.unblackbox();
|
||||||
|
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true);
|
||||||
|
yield ensurePixelIs(debuggee, { x: 511, y: 511 }, { r: 0, g: 255, b: 0, a: 255 }, true);
|
||||||
|
yield checkShaderSource("The shader sources are correct after unblackboxing.");
|
||||||
|
ok(true, "The corner pixel colors are correct after unblackboxing.");
|
||||||
|
|
||||||
function checkShaderSource(aMessage) {
|
function checkShaderSource(aMessage) {
|
||||||
return Task.spawn(function() {
|
return Task.spawn(function() {
|
||||||
|
@ -0,0 +1,47 @@
|
|||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that the blackbox/unblackbox operations work as expected with
|
||||||
|
* overlapping geometry.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function ifWebGLSupported() {
|
||||||
|
let [target, debuggee, front] = yield initBackend(OVERLAPPING_GEOMETRY_CANVAS_URL);
|
||||||
|
front.setup({ reload: true });
|
||||||
|
|
||||||
|
let firstProgramActor = yield once(front, "program-linked");
|
||||||
|
let secondProgramActor = yield once(front, "program-linked");
|
||||||
|
|
||||||
|
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 255, b: 0, a: 255 }, true);
|
||||||
|
yield ensurePixelIs(debuggee, { x: 64, y: 64 }, { r: 0, g: 255, b: 255, a: 255 }, true);
|
||||||
|
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 255, g: 255, b: 0, a: 255 }, true);
|
||||||
|
ok(true, "The corner vs. center pixel colors are correct before blackboxing.");
|
||||||
|
|
||||||
|
yield firstProgramActor.blackbox();
|
||||||
|
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 255 }, true);
|
||||||
|
yield ensurePixelIs(debuggee, { x: 64, y: 64 }, { r: 0, g: 255, b: 255, a: 255 }, true);
|
||||||
|
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 0, b: 0, a: 255 }, true);
|
||||||
|
ok(true, "The corner vs. center pixel colors are correct after blackboxing (1).");
|
||||||
|
|
||||||
|
yield firstProgramActor.unblackbox();
|
||||||
|
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 255, b: 0, a: 255 }, true);
|
||||||
|
yield ensurePixelIs(debuggee, { x: 64, y: 64 }, { r: 0, g: 255, b: 255, a: 255 }, true);
|
||||||
|
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 255, g: 255, b: 0, a: 255 }, true);
|
||||||
|
ok(true, "The corner vs. center pixel colors are correct after unblackboxing (1).");
|
||||||
|
|
||||||
|
yield secondProgramActor.blackbox();
|
||||||
|
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 255, b: 0, a: 255 }, true);
|
||||||
|
yield ensurePixelIs(debuggee, { x: 64, y: 64 }, { r: 255, g: 255, b: 0, a: 255 }, true);
|
||||||
|
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 255, g: 255, b: 0, a: 255 }, true);
|
||||||
|
ok(true, "The corner vs. center pixel colors are correct after blackboxing (2).");
|
||||||
|
|
||||||
|
yield secondProgramActor.unblackbox();
|
||||||
|
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 255, b: 0, a: 255 }, true);
|
||||||
|
yield ensurePixelIs(debuggee, { x: 64, y: 64 }, { r: 0, g: 255, b: 255, a: 255 }, true);
|
||||||
|
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 255, g: 255, b: 0, a: 255 }, true);
|
||||||
|
ok(true, "The corner vs. center pixel colors are correct after unblackboxing (2).");
|
||||||
|
|
||||||
|
yield removeTab(target.tab);
|
||||||
|
finish();
|
||||||
|
}
|
120
browser/devtools/shadereditor/test/doc_overlapping-geometry.html
Normal file
120
browser/devtools/shadereditor/test/doc_overlapping-geometry.html
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
<!-- Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||||
|
<!doctype html>
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<title>WebGL editor test page</title>
|
||||||
|
|
||||||
|
<script id="shader-vs" type="x-shader/x-vertex">
|
||||||
|
precision lowp float;
|
||||||
|
attribute vec3 aVertexPosition;
|
||||||
|
uniform float uDepth;
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
gl_Position = vec4(aVertexPosition, uDepth);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script id="shader-fs-0" type="x-shader/x-fragment">
|
||||||
|
precision lowp float;
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script id="shader-fs-1" type="x-shader/x-fragment">
|
||||||
|
precision lowp float;
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
gl_FragColor = vec4(0.0, 1.0, 1.0, 1.0);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<canvas id="canvas" width="128" height="128"></canvas>
|
||||||
|
|
||||||
|
<script type="text/javascript;version=1.8">
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
let canvas, gl;
|
||||||
|
let program = [];
|
||||||
|
let squareVerticesPositionBuffer;
|
||||||
|
let vertexPositionAttribute = [];
|
||||||
|
let depthUniform = [];
|
||||||
|
|
||||||
|
window.onload = function() {
|
||||||
|
canvas = document.querySelector("canvas");
|
||||||
|
gl = canvas.getContext("webgl");
|
||||||
|
gl.clearColor(0.0, 0.0, 0.0, 1.0);
|
||||||
|
|
||||||
|
initProgram(0);
|
||||||
|
initProgram(1);
|
||||||
|
initBuffers();
|
||||||
|
drawScene();
|
||||||
|
}
|
||||||
|
|
||||||
|
function initProgram(i) {
|
||||||
|
let vertexShader = getShader("shader-vs");
|
||||||
|
let fragmentShader = getShader("shader-fs-" + i);
|
||||||
|
|
||||||
|
program[i] = gl.createProgram();
|
||||||
|
gl.attachShader(program[i], vertexShader);
|
||||||
|
gl.attachShader(program[i], fragmentShader);
|
||||||
|
gl.linkProgram(program[i]);
|
||||||
|
|
||||||
|
vertexPositionAttribute[i] = gl.getAttribLocation(program[i], "aVertexPosition");
|
||||||
|
gl.enableVertexAttribArray(vertexPositionAttribute[i]);
|
||||||
|
|
||||||
|
depthUniform[i] = gl.getUniformLocation(program[i], "uDepth");
|
||||||
|
}
|
||||||
|
|
||||||
|
function getShader(id) {
|
||||||
|
let script = document.getElementById(id);
|
||||||
|
let source = script.textContent;
|
||||||
|
let shader;
|
||||||
|
|
||||||
|
if (script.type == "x-shader/x-fragment") {
|
||||||
|
shader = gl.createShader(gl.FRAGMENT_SHADER);
|
||||||
|
} else if (script.type == "x-shader/x-vertex") {
|
||||||
|
shader = gl.createShader(gl.VERTEX_SHADER);
|
||||||
|
}
|
||||||
|
|
||||||
|
gl.shaderSource(shader, source);
|
||||||
|
gl.compileShader(shader);
|
||||||
|
|
||||||
|
return shader;
|
||||||
|
}
|
||||||
|
|
||||||
|
function initBuffers() {
|
||||||
|
squareVerticesPositionBuffer = gl.createBuffer();
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, squareVerticesPositionBuffer);
|
||||||
|
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
|
||||||
|
1.0, 1.0, 0.0,
|
||||||
|
-1.0, 1.0, 0.0,
|
||||||
|
1.0, -1.0, 0.0,
|
||||||
|
-1.0, -1.0, 0.0
|
||||||
|
]), gl.STATIC_DRAW);
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawScene() {
|
||||||
|
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
|
for (let i = 0; i < 2; i++) {
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, squareVerticesPositionBuffer);
|
||||||
|
gl.vertexAttribPointer(vertexPositionAttribute[i], 3, gl.FLOAT, false, 0, 0);
|
||||||
|
|
||||||
|
gl.useProgram(program[i]);
|
||||||
|
gl.uniform1f(depthUniform[i], i + 1);
|
||||||
|
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
window.requestAnimationFrame(drawScene);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
@ -27,6 +27,7 @@ const EXAMPLE_URL = "http://example.com/browser/browser/devtools/shadereditor/te
|
|||||||
const SIMPLE_CANVAS_URL = EXAMPLE_URL + "doc_simple-canvas.html";
|
const SIMPLE_CANVAS_URL = EXAMPLE_URL + "doc_simple-canvas.html";
|
||||||
const SHADER_ORDER_URL = EXAMPLE_URL + "doc_shader-order.html";
|
const SHADER_ORDER_URL = EXAMPLE_URL + "doc_shader-order.html";
|
||||||
const MULTIPLE_CONTEXTS_URL = EXAMPLE_URL + "doc_multiple-contexts.html";
|
const MULTIPLE_CONTEXTS_URL = EXAMPLE_URL + "doc_multiple-contexts.html";
|
||||||
|
const OVERLAPPING_GEOMETRY_CANVAS_URL = EXAMPLE_URL + "doc_overlapping-geometry.html";
|
||||||
|
|
||||||
// All tests are asynchronous.
|
// All tests are asynchronous.
|
||||||
waitForExplicitFinish();
|
waitForExplicitFinish();
|
||||||
|
@ -95,6 +95,10 @@ function Tooltip(doc) {
|
|||||||
module.exports.Tooltip = Tooltip;
|
module.exports.Tooltip = Tooltip;
|
||||||
|
|
||||||
Tooltip.prototype = {
|
Tooltip.prototype = {
|
||||||
|
defaultPosition: "before_start",
|
||||||
|
defaultOffsetX: 0,
|
||||||
|
defaultOffsetY: 0,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show the tooltip. It might be wise to append some content first if you
|
* Show the tooltip. It might be wise to append some content first if you
|
||||||
* don't want the tooltip to be empty. You may access the content of the
|
* don't want the tooltip to be empty. You may access the content of the
|
||||||
@ -105,9 +109,12 @@ Tooltip.prototype = {
|
|||||||
* https://developer.mozilla.org/en-US/docs/XUL/PopupGuide/Positioning
|
* https://developer.mozilla.org/en-US/docs/XUL/PopupGuide/Positioning
|
||||||
* Defaults to before_start
|
* Defaults to before_start
|
||||||
*/
|
*/
|
||||||
show: function(anchor, position="before_start") {
|
show: function(anchor,
|
||||||
|
position = this.defaultPosition,
|
||||||
|
x = this.defaultOffsetX,
|
||||||
|
y = this.defaultOffsetY) {
|
||||||
this.panel.hidden = false;
|
this.panel.hidden = false;
|
||||||
this.panel.openPopup(anchor, position);
|
this.panel.openPopup(anchor, position, x, y);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -258,11 +265,44 @@ Tooltip.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fill the tooltip with an image, displayed over a tiled background useful
|
* Sets some text as the content of this tooltip.
|
||||||
* for transparent images.
|
*
|
||||||
* Also adds the image dimension as a label at the bottom.
|
* @param string[] messages
|
||||||
|
* A list of text messages.
|
||||||
*/
|
*/
|
||||||
setImageContent: function(imageUrl, maxDim=400) {
|
setTextContent: function(...messages) {
|
||||||
|
let vbox = this.doc.createElement("vbox");
|
||||||
|
vbox.className = "devtools-tooltip-simple-text-container";
|
||||||
|
vbox.setAttribute("flex", "1");
|
||||||
|
|
||||||
|
for (let text of messages) {
|
||||||
|
let description = this.doc.createElement("description");
|
||||||
|
description.setAttribute("flex", "1");
|
||||||
|
description.className = "devtools-tooltip-simple-text";
|
||||||
|
description.textContent = text;
|
||||||
|
vbox.appendChild(description);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.content = vbox;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fill the tooltip with an image, displayed over a tiled background useful
|
||||||
|
* for transparent images. Also adds the image dimension as a label at the
|
||||||
|
* bottom.
|
||||||
|
* @param {string} imageUrl
|
||||||
|
* The url to load the image from
|
||||||
|
* @param {Object} options
|
||||||
|
* The following options are supported:
|
||||||
|
* - resized : whether or not the image identified by imageUrl has been
|
||||||
|
* resized before this function was called.
|
||||||
|
* - naturalWidth/naturalHeight : the original size of the image before
|
||||||
|
* it was resized, if if was resized before this function was called.
|
||||||
|
* If not provided, will be measured on the loaded image.
|
||||||
|
* - maxDim : if the image should be resized before being shown, pass
|
||||||
|
* a number here
|
||||||
|
*/
|
||||||
|
setImageContent: function(imageUrl, options={}) {
|
||||||
// Main container
|
// Main container
|
||||||
let vbox = this.doc.createElement("vbox");
|
let vbox = this.doc.createElement("vbox");
|
||||||
vbox.setAttribute("align", "center")
|
vbox.setAttribute("align", "center")
|
||||||
@ -279,9 +319,9 @@ Tooltip.prototype = {
|
|||||||
// Display the image
|
// Display the image
|
||||||
let image = this.doc.createElement("image");
|
let image = this.doc.createElement("image");
|
||||||
image.setAttribute("src", imageUrl);
|
image.setAttribute("src", imageUrl);
|
||||||
if (maxDim) {
|
if (options.maxDim) {
|
||||||
image.style.maxWidth = maxDim + "px";
|
image.style.maxWidth = options.maxDim + "px";
|
||||||
image.style.maxHeight = maxDim + "px";
|
image.style.maxHeight = options.maxDim + "px";
|
||||||
}
|
}
|
||||||
tiles.appendChild(image);
|
tiles.appendChild(image);
|
||||||
|
|
||||||
@ -294,11 +334,9 @@ Tooltip.prototype = {
|
|||||||
imgObj.onload = null;
|
imgObj.onload = null;
|
||||||
|
|
||||||
// Display dimensions
|
// Display dimensions
|
||||||
label.textContent = imgObj.naturalWidth + " x " + imgObj.naturalHeight;
|
let w = options.naturalWidth || imgObj.naturalWidth;
|
||||||
if (imgObj.naturalWidth > maxDim ||
|
let h = options.naturalHeight || imgObj.naturalHeight;
|
||||||
imgObj.naturalHeight > maxDim) {
|
label.textContent = w + " x " + h;
|
||||||
label.textContent += " *";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -309,7 +347,9 @@ Tooltip.prototype = {
|
|||||||
setCssBackgroundImageContent: function(cssBackground, sheetHref, maxDim=400) {
|
setCssBackgroundImageContent: function(cssBackground, sheetHref, maxDim=400) {
|
||||||
let uri = getBackgroundImageUri(cssBackground, sheetHref);
|
let uri = getBackgroundImageUri(cssBackground, sheetHref);
|
||||||
if (uri) {
|
if (uri) {
|
||||||
this.setImageContent(uri, maxDim);
|
this.setImageContent(uri, {
|
||||||
|
maxDim: maxDim
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -1,15 +1,25 @@
|
|||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
.errors,
|
||||||
.breakpoints {
|
.breakpoints {
|
||||||
width: 16px;
|
width: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.breakpoint, .debugLocation, .breakpoint-debugLocation {
|
.error, .breakpoint, .debugLocation, .breakpoint-debugLocation {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
width: 14px;
|
width: 12px;
|
||||||
height: 14px;
|
height: 12px;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-position: center center;
|
background-position: center;
|
||||||
background-size: 12px;
|
background-size: contain;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error {
|
||||||
|
background-image: url("chrome://browser/skin/devtools/orion-error.png");
|
||||||
|
opacity: 0.75;
|
||||||
}
|
}
|
||||||
|
|
||||||
.breakpoint {
|
.breakpoint {
|
||||||
@ -23,4 +33,8 @@
|
|||||||
.breakpoint.debugLocation {
|
.breakpoint.debugLocation {
|
||||||
background-image: url("chrome://browser/skin/devtools/orion-debug-location.png"),
|
background-image: url("chrome://browser/skin/devtools/orion-debug-location.png"),
|
||||||
url("chrome://browser/skin/devtools/orion-breakpoint.png");
|
url("chrome://browser/skin/devtools/orion-breakpoint.png");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.error-line {
|
||||||
|
background: rgba(255,0,0,0.2);
|
||||||
|
}
|
||||||
|
@ -6,38 +6,6 @@
|
|||||||
|
|
||||||
const dbginfo = new WeakMap();
|
const dbginfo = new WeakMap();
|
||||||
|
|
||||||
// Private functions
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a marker to the breakpoints gutter.
|
|
||||||
* Type should be either a 'breakpoint' or a 'debugLocation'.
|
|
||||||
*/
|
|
||||||
function addMarker(cm, line, type) {
|
|
||||||
let info = cm.lineInfo(line);
|
|
||||||
|
|
||||||
if (info.gutterMarkers)
|
|
||||||
return void info.gutterMarkers.breakpoints.classList.add(type);
|
|
||||||
|
|
||||||
let mark = cm.getWrapperElement().ownerDocument.createElement("div");
|
|
||||||
mark.className = type;
|
|
||||||
mark.innerHTML = "";
|
|
||||||
|
|
||||||
cm.setGutterMarker(info.line, "breakpoints", mark);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes a marker from the breakpoints gutter.
|
|
||||||
* Type should be either a 'breakpoint' or a 'debugLocation'.
|
|
||||||
*/
|
|
||||||
function removeMarker(cm, line, type) {
|
|
||||||
let info = cm.lineInfo(line);
|
|
||||||
|
|
||||||
if (!info || !info.gutterMarkers)
|
|
||||||
return;
|
|
||||||
|
|
||||||
info.gutterMarkers.breakpoints.classList.remove(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
// These functions implement search within the debugger. Since
|
// These functions implement search within the debugger. Since
|
||||||
// search in the debugger is different from other components,
|
// search in the debugger is different from other components,
|
||||||
// we can't use search.js CodeMirror addon. This is a slightly
|
// we can't use search.js CodeMirror addon. This is a slightly
|
||||||
@ -155,7 +123,7 @@ function addBreakpoint(ctx, line, cond) {
|
|||||||
let meta = dbginfo.get(ed);
|
let meta = dbginfo.get(ed);
|
||||||
let info = cm.lineInfo(line);
|
let info = cm.lineInfo(line);
|
||||||
|
|
||||||
addMarker(cm, line, "breakpoint");
|
ed.addMarker(line, "breakpoints", "breakpoint");
|
||||||
meta.breakpoints[line] = { condition: cond };
|
meta.breakpoints[line] = { condition: cond };
|
||||||
|
|
||||||
info.handle.on("delete", function onDelete() {
|
info.handle.on("delete", function onDelete() {
|
||||||
@ -179,7 +147,7 @@ function removeBreakpoint(ctx, line) {
|
|||||||
let info = cm.lineInfo(line);
|
let info = cm.lineInfo(line);
|
||||||
|
|
||||||
meta.breakpoints[info.line] = null;
|
meta.breakpoints[info.line] = null;
|
||||||
removeMarker(cm, info.line, "breakpoint");
|
ed.removeMarker(info.line, "breakpoints", "breakpoint");
|
||||||
ed.emit("breakpointRemoved", line);
|
ed.emit("breakpointRemoved", line);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,11 +171,11 @@ function getBreakpoints(ctx) {
|
|||||||
* display the line on which the Debugger is currently paused.
|
* display the line on which the Debugger is currently paused.
|
||||||
*/
|
*/
|
||||||
function setDebugLocation(ctx, line) {
|
function setDebugLocation(ctx, line) {
|
||||||
let { ed, cm } = ctx;
|
let { ed } = ctx;
|
||||||
let meta = dbginfo.get(ed);
|
let meta = dbginfo.get(ed);
|
||||||
|
|
||||||
meta.debugLocation = line;
|
meta.debugLocation = line;
|
||||||
addMarker(cm, line, "debugLocation");
|
ed.addMarker(line, "breakpoints", "debugLocation");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -226,11 +194,11 @@ function getDebugLocation(ctx) {
|
|||||||
* also removes a visual anchor from the breakpoints gutter.
|
* also removes a visual anchor from the breakpoints gutter.
|
||||||
*/
|
*/
|
||||||
function clearDebugLocation(ctx) {
|
function clearDebugLocation(ctx) {
|
||||||
let { ed, cm } = ctx;
|
let { ed } = ctx;
|
||||||
let meta = dbginfo.get(ed);
|
let meta = dbginfo.get(ed);
|
||||||
|
|
||||||
if (meta.debugLocation != null) {
|
if (meta.debugLocation != null) {
|
||||||
removeMarker(cm, meta.debugLocation, "debugLocation");
|
ed.removeMarker(meta.debugLocation, "breakpoints", "debugLocation");
|
||||||
meta.debugLocation = null;
|
meta.debugLocation = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -340,7 +340,7 @@ Editor.prototype = {
|
|||||||
* Replaces contents of a text area within the from/to {line, ch}
|
* Replaces contents of a text area within the from/to {line, ch}
|
||||||
* range. If neither from nor to arguments are provided works
|
* range. If neither from nor to arguments are provided works
|
||||||
* exactly like setText. If only from object is provided, inserts
|
* exactly like setText. If only from object is provided, inserts
|
||||||
* text at that point.
|
* text at that point, *overwriting* as many characters as needed.
|
||||||
*/
|
*/
|
||||||
replaceText: function (value, from, to) {
|
replaceText: function (value, from, to) {
|
||||||
let cm = editors.get(this);
|
let cm = editors.get(this);
|
||||||
@ -356,6 +356,15 @@ Editor.prototype = {
|
|||||||
cm.replaceRange(value, from, to);
|
cm.replaceRange(value, from, to);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts text at the specified {line, ch} position, shifting existing
|
||||||
|
* contents as necessary.
|
||||||
|
*/
|
||||||
|
insertText: function (value, at) {
|
||||||
|
let cm = editors.get(this);
|
||||||
|
cm.replaceRange(value, at, at);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deselects contents of the text area.
|
* Deselects contents of the text area.
|
||||||
*/
|
*/
|
||||||
@ -370,7 +379,7 @@ Editor.prototype = {
|
|||||||
* Marks the contents as clean and returns the current
|
* Marks the contents as clean and returns the current
|
||||||
* version number.
|
* version number.
|
||||||
*/
|
*/
|
||||||
markClean: function () {
|
setClean: function () {
|
||||||
let cm = editors.get(this);
|
let cm = editors.get(this);
|
||||||
this.version = cm.changeGeneration();
|
this.version = cm.changeGeneration();
|
||||||
return this.version;
|
return this.version;
|
||||||
@ -519,6 +528,120 @@ Editor.prototype = {
|
|||||||
this.setFirstVisibleLine(topLine);
|
this.setFirstVisibleLine(topLine);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether a marker of a specified class exists in a line's gutter.
|
||||||
|
*/
|
||||||
|
hasMarker: function (line, gutterName, markerClass) {
|
||||||
|
let cm = editors.get(this);
|
||||||
|
let info = cm.lineInfo(line);
|
||||||
|
if (!info)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
let gutterMarkers = info.gutterMarkers;
|
||||||
|
if (!gutterMarkers)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
let marker = gutterMarkers[gutterName];
|
||||||
|
if (!marker)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return marker.classList.contains(markerClass);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a marker with a specified class to a line's gutter. If another marker
|
||||||
|
* exists on that line, the new marker class is added to its class list.
|
||||||
|
*/
|
||||||
|
addMarker: function (line, gutterName, markerClass) {
|
||||||
|
let cm = editors.get(this);
|
||||||
|
let info = cm.lineInfo(line);
|
||||||
|
if (!info)
|
||||||
|
return;
|
||||||
|
|
||||||
|
let gutterMarkers = info.gutterMarkers;
|
||||||
|
if (gutterMarkers) {
|
||||||
|
let marker = gutterMarkers[gutterName];
|
||||||
|
if (marker) {
|
||||||
|
marker.classList.add(markerClass);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let marker = cm.getWrapperElement().ownerDocument.createElement("div");
|
||||||
|
marker.className = markerClass;
|
||||||
|
cm.setGutterMarker(info.line, gutterName, marker);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The reverse of addMarker. Removes a marker of a specified class from a
|
||||||
|
* line's gutter.
|
||||||
|
*/
|
||||||
|
removeMarker: function (line, gutterName, markerClass) {
|
||||||
|
if (!this.hasMarker(line, gutterName, markerClass))
|
||||||
|
return;
|
||||||
|
|
||||||
|
let cm = editors.get(this);
|
||||||
|
cm.lineInfo(line).gutterMarkers[gutterName].classList.remove(markerClass);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove all gutter markers in the gutter with the given name.
|
||||||
|
*/
|
||||||
|
removeAllMarkers: function (gutterName) {
|
||||||
|
let cm = editors.get(this);
|
||||||
|
cm.clearGutter(gutterName);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles attaching a set of events listeners on a marker. They should
|
||||||
|
* be passed as an object literal with keys as event names and values as
|
||||||
|
* function listeners. The line number, marker node and optional data
|
||||||
|
* will be passed as arguments to the function listener.
|
||||||
|
*
|
||||||
|
* You don't need to worry about removing these event listeners.
|
||||||
|
* They're automatically orphaned when clearing markers.
|
||||||
|
*/
|
||||||
|
setMarkerListeners: function(line, gutterName, markerClass, events, data) {
|
||||||
|
if (!this.hasMarker(line, gutterName, markerClass))
|
||||||
|
return;
|
||||||
|
|
||||||
|
let cm = editors.get(this);
|
||||||
|
let marker = cm.lineInfo(line).gutterMarkers[gutterName];
|
||||||
|
|
||||||
|
for (let name in events) {
|
||||||
|
let listener = events[name].bind(this, line, marker, data);
|
||||||
|
marker.addEventListener(name, listener);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether a line is decorated using the specified class name.
|
||||||
|
*/
|
||||||
|
hasLineClass: function (line, className) {
|
||||||
|
let cm = editors.get(this);
|
||||||
|
let info = cm.lineInfo(line);
|
||||||
|
if (!info)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return info.wrapClass == className;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a CSS class name for the given line, including the text and gutter.
|
||||||
|
*/
|
||||||
|
addLineClass: function (line, className) {
|
||||||
|
let cm = editors.get(this);
|
||||||
|
cm.addLineClass(line, "wrap", className);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The reverse of addLineClass.
|
||||||
|
*/
|
||||||
|
removeLineClass: function (line, className) {
|
||||||
|
let cm = editors.get(this);
|
||||||
|
cm.removeLineClass(line, "wrap", className);
|
||||||
|
},
|
||||||
|
|
||||||
destroy: function () {
|
destroy: function () {
|
||||||
this.container = null;
|
this.container = null;
|
||||||
this.config = null;
|
this.config = null;
|
||||||
|
@ -376,7 +376,7 @@ StyleSheetEditor.prototype = {
|
|||||||
if (callback) {
|
if (callback) {
|
||||||
callback(returnFile);
|
callback(returnFile);
|
||||||
}
|
}
|
||||||
this.sourceEditor.markClean();
|
this.sourceEditor.setClean();
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -34,8 +34,8 @@ validator.invalidAppType=Unknown app type: '%S'.
|
|||||||
validator.invalidHostedPriviledges=Hosted App can't be type '%S'.
|
validator.invalidHostedPriviledges=Hosted App can't be type '%S'.
|
||||||
validator.noCertifiedSupport='certified' apps are not fully supported on the App manager.
|
validator.noCertifiedSupport='certified' apps are not fully supported on the App manager.
|
||||||
validator.nonAbsoluteLaunchPath=Launch path has to be an absolute path starting with '/': '%S'
|
validator.nonAbsoluteLaunchPath=Launch path has to be an absolute path starting with '/': '%S'
|
||||||
validator.invalidLaunchPath=Unable to access to app starting document '%S'
|
validator.accessFailedLaunchPath=Unable to access the app starting document '%S'
|
||||||
# LOCALIZATION NOTE (validator.invalidLaunchPathBadHttpCode): %1$S is the URI of
|
# LOCALIZATION NOTE (validator.accessFailedLaunchPathBadHttpCode): %1$S is the URI of
|
||||||
# the launch document, %2$S is the http error code.
|
# the launch document, %2$S is the http error code.
|
||||||
validator.invalidLaunchPathBadHttpCode=Unable to access to app starting document '%1$S', got HTTP code %2$S
|
validator.accessFailedLaunchPathBadHttpCode=Unable to access the app starting document '%1$S', got HTTP code %2$S
|
||||||
|
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
- 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/. -->
|
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||||
|
|
||||||
|
<!ENTITY popups.label "Pop-ups">
|
||||||
|
|
||||||
<!ENTITY blockPopups.label "Block pop-up windows">
|
<!ENTITY blockPopups.label "Block pop-up windows">
|
||||||
<!ENTITY blockPopups.accesskey "B">
|
<!ENTITY blockPopups.accesskey "B">
|
||||||
<!ENTITY popupExceptions.label "Exceptions…">
|
<!ENTITY popupExceptions.label "Exceptions…">
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
- 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/. -->
|
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||||
|
|
||||||
|
<!ENTITY general.label "General">
|
||||||
|
|
||||||
<!ENTITY warnAddonInstall.label "Warn me when sites try to install add-ons">
|
<!ENTITY warnAddonInstall.label "Warn me when sites try to install add-ons">
|
||||||
<!ENTITY warnAddonInstall.accesskey "W">
|
<!ENTITY warnAddonInstall.accesskey "W">
|
||||||
|
|
||||||
|
@ -44,6 +44,8 @@ let IndexedDB = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let prompt = Cc["@mozilla.org/content-permission/prompt;1"].createInstance(Ci.nsIContentPermissionPrompt);
|
let prompt = Cc["@mozilla.org/content-permission/prompt;1"].createInstance(Ci.nsIContentPermissionPrompt);
|
||||||
|
let types = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
|
||||||
|
types.appendElement({type: type, access: "unused"}, false);
|
||||||
|
|
||||||
// If the user waits a long time before responding, we default to UNKNOWN_ACTION.
|
// If the user waits a long time before responding, we default to UNKNOWN_ACTION.
|
||||||
let timeoutId = setTimeout(function() {
|
let timeoutId = setTimeout(function() {
|
||||||
@ -60,7 +62,7 @@ let IndexedDB = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
prompt.prompt({
|
prompt.prompt({
|
||||||
type: type,
|
types: types,
|
||||||
uri: Services.io.newURI(payload.location, null, null),
|
uri: Services.io.newURI(payload.location, null, null),
|
||||||
window: null,
|
window: null,
|
||||||
element: aMessage.target,
|
element: aMessage.target,
|
||||||
|
@ -56,8 +56,8 @@ ContentPermissionPrompt.prototype = {
|
|||||||
return chromeWin.Browser.getNotificationBox(request.element);
|
return chromeWin.Browser.getNotificationBox(request.element);
|
||||||
},
|
},
|
||||||
|
|
||||||
handleExistingPermission: function handleExistingPermission(request) {
|
handleExistingPermission: function handleExistingPermission(request, type) {
|
||||||
let result = Services.perms.testExactPermissionFromPrincipal(request.principal, request.type);
|
let result = Services.perms.testExactPermissionFromPrincipal(request.principal, type);
|
||||||
if (result == Ci.nsIPermissionManager.ALLOW_ACTION) {
|
if (result == Ci.nsIPermissionManager.ALLOW_ACTION) {
|
||||||
request.allow();
|
request.allow();
|
||||||
return true;
|
return true;
|
||||||
@ -70,20 +70,28 @@ ContentPermissionPrompt.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
prompt: function(request) {
|
prompt: function(request) {
|
||||||
|
// Only allow exactly one permission rquest here.
|
||||||
|
let types = request.types.QueryInterface(Ci.nsIArray);
|
||||||
|
if (types.length != 1) {
|
||||||
|
request.cancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let perm = types.queryElementAt(0, Ci.nsIContentPermissionType);
|
||||||
|
|
||||||
// returns true if the request was handled
|
// returns true if the request was handled
|
||||||
if (this.handleExistingPermission(request))
|
if (this.handleExistingPermission(request, perm.type))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
let pm = Services.perms;
|
let pm = Services.perms;
|
||||||
let notificationBox = this.getNotificationBoxForRequest(request);
|
let notificationBox = this.getNotificationBoxForRequest(request);
|
||||||
let browserBundle = Services.strings.createBundle("chrome://browser/locale/browser.properties");
|
let browserBundle = Services.strings.createBundle("chrome://browser/locale/browser.properties");
|
||||||
|
|
||||||
let notification = notificationBox.getNotificationWithValue(request.type);
|
let notification = notificationBox.getNotificationWithValue(perm.type);
|
||||||
if (notification)
|
if (notification)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
let entityName = kEntities[request.type];
|
let entityName = kEntities[perm.type];
|
||||||
let icon = kIcons[request.type] || "";
|
let icon = kIcons[perm.type] || "";
|
||||||
|
|
||||||
let buttons = [{
|
let buttons = [{
|
||||||
label: browserBundle.GetStringFromName(entityName + ".allow"),
|
label: browserBundle.GetStringFromName(entityName + ".allow"),
|
||||||
@ -96,7 +104,7 @@ ContentPermissionPrompt.prototype = {
|
|||||||
label: browserBundle.GetStringFromName("contentPermissions.alwaysForSite"),
|
label: browserBundle.GetStringFromName("contentPermissions.alwaysForSite"),
|
||||||
accessKey: "",
|
accessKey: "",
|
||||||
callback: function(notification) {
|
callback: function(notification) {
|
||||||
Services.perms.addFromPrincipal(request.principal, request.type, Ci.nsIPermissionManager.ALLOW_ACTION);
|
Services.perms.addFromPrincipal(request.principal, perm.type, Ci.nsIPermissionManager.ALLOW_ACTION);
|
||||||
request.allow();
|
request.allow();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -104,7 +112,7 @@ ContentPermissionPrompt.prototype = {
|
|||||||
label: browserBundle.GetStringFromName("contentPermissions.neverForSite"),
|
label: browserBundle.GetStringFromName("contentPermissions.neverForSite"),
|
||||||
accessKey: "",
|
accessKey: "",
|
||||||
callback: function(notification) {
|
callback: function(notification) {
|
||||||
Services.perms.addFromPrincipal(request.principal, request.type, Ci.nsIPermissionManager.DENY_ACTION);
|
Services.perms.addFromPrincipal(request.principal, perm.type, Ci.nsIPermissionManager.DENY_ACTION);
|
||||||
request.cancel();
|
request.cancel();
|
||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
@ -112,12 +120,12 @@ ContentPermissionPrompt.prototype = {
|
|||||||
let message = browserBundle.formatStringFromName(entityName + ".wantsTo",
|
let message = browserBundle.formatStringFromName(entityName + ".wantsTo",
|
||||||
[request.principal.URI.host], 1);
|
[request.principal.URI.host], 1);
|
||||||
let newBar = notificationBox.appendNotification(message,
|
let newBar = notificationBox.appendNotification(message,
|
||||||
request.type,
|
perm.type,
|
||||||
icon,
|
icon,
|
||||||
notificationBox.PRIORITY_WARNING_MEDIUM,
|
notificationBox.PRIORITY_WARNING_MEDIUM,
|
||||||
buttons);
|
buttons);
|
||||||
|
|
||||||
if (request.type == "geolocation") {
|
if (perm.type == "geolocation") {
|
||||||
// Add the "learn more" link.
|
// Add the "learn more" link.
|
||||||
let link = newBar.ownerDocument.createElement("label");
|
let link = newBar.ownerDocument.createElement("label");
|
||||||
link.setAttribute("value", browserBundle.GetStringFromName("geolocation.learnMore"));
|
link.setAttribute("value", browserBundle.GetStringFromName("geolocation.learnMore"));
|
||||||
|
@ -255,7 +255,11 @@ this.UITour = {
|
|||||||
if (uri.schemeIs("chrome"))
|
if (uri.schemeIs("chrome"))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (!uri.schemeIs("https"))
|
let allowedSchemes = new Set(["https"]);
|
||||||
|
if (!Services.prefs.getBoolPref("browser.uitour.requireSecure"))
|
||||||
|
allowedSchemes.add("http");
|
||||||
|
|
||||||
|
if (!allowedSchemes.has(uri.scheme))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
this.importPermissions();
|
this.importPermissions();
|
||||||
|
@ -32,13 +32,12 @@ function is_element_hidden(element, msg) {
|
|||||||
ok(is_hidden(element), msg);
|
ok(is_hidden(element), msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadTestPage(callback, untrustedHost = false) {
|
function loadTestPage(callback, host = "https://example.com/") {
|
||||||
if (gTestTab)
|
if (gTestTab)
|
||||||
gBrowser.removeTab(gTestTab);
|
gBrowser.removeTab(gTestTab);
|
||||||
|
|
||||||
let url = getRootDirectory(gTestPath) + "uitour.html";
|
let url = getRootDirectory(gTestPath) + "uitour.html";
|
||||||
if (untrustedHost)
|
url = url.replace("chrome://mochitests/content/", host);
|
||||||
url = url.replace("chrome://mochitests/content/", "http://example.com/");
|
|
||||||
|
|
||||||
gTestTab = gBrowser.addTab(url);
|
gTestTab = gBrowser.addTab(url);
|
||||||
gBrowser.selectedTab = gTestTab;
|
gBrowser.selectedTab = gTestTab;
|
||||||
@ -55,6 +54,8 @@ function loadTestPage(callback, untrustedHost = false) {
|
|||||||
|
|
||||||
function test() {
|
function test() {
|
||||||
Services.prefs.setBoolPref("browser.uitour.enabled", true);
|
Services.prefs.setBoolPref("browser.uitour.enabled", true);
|
||||||
|
let testUri = Services.io.newURI("http://example.com", null, null);
|
||||||
|
Services.perms.add(testUri, "uitour", Services.perms.ALLOW_ACTION);
|
||||||
|
|
||||||
waitForExplicitFinish();
|
waitForExplicitFinish();
|
||||||
|
|
||||||
@ -65,6 +66,7 @@ function test() {
|
|||||||
gBrowser.removeTab(gTestTab);
|
gBrowser.removeTab(gTestTab);
|
||||||
delete window.gTestTab;
|
delete window.gTestTab;
|
||||||
Services.prefs.clearUserPref("browser.uitour.enabled", true);
|
Services.prefs.clearUserPref("browser.uitour.enabled", true);
|
||||||
|
Services.perms.remove("example.com", "uitour");
|
||||||
});
|
});
|
||||||
|
|
||||||
function done() {
|
function done() {
|
||||||
@ -98,6 +100,41 @@ function test() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let tests = [
|
let tests = [
|
||||||
|
function test_untrusted_host(done) {
|
||||||
|
loadTestPage(function() {
|
||||||
|
let highlight = document.getElementById("UITourHighlight");
|
||||||
|
is_element_hidden(highlight, "Highlight should initially be hidden");
|
||||||
|
|
||||||
|
gContentAPI.showHighlight("urlbar");
|
||||||
|
is_element_hidden(highlight, "Highlight should not be shown on a untrusted host");
|
||||||
|
|
||||||
|
done();
|
||||||
|
}, "http://mochi.test:8888/");
|
||||||
|
},
|
||||||
|
function test_unsecure_host(done) {
|
||||||
|
loadTestPage(function() {
|
||||||
|
let highlight = document.getElementById("UITourHighlight");
|
||||||
|
is_element_hidden(highlight, "Highlight should initially be hidden");
|
||||||
|
|
||||||
|
gContentAPI.showHighlight("urlbar");
|
||||||
|
is_element_hidden(highlight, "Highlight should not be shown on a unsecure host");
|
||||||
|
|
||||||
|
done();
|
||||||
|
}, "http://example.com/");
|
||||||
|
},
|
||||||
|
function test_unsecure_host_override(done) {
|
||||||
|
Services.prefs.setBoolPref("browser.uitour.requireSecure", false);
|
||||||
|
loadTestPage(function() {
|
||||||
|
let highlight = document.getElementById("UITourHighlight");
|
||||||
|
is_element_hidden(highlight, "Highlight should initially be hidden");
|
||||||
|
|
||||||
|
gContentAPI.showHighlight("urlbar");
|
||||||
|
is_element_visible(highlight, "Highlight should be shown on a unsecure host when override pref is set");
|
||||||
|
|
||||||
|
Services.prefs.setBoolPref("browser.uitour.requireSecure", true);
|
||||||
|
done();
|
||||||
|
}, "http://example.com/");
|
||||||
|
},
|
||||||
function test_disabled(done) {
|
function test_disabled(done) {
|
||||||
Services.prefs.setBoolPref("browser.uitour.enabled", false);
|
Services.prefs.setBoolPref("browser.uitour.enabled", false);
|
||||||
|
|
||||||
@ -110,17 +147,6 @@ let tests = [
|
|||||||
Services.prefs.setBoolPref("browser.uitour.enabled", true);
|
Services.prefs.setBoolPref("browser.uitour.enabled", true);
|
||||||
done();
|
done();
|
||||||
},
|
},
|
||||||
function test_untrusted_host(done) {
|
|
||||||
loadTestPage(function() {
|
|
||||||
let highlight = document.getElementById("UITourHighlight");
|
|
||||||
is_element_hidden(highlight, "Highlight should initially be hidden");
|
|
||||||
|
|
||||||
gContentAPI.showHighlight("urlbar");
|
|
||||||
is_element_hidden(highlight, "Highlight should not be shown on a untrusted domain");
|
|
||||||
|
|
||||||
done();
|
|
||||||
}, true);
|
|
||||||
},
|
|
||||||
function test_highlight(done) {
|
function test_highlight(done) {
|
||||||
let highlight = document.getElementById("UITourHighlight");
|
let highlight = document.getElementById("UITourHighlight");
|
||||||
is_element_hidden(highlight, "Highlight should initially be hidden");
|
is_element_hidden(highlight, "Highlight should initially be hidden");
|
||||||
|
BIN
browser/themes/linux/devtools/orion-error.png
Normal file
BIN
browser/themes/linux/devtools/orion-error.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.7 KiB |
@ -105,7 +105,7 @@ browser.jar:
|
|||||||
skin/classic/browser/preferences/Options-sync.png (preferences/Options-sync.png)
|
skin/classic/browser/preferences/Options-sync.png (preferences/Options-sync.png)
|
||||||
#endif
|
#endif
|
||||||
* skin/classic/browser/preferences/preferences.css (preferences/preferences.css)
|
* skin/classic/browser/preferences/preferences.css (preferences/preferences.css)
|
||||||
skin/classic/browser/preferences/in-content/preferences.css (preferences/in-content/preferences.css)
|
* skin/classic/browser/preferences/in-content/preferences.css (preferences/in-content/preferences.css)
|
||||||
skin/classic/browser/preferences/applications.css (preferences/applications.css)
|
skin/classic/browser/preferences/applications.css (preferences/applications.css)
|
||||||
skin/classic/browser/preferences/aboutPermissions.css (preferences/aboutPermissions.css)
|
skin/classic/browser/preferences/aboutPermissions.css (preferences/aboutPermissions.css)
|
||||||
skin/classic/browser/social/services-16.png (social/services-16.png)
|
skin/classic/browser/social/services-16.png (social/services-16.png)
|
||||||
@ -143,6 +143,7 @@ browser.jar:
|
|||||||
skin/classic/browser/devtools/orion.css (devtools/orion.css)
|
skin/classic/browser/devtools/orion.css (devtools/orion.css)
|
||||||
skin/classic/browser/devtools/orion-container.css (devtools/orion-container.css)
|
skin/classic/browser/devtools/orion-container.css (devtools/orion-container.css)
|
||||||
skin/classic/browser/devtools/orion-task.png (devtools/orion-task.png)
|
skin/classic/browser/devtools/orion-task.png (devtools/orion-task.png)
|
||||||
|
skin/classic/browser/devtools/orion-error.png (devtools/orion-error.png)
|
||||||
skin/classic/browser/devtools/orion-breakpoint.png (devtools/orion-breakpoint.png)
|
skin/classic/browser/devtools/orion-breakpoint.png (devtools/orion-breakpoint.png)
|
||||||
skin/classic/browser/devtools/orion-debug-location.png (devtools/orion-debug-location.png)
|
skin/classic/browser/devtools/orion-debug-location.png (devtools/orion-debug-location.png)
|
||||||
skin/classic/browser/devtools/breadcrumbs-scrollbutton.png (devtools/breadcrumbs-scrollbutton.png)
|
skin/classic/browser/devtools/breadcrumbs-scrollbutton.png (devtools/breadcrumbs-scrollbutton.png)
|
||||||
|
@ -21,12 +21,12 @@
|
|||||||
-moz-margin-end: 3px;
|
-moz-margin-end: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
richlistitem label {
|
#handlersView > richlistitem label {
|
||||||
-moz-margin-start: 1px;
|
-moz-margin-start: 1px;
|
||||||
margin-top: 2px;
|
margin-top: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
richlistitem {
|
#handlersView > richlistitem {
|
||||||
min-height: 25px;
|
min-height: 25px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,95 +6,115 @@
|
|||||||
|
|
||||||
@namespace html "http://www.w3.org/1999/xhtml";
|
@namespace html "http://www.w3.org/1999/xhtml";
|
||||||
|
|
||||||
#preferences-home {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
#header {
|
#header {
|
||||||
margin-bottom: 18px;
|
margin-bottom: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.landingButton {
|
|
||||||
-moz-box-align: center;
|
|
||||||
-moz-box-orient: vertical;
|
|
||||||
}
|
|
||||||
|
|
||||||
.landingButton:hover {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.landingButton-label {
|
|
||||||
margin-top: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.landingButton-icon {
|
|
||||||
display: block;
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
background-image: url("chrome://browser/skin/preferences/Options.png");
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preference-icon {
|
|
||||||
display: block;
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
background-image: url("chrome://browser/skin/preferences/Options.png");
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
margin: 0 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preference-icon[type="general"],
|
|
||||||
.landingButton-icon[type="general"] {
|
|
||||||
background-position: 0 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preference-icon[type="content"],
|
|
||||||
.landingButton-icon[type="content"] {
|
|
||||||
background-position: -64px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preference-icon[type="applications"],
|
|
||||||
.landingButton-icon[type="applications"] {
|
|
||||||
background-position: -96px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preference-icon[type="privacy"],
|
|
||||||
.landingButton-icon[type="privacy"] {
|
|
||||||
background-position: -128px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preference-icon[type="security"],
|
|
||||||
.landingButton-icon[type="security"] {
|
|
||||||
background-position: -160px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preference-icon[type="advanced"],
|
|
||||||
.landingButton-icon[type="advanced"] {
|
|
||||||
background-position: -192px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preference-icon[type="sync"],
|
|
||||||
.landingButton-icon[type="sync"] {
|
|
||||||
background-image: url("chrome://browser/skin/preferences/Options-sync.png");
|
|
||||||
}
|
|
||||||
|
|
||||||
caption {
|
caption {
|
||||||
font-size: 20px;
|
font-size: 1.667rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.heading {
|
.main-content {
|
||||||
height: 50px;
|
max-width: 800px;
|
||||||
background-color: rgba(192,199,210,0.7);
|
|
||||||
border-radius: 5px 5px 0 0;
|
|
||||||
margin-bottom: 15px;
|
|
||||||
-moz-box-align: center;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
prefpane > .content-box {
|
prefpane > .content-box {
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Category List */
|
||||||
|
|
||||||
|
#categories {
|
||||||
|
-moz-appearance: none;
|
||||||
|
border: none;
|
||||||
|
-moz-margin-end: -1px;
|
||||||
|
background-color: transparent;
|
||||||
|
position: relative;
|
||||||
|
margin-top: 41px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.category {
|
||||||
|
-moz-appearance: none;
|
||||||
|
border-width: 1px;
|
||||||
|
-moz-border-end-width: 0;
|
||||||
|
border-style: solid;
|
||||||
|
border-color: transparent;
|
||||||
|
padding: 9px 4px 10px;
|
||||||
|
-moz-padding-end: 8px;
|
||||||
|
-moz-box-align: center;
|
||||||
|
overflow: hidden;
|
||||||
|
min-height: 0;
|
||||||
|
color: WindowText;
|
||||||
|
height: 52px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.category:-moz-locale-dir(ltr) {
|
||||||
|
border-top-left-radius: 5px;
|
||||||
|
border-bottom-left-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.category:-moz-locale-dir(rtl) {
|
||||||
|
border-top-right-radius: 5px;
|
||||||
|
border-bottom-right-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.category[selected] {
|
||||||
|
background-color: -moz-Field;
|
||||||
|
color: -moz-FieldText;
|
||||||
|
border-color: ThreeDShadow;
|
||||||
|
}
|
||||||
|
|
||||||
|
.category-name {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
-moz-padding-end: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Maximize the size of the viewport when the window is small */
|
||||||
|
@media (max-width: 800px) {
|
||||||
|
.category-name {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.category-icon {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
margin: 0 6px;
|
||||||
|
-moz-margin-start: 6px;
|
||||||
|
-moz-margin-end: 5px;
|
||||||
|
list-style-image: url("chrome://browser/skin/preferences/Options.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
#category-general > .category-icon {
|
||||||
|
-moz-image-region: rect(0, 32px, 32px, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#category-content > .category-icon {
|
||||||
|
-moz-image-region: rect(0, 96px, 32px, 64px)
|
||||||
|
}
|
||||||
|
|
||||||
|
#category-application > .category-icon {
|
||||||
|
-moz-image-region: rect(0, 128px, 32px, 96px)
|
||||||
|
}
|
||||||
|
|
||||||
|
#category-privacy > .category-icon {
|
||||||
|
-moz-image-region: rect(0, 160px, 32px, 128px)
|
||||||
|
}
|
||||||
|
|
||||||
|
#category-security > .category-icon {
|
||||||
|
-moz-image-region: rect(0, 192px, 32px, 160px)
|
||||||
|
}
|
||||||
|
|
||||||
|
#category-advanced > .category-icon {
|
||||||
|
-moz-image-region: rect(0, 224px, 32px, 192px)
|
||||||
|
}
|
||||||
|
|
||||||
|
%ifdef MOZ_SERVICES_SYNC
|
||||||
|
#category-sync > .category-icon {
|
||||||
|
list-style-image: url("chrome://browser/skin/preferences/Options-sync.png");
|
||||||
|
}
|
||||||
|
%endif
|
||||||
|
|
||||||
/* Applications Pane Styles */
|
/* Applications Pane Styles */
|
||||||
|
|
||||||
#applications-content {
|
#applications-content {
|
||||||
|
BIN
browser/themes/osx/devtools/orion-error.png
Normal file
BIN
browser/themes/osx/devtools/orion-error.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.7 KiB |
@ -169,7 +169,7 @@ browser.jar:
|
|||||||
#endif
|
#endif
|
||||||
skin/classic/browser/preferences/saveFile.png (preferences/saveFile.png)
|
skin/classic/browser/preferences/saveFile.png (preferences/saveFile.png)
|
||||||
* skin/classic/browser/preferences/preferences.css (preferences/preferences.css)
|
* skin/classic/browser/preferences/preferences.css (preferences/preferences.css)
|
||||||
skin/classic/browser/preferences/in-content/preferences.css (preferences/in-content/preferences.css)
|
* skin/classic/browser/preferences/in-content/preferences.css (preferences/in-content/preferences.css)
|
||||||
skin/classic/browser/preferences/applications.css (preferences/applications.css)
|
skin/classic/browser/preferences/applications.css (preferences/applications.css)
|
||||||
skin/classic/browser/preferences/aboutPermissions.css (preferences/aboutPermissions.css)
|
skin/classic/browser/preferences/aboutPermissions.css (preferences/aboutPermissions.css)
|
||||||
skin/classic/browser/social/services-16.png (social/services-16.png)
|
skin/classic/browser/social/services-16.png (social/services-16.png)
|
||||||
@ -232,6 +232,7 @@ browser.jar:
|
|||||||
skin/classic/browser/devtools/orion.css (devtools/orion.css)
|
skin/classic/browser/devtools/orion.css (devtools/orion.css)
|
||||||
skin/classic/browser/devtools/orion-container.css (devtools/orion-container.css)
|
skin/classic/browser/devtools/orion-container.css (devtools/orion-container.css)
|
||||||
skin/classic/browser/devtools/orion-task.png (devtools/orion-task.png)
|
skin/classic/browser/devtools/orion-task.png (devtools/orion-task.png)
|
||||||
|
skin/classic/browser/devtools/orion-error.png (devtools/orion-error.png)
|
||||||
skin/classic/browser/devtools/orion-breakpoint.png (devtools/orion-breakpoint.png)
|
skin/classic/browser/devtools/orion-breakpoint.png (devtools/orion-breakpoint.png)
|
||||||
skin/classic/browser/devtools/orion-debug-location.png (devtools/orion-debug-location.png)
|
skin/classic/browser/devtools/orion-debug-location.png (devtools/orion-debug-location.png)
|
||||||
* skin/classic/browser/devtools/webconsole.css (devtools/webconsole.css)
|
* skin/classic/browser/devtools/webconsole.css (devtools/webconsole.css)
|
||||||
|
@ -14,12 +14,12 @@
|
|||||||
margin-bottom: -1px;
|
margin-bottom: -1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
richlistitem label {
|
#handlersView > richlistitem label {
|
||||||
-moz-margin-start: 3px;
|
-moz-margin-start: 3px;
|
||||||
margin-top: 2px;
|
margin-top: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
richlistitem {
|
#handlersView > richlistitem {
|
||||||
min-height: 22px;
|
min-height: 22px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,102 +2,119 @@
|
|||||||
- License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
- 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/. */
|
- You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
%include ../../shared.inc
|
||||||
|
|
||||||
@import url("chrome://global/skin/inContentUI.css");
|
@import url("chrome://global/skin/inContentUI.css");
|
||||||
|
|
||||||
@namespace html "http://www.w3.org/1999/xhtml";
|
@namespace html "http://www.w3.org/1999/xhtml";
|
||||||
|
|
||||||
#preferences-home {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
#header {
|
#header {
|
||||||
margin-bottom: 18px;
|
margin-bottom: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.landingButton {
|
|
||||||
-moz-box-align: center;
|
|
||||||
-moz-box-orient: vertical;
|
|
||||||
border: none;
|
|
||||||
background: none;
|
|
||||||
box-shadow: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.landingButton:hover {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.landingButton-label {
|
|
||||||
margin-top: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.landingButton-icon {
|
|
||||||
display: block;
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
background-image: url("chrome://browser/skin/preferences/Options.png");
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preference-icon {
|
|
||||||
display: block;
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
background-image: url("chrome://browser/skin/preferences/Options.png");
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
margin: 0 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preference-icon[type="general"],
|
|
||||||
.landingButton-icon[type="general"] {
|
|
||||||
background-position: 0 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preference-icon[type="content"],
|
|
||||||
.landingButton-icon[type="content"] {
|
|
||||||
background-position: -64px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preference-icon[type="applications"],
|
|
||||||
.landingButton-icon[type="applications"] {
|
|
||||||
background-position: -96px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preference-icon[type="privacy"],
|
|
||||||
.landingButton-icon[type="privacy"] {
|
|
||||||
background-position: -128px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preference-icon[type="security"],
|
|
||||||
.landingButton-icon[type="security"] {
|
|
||||||
background-position: -160px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preference-icon[type="advanced"],
|
|
||||||
.landingButton-icon[type="advanced"] {
|
|
||||||
background-position: -192px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preference-icon[type="sync"],
|
|
||||||
.landingButton-icon[type="sync"] {
|
|
||||||
background-image: url("chrome://browser/skin/preferences/Options-sync.png");
|
|
||||||
}
|
|
||||||
|
|
||||||
caption {
|
caption {
|
||||||
font-size: 20px;
|
font-size: 1.667rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.heading {
|
.main-content {
|
||||||
height: 50px;
|
max-width: 800px;
|
||||||
background-color: rgba(192,199,210,0.7);
|
|
||||||
border-radius: 5px 5px 0 0;
|
|
||||||
margin-bottom: 15px;
|
|
||||||
-moz-box-align: center;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
prefpane > .content-box {
|
prefpane > .content-box {
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Category List */
|
||||||
|
|
||||||
|
#categories {
|
||||||
|
-moz-appearance: none;
|
||||||
|
border: none;
|
||||||
|
-moz-margin-end: -1px;
|
||||||
|
background-color: transparent;
|
||||||
|
position: relative;
|
||||||
|
margin-top: 31px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.category {
|
||||||
|
-moz-appearance: none;
|
||||||
|
color: #252F3B;
|
||||||
|
border-width: 1px;
|
||||||
|
border-style: solid;
|
||||||
|
border-color: transparent;
|
||||||
|
padding: 10px 4px;
|
||||||
|
-moz-padding-end: 8px;
|
||||||
|
-moz-box-align: center;
|
||||||
|
overflow: hidden;
|
||||||
|
min-height: 0;
|
||||||
|
height: 52px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.category:-moz-locale-dir(ltr) {
|
||||||
|
border-top-left-radius: 5px;
|
||||||
|
border-bottom-left-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.category:-moz-locale-dir(rtl) {
|
||||||
|
border-top-right-radius: 5px;
|
||||||
|
border-bottom-right-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.category[selected] {
|
||||||
|
background-color: rgba(255, 255, 255, 0.35);
|
||||||
|
color: -moz-dialogtext;
|
||||||
|
border-color: rgba(50, 65, 92, 0.4);
|
||||||
|
-moz-border-end-color: #C9CFD7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.category-name {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
-moz-padding-end: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Maximize the size of the viewport when the window is small */
|
||||||
|
@media (max-width: 800px) {
|
||||||
|
.category-name {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.category-icon {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
-moz-margin-start: 6px;
|
||||||
|
list-style-image: url("chrome://browser/skin/preferences/Options.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
#category-general > .category-icon {
|
||||||
|
-moz-image-region: rect(0, 32px, 32px, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#category-content > .category-icon {
|
||||||
|
-moz-image-region: rect(0, 96px, 32px, 64px)
|
||||||
|
}
|
||||||
|
|
||||||
|
#category-application > .category-icon {
|
||||||
|
-moz-image-region: rect(0, 128px, 32px, 96px)
|
||||||
|
}
|
||||||
|
|
||||||
|
#category-privacy > .category-icon {
|
||||||
|
-moz-image-region: rect(0, 160px, 32px, 128px)
|
||||||
|
}
|
||||||
|
|
||||||
|
#category-security > .category-icon {
|
||||||
|
-moz-image-region: rect(0, 192px, 32px, 160px)
|
||||||
|
}
|
||||||
|
|
||||||
|
#category-advanced > .category-icon {
|
||||||
|
-moz-image-region: rect(0, 224px, 32px, 192px)
|
||||||
|
}
|
||||||
|
|
||||||
|
%ifdef MOZ_SERVICES_SYNC
|
||||||
|
#category-sync > .category-icon {
|
||||||
|
list-style-image: url("chrome://browser/skin/preferences/Options-sync.png");
|
||||||
|
}
|
||||||
|
%endif
|
||||||
|
|
||||||
/* Applications Pane Styles */
|
/* Applications Pane Styles */
|
||||||
|
|
||||||
#applications-content {
|
#applications-content {
|
||||||
|
@ -121,11 +121,29 @@
|
|||||||
background: #eee;
|
background: #eee;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.devtools-tooltip.devtools-tooltip-panel .panel-arrowcontent {
|
.devtools-tooltip.devtools-tooltip-panel .panel-arrowcontent {
|
||||||
/* If the tooltip uses a <panel> XUL element instead */
|
/* If the tooltip uses a <panel> XUL element instead */
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.devtools-tooltip-simple-text {
|
||||||
|
background: linear-gradient(1deg, transparent 0%, rgba(94,136,176,0.1) 100%);
|
||||||
|
max-width: 400px;
|
||||||
|
margin: 0 -4px; /* Compensate for the .panel-arrowcontent padding. */
|
||||||
|
padding: 8px 12px;
|
||||||
|
text-shadow: 0 1px 0 #fff;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.devtools-tooltip-simple-text:first-child {
|
||||||
|
margin-top: -4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.devtools-tooltip-simple-text:last-child {
|
||||||
|
margin-bottom: -4px;
|
||||||
|
}
|
||||||
|
|
||||||
.devtools-tooltip-tiles {
|
.devtools-tooltip-tiles {
|
||||||
background-color: #eee;
|
background-color: #eee;
|
||||||
background-image: linear-gradient(45deg, #ccc 25%, transparent 25%, transparent 75%, #ccc 75%, #ccc),
|
background-image: linear-gradient(45deg, #ccc 25%, transparent 25%, transparent 75%, #ccc 75%, #ccc),
|
||||||
|
BIN
browser/themes/windows/devtools/orion-error.png
Normal file
BIN
browser/themes/windows/devtools/orion-error.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.7 KiB |
@ -125,7 +125,7 @@ browser.jar:
|
|||||||
#endif
|
#endif
|
||||||
skin/classic/browser/preferences/saveFile.png (preferences/saveFile.png)
|
skin/classic/browser/preferences/saveFile.png (preferences/saveFile.png)
|
||||||
* skin/classic/browser/preferences/preferences.css (preferences/preferences.css)
|
* skin/classic/browser/preferences/preferences.css (preferences/preferences.css)
|
||||||
skin/classic/browser/preferences/in-content/preferences.css (preferences/in-content/preferences.css)
|
* skin/classic/browser/preferences/in-content/preferences.css (preferences/in-content/preferences.css)
|
||||||
skin/classic/browser/preferences/applications.css (preferences/applications.css)
|
skin/classic/browser/preferences/applications.css (preferences/applications.css)
|
||||||
skin/classic/browser/preferences/aboutPermissions.css (preferences/aboutPermissions.css)
|
skin/classic/browser/preferences/aboutPermissions.css (preferences/aboutPermissions.css)
|
||||||
skin/classic/browser/social/services-16.png (social/services-16.png)
|
skin/classic/browser/social/services-16.png (social/services-16.png)
|
||||||
@ -167,6 +167,7 @@ browser.jar:
|
|||||||
skin/classic/browser/devtools/orion.css (devtools/orion.css)
|
skin/classic/browser/devtools/orion.css (devtools/orion.css)
|
||||||
skin/classic/browser/devtools/orion-container.css (devtools/orion-container.css)
|
skin/classic/browser/devtools/orion-container.css (devtools/orion-container.css)
|
||||||
skin/classic/browser/devtools/orion-task.png (devtools/orion-task.png)
|
skin/classic/browser/devtools/orion-task.png (devtools/orion-task.png)
|
||||||
|
skin/classic/browser/devtools/orion-error.png (devtools/orion-error.png)
|
||||||
skin/classic/browser/devtools/orion-breakpoint.png (devtools/orion-breakpoint.png)
|
skin/classic/browser/devtools/orion-breakpoint.png (devtools/orion-breakpoint.png)
|
||||||
skin/classic/browser/devtools/orion-debug-location.png (devtools/orion-debug-location.png)
|
skin/classic/browser/devtools/orion-debug-location.png (devtools/orion-debug-location.png)
|
||||||
* skin/classic/browser/devtools/webconsole.css (devtools/webconsole.css)
|
* skin/classic/browser/devtools/webconsole.css (devtools/webconsole.css)
|
||||||
@ -402,7 +403,7 @@ browser.jar:
|
|||||||
#endif
|
#endif
|
||||||
skin/classic/aero/browser/preferences/saveFile.png (preferences/saveFile-aero.png)
|
skin/classic/aero/browser/preferences/saveFile.png (preferences/saveFile-aero.png)
|
||||||
* skin/classic/aero/browser/preferences/preferences.css (preferences/preferences.css)
|
* skin/classic/aero/browser/preferences/preferences.css (preferences/preferences.css)
|
||||||
skin/classic/aero/browser/preferences/in-content/preferences.css (preferences/in-content/preferences.css)
|
* skin/classic/aero/browser/preferences/in-content/preferences.css (preferences/in-content/preferences.css)
|
||||||
skin/classic/aero/browser/preferences/applications.css (preferences/applications.css)
|
skin/classic/aero/browser/preferences/applications.css (preferences/applications.css)
|
||||||
skin/classic/aero/browser/preferences/aboutPermissions.css (preferences/aboutPermissions.css)
|
skin/classic/aero/browser/preferences/aboutPermissions.css (preferences/aboutPermissions.css)
|
||||||
skin/classic/aero/browser/social/services-16.png (social/services-16.png)
|
skin/classic/aero/browser/social/services-16.png (social/services-16.png)
|
||||||
@ -444,6 +445,7 @@ browser.jar:
|
|||||||
skin/classic/aero/browser/devtools/orion.css (devtools/orion.css)
|
skin/classic/aero/browser/devtools/orion.css (devtools/orion.css)
|
||||||
skin/classic/aero/browser/devtools/orion-container.css (devtools/orion-container.css)
|
skin/classic/aero/browser/devtools/orion-container.css (devtools/orion-container.css)
|
||||||
skin/classic/aero/browser/devtools/orion-task.png (devtools/orion-task.png)
|
skin/classic/aero/browser/devtools/orion-task.png (devtools/orion-task.png)
|
||||||
|
skin/classic/aero/browser/devtools/orion-error.png (devtools/orion-error.png)
|
||||||
skin/classic/aero/browser/devtools/orion-breakpoint.png (devtools/orion-breakpoint.png)
|
skin/classic/aero/browser/devtools/orion-breakpoint.png (devtools/orion-breakpoint.png)
|
||||||
skin/classic/aero/browser/devtools/orion-debug-location.png (devtools/orion-debug-location.png)
|
skin/classic/aero/browser/devtools/orion-debug-location.png (devtools/orion-debug-location.png)
|
||||||
* skin/classic/aero/browser/devtools/webconsole.css (devtools/webconsole.css)
|
* skin/classic/aero/browser/devtools/webconsole.css (devtools/webconsole.css)
|
||||||
|
@ -21,12 +21,12 @@
|
|||||||
-moz-margin-end: 3px;
|
-moz-margin-end: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
richlistitem label {
|
#handlersView > richlistitem label {
|
||||||
-moz-margin-start: 1px;
|
-moz-margin-start: 1px;
|
||||||
margin-top: 2px;
|
margin-top: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
richlistitem {
|
#handlersView > richlistitem {
|
||||||
min-height: 22px;
|
min-height: 22px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,98 +6,116 @@
|
|||||||
|
|
||||||
@namespace html "http://www.w3.org/1999/xhtml";
|
@namespace html "http://www.w3.org/1999/xhtml";
|
||||||
|
|
||||||
#preferences-home {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
#header {
|
#header {
|
||||||
margin-bottom: 18px;
|
margin-bottom: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.landingButton {
|
|
||||||
-moz-box-align: center;
|
|
||||||
-moz-box-orient: vertical;
|
|
||||||
border: none;
|
|
||||||
background: none;
|
|
||||||
box-shadow: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.landingButton:hover {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.landingButton-label {
|
|
||||||
margin-top: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.landingButton-icon {
|
|
||||||
display: block;
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
background-image: url("chrome://browser/skin/preferences/Options.png");
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preference-icon {
|
|
||||||
display: block;
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
background-image: url("chrome://browser/skin/preferences/Options.png");
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
margin: 0 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preference-icon[type="general"],
|
|
||||||
.landingButton-icon[type="general"] {
|
|
||||||
background-position: 0 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preference-icon[type="content"],
|
|
||||||
.landingButton-icon[type="content"] {
|
|
||||||
background-position: -64px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preference-icon[type="applications"],
|
|
||||||
.landingButton-icon[type="applications"] {
|
|
||||||
background-position: -96px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preference-icon[type="privacy"],
|
|
||||||
.landingButton-icon[type="privacy"] {
|
|
||||||
background-position: -128px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preference-icon[type="security"],
|
|
||||||
.landingButton-icon[type="security"] {
|
|
||||||
background-position: -160px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preference-icon[type="advanced"],
|
|
||||||
.landingButton-icon[type="advanced"] {
|
|
||||||
background-position: -192px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preference-icon[type="sync"],
|
|
||||||
.landingButton-icon[type="sync"] {
|
|
||||||
background-image: url("chrome://browser/skin/preferences/Options-sync.png");
|
|
||||||
}
|
|
||||||
|
|
||||||
caption {
|
caption {
|
||||||
font-size: 20px;
|
font-size: 1.667rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.heading {
|
.main-content {
|
||||||
height: 50px;
|
max-width: 800px;
|
||||||
background-color: rgba(192,199,210,0.7);
|
|
||||||
border-radius: 5px 5px 0 0;
|
|
||||||
margin-bottom: 15px;
|
|
||||||
-moz-box-align: center;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
prefpane > .content-box {
|
prefpane > .content-box {
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Category List */
|
||||||
|
|
||||||
|
#categories {
|
||||||
|
-moz-appearance: none;
|
||||||
|
border: none;
|
||||||
|
-moz-margin-end: -1px;
|
||||||
|
background-color: transparent;
|
||||||
|
position: relative;
|
||||||
|
margin-top: 31px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.category {
|
||||||
|
-moz-appearance: none;
|
||||||
|
background-color: transparent;
|
||||||
|
color: #252F3B;
|
||||||
|
padding: 10px 4px;
|
||||||
|
border-width: 1px;
|
||||||
|
border-style: solid;
|
||||||
|
border-color: transparent;
|
||||||
|
-moz-padding-end: 8px;
|
||||||
|
-moz-box-align: center;
|
||||||
|
overflow: hidden;
|
||||||
|
min-height: 0;
|
||||||
|
height: 52px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.category:-moz-locale-dir(ltr) {
|
||||||
|
border-top-left-radius: 5px;
|
||||||
|
border-bottom-left-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.category:-moz-locale-dir(rtl) {
|
||||||
|
border-top-right-radius: 5px;
|
||||||
|
border-bottom-right-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.category[selected] {
|
||||||
|
background-color: rgba(255, 255, 255, 0.4);
|
||||||
|
color: #252F3B;
|
||||||
|
border-color: #C3CEDF;
|
||||||
|
-moz-border-end-color: #E2E9F2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.category-name {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
-moz-padding-end: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Maximize the size of the viewport when the window is small */
|
||||||
|
@media (max-width: 800px) {
|
||||||
|
.category-name {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.category-icon {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
margin: 0 6px;
|
||||||
|
-moz-margin-start: 6px;
|
||||||
|
-moz-margin-end: 5px;
|
||||||
|
list-style-image: url("chrome://browser/skin/preferences/Options.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
#category-general > .category-icon {
|
||||||
|
-moz-image-region: rect(0, 32px, 32px, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#category-content > .category-icon {
|
||||||
|
-moz-image-region: rect(0, 96px, 32px, 64px)
|
||||||
|
}
|
||||||
|
|
||||||
|
#category-application > .category-icon {
|
||||||
|
-moz-image-region: rect(0, 128px, 32px, 96px)
|
||||||
|
}
|
||||||
|
|
||||||
|
#category-privacy > .category-icon {
|
||||||
|
-moz-image-region: rect(0, 160px, 32px, 128px)
|
||||||
|
}
|
||||||
|
|
||||||
|
#category-security > .category-icon {
|
||||||
|
-moz-image-region: rect(0, 192px, 32px, 160px)
|
||||||
|
}
|
||||||
|
|
||||||
|
#category-advanced > .category-icon {
|
||||||
|
-moz-image-region: rect(0, 224px, 32px, 192px)
|
||||||
|
}
|
||||||
|
|
||||||
|
%ifdef MOZ_SERVICES_SYNC
|
||||||
|
#category-sync > .category-icon {
|
||||||
|
list-style-image: url("chrome://browser/skin/preferences/Options-sync.png");
|
||||||
|
}
|
||||||
|
%endif
|
||||||
|
|
||||||
/* Applications Pane Styles */
|
/* Applications Pane Styles */
|
||||||
|
|
||||||
#applications-content {
|
#applications-content {
|
||||||
|
@ -215,6 +215,8 @@
|
|||||||
#include "mozilla/dom/XPathEvaluator.h"
|
#include "mozilla/dom/XPathEvaluator.h"
|
||||||
#include "nsIDocumentEncoder.h"
|
#include "nsIDocumentEncoder.h"
|
||||||
#include "nsIStructuredCloneContainer.h"
|
#include "nsIStructuredCloneContainer.h"
|
||||||
|
#include "nsIMutableArray.h"
|
||||||
|
#include "nsContentPermissionHelper.h"
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
using namespace mozilla::dom;
|
using namespace mozilla::dom;
|
||||||
@ -10647,17 +10649,11 @@ NS_IMPL_ISUPPORTS_INHERITED1(nsPointerLockPermissionRequest,
|
|||||||
nsIContentPermissionRequest)
|
nsIContentPermissionRequest)
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsPointerLockPermissionRequest::GetType(nsACString& aType)
|
nsPointerLockPermissionRequest::GetTypes(nsIArray** aTypes)
|
||||||
{
|
{
|
||||||
aType = "pointerLock";
|
return CreatePermissionArray(NS_LITERAL_CSTRING("pointerLock"),
|
||||||
return NS_OK;
|
NS_LITERAL_CSTRING("unused"),
|
||||||
}
|
aTypes);
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsPointerLockPermissionRequest::GetAccess(nsACString& aAccess)
|
|
||||||
{
|
|
||||||
aAccess = "unused";
|
|
||||||
return NS_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
|
@ -116,20 +116,21 @@ MOCHITEST_FILES = \
|
|||||||
test_volume.html \
|
test_volume.html \
|
||||||
test_video_to_canvas.html \
|
test_video_to_canvas.html \
|
||||||
test_audiowrite.html \
|
test_audiowrite.html \
|
||||||
test_mediarecorder_creation.html \
|
|
||||||
test_mediarecorder_avoid_recursion.html \
|
test_mediarecorder_avoid_recursion.html \
|
||||||
test_mediarecorder_record_timeslice.html \
|
test_mediarecorder_creation.html \
|
||||||
test_mediarecorder_record_audiocontext.html \
|
test_mediarecorder_record_audiocontext.html \
|
||||||
test_mediarecorder_record_stopms.html \
|
test_mediarecorder_record_immediate_stop.html \
|
||||||
|
test_mediarecorder_record_no_timeslice.html \
|
||||||
test_mediarecorder_record_nosrc.html \
|
test_mediarecorder_record_nosrc.html \
|
||||||
|
test_mediarecorder_record_session.html \
|
||||||
|
test_mediarecorder_record_stopms.html \
|
||||||
|
test_mediarecorder_record_timeslice.html \
|
||||||
|
test_mediarecorder_reload_crash.html \
|
||||||
|
test_mediarecorder_state_transition.html \
|
||||||
test_mozHasAudio.html \
|
test_mozHasAudio.html \
|
||||||
test_source_media.html \
|
test_source_media.html \
|
||||||
test_autoplay_contentEditable.html \
|
test_autoplay_contentEditable.html \
|
||||||
test_decoder_disable.html \
|
test_decoder_disable.html \
|
||||||
test_mediarecorder_record_no_timeslice.html \
|
|
||||||
test_mediarecorder_reload_crash.html \
|
|
||||||
test_mediarecorder_record_immediate_stop.html \
|
|
||||||
test_mediarecorder_record_session.html \
|
|
||||||
test_playback.html \
|
test_playback.html \
|
||||||
test_seekLies.html \
|
test_seekLies.html \
|
||||||
test_media_sniffer.html \
|
test_media_sniffer.html \
|
||||||
|
170
content/media/test/test_mediarecorder_state_transition.html
Normal file
170
content/media/test/test_mediarecorder_state_transition.html
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Test MediaRecorder State Transition</title>
|
||||||
|
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||||
|
<script type="text/javascript" src="manifest.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<pre id="test">
|
||||||
|
<script class="testbody" type="text/javascript">
|
||||||
|
var manager = new MediaTestManager;
|
||||||
|
|
||||||
|
// List of operation tests for media recorder objects to verify if running
|
||||||
|
// these operations should result in an exception or not
|
||||||
|
var operationTests = [
|
||||||
|
{
|
||||||
|
operations: ['stop'],
|
||||||
|
isValid: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
operations: ['requestData'],
|
||||||
|
isValid: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
operations: ['pause'],
|
||||||
|
isValid: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
operations: ['resume'],
|
||||||
|
isValid: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
operations: ['start'],
|
||||||
|
isValid: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
operations: ['start'],
|
||||||
|
isValid: true,
|
||||||
|
timeSlice: 200
|
||||||
|
},
|
||||||
|
{
|
||||||
|
operations: ['start', 'pause'],
|
||||||
|
isValid: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
operations: ['start', 'pause'],
|
||||||
|
isValid: true,
|
||||||
|
timeSlice: 200
|
||||||
|
},
|
||||||
|
{
|
||||||
|
operations: ['start', 'start'],
|
||||||
|
isValid: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
operations: ['start', 'resume'],
|
||||||
|
isValid: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
operations: ['start', 'stop'],
|
||||||
|
isValid: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
operations: ['start', 'stop'],
|
||||||
|
isValid: true,
|
||||||
|
timeSlice: 200
|
||||||
|
},
|
||||||
|
{
|
||||||
|
operations: ['start', 'requestData'],
|
||||||
|
isValid: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
operations: ['start', 'requestData'],
|
||||||
|
isValid: true,
|
||||||
|
timeSlice: 200
|
||||||
|
},
|
||||||
|
{
|
||||||
|
operations: ['start', 'pause', 'stop'],
|
||||||
|
isValid: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
operations: ['start', 'pause', 'start'],
|
||||||
|
isValid: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
operations: ['start', 'pause', 'pause'],
|
||||||
|
isValid: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
operations: ['start', 'pause', 'requestData'],
|
||||||
|
isValid: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
operations: ['start', 'pause', 'resume'],
|
||||||
|
isValid: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
operations: ['start', 'pause', 'resume'],
|
||||||
|
isValid: true,
|
||||||
|
timeSlice: 200
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs through each available state transition test by running all
|
||||||
|
* available operations on a media recorder object. Then, we report
|
||||||
|
* back if the test was expected through an exception or not.
|
||||||
|
*
|
||||||
|
* @param {MediaStream} testStream the media stream used for media recorder
|
||||||
|
* operation tests
|
||||||
|
*/
|
||||||
|
function runStateTransitionTests(testStream) {
|
||||||
|
for (operationTest of operationTests) {
|
||||||
|
var mediaRecorder = new MediaRecorder(testStream);
|
||||||
|
var operationsString = operationTest.operations.toString();
|
||||||
|
|
||||||
|
try {
|
||||||
|
for (operation of operationTest.operations) {
|
||||||
|
if (operationTest.timeSlice && operation === 'start') {
|
||||||
|
operationsString += ' with timeslice ' + operationTest.timeSlice;
|
||||||
|
mediaRecorder[operation](operationTest.timeSlice);
|
||||||
|
} else {
|
||||||
|
mediaRecorder[operation]();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (operationTest.isValid) {
|
||||||
|
ok(true, 'Successful transitions for ' + operationsString);
|
||||||
|
} else {
|
||||||
|
ok(false, 'Failed transitions for ' + operationsString);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
if (!operationTest.isValid && err.name === 'InvalidStateError') {
|
||||||
|
ok(true, 'InvalidStateError fired for ' + operationsString);
|
||||||
|
} else {
|
||||||
|
ok(false, 'No InvalidStateError for ' + operationsString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts a test on every media recorder file included to check that various
|
||||||
|
* state transition flows that can happen in the media recorder object throw
|
||||||
|
* exceptions when they are expected to and vice versa.
|
||||||
|
*/
|
||||||
|
function startTest(test, token) {
|
||||||
|
var element = document.createElement('audio');
|
||||||
|
var expectedMimeType = test.type.substring(0, test.type.indexOf(';'));
|
||||||
|
|
||||||
|
element.token = token;
|
||||||
|
manager.started(token);
|
||||||
|
|
||||||
|
element.src = test.name;
|
||||||
|
element.test = test;
|
||||||
|
element.stream = element.mozCaptureStream();
|
||||||
|
|
||||||
|
element.oncanplaythrough = function () {
|
||||||
|
runStateTransitionTests(element.stream);
|
||||||
|
manager.finished(token);
|
||||||
|
};
|
||||||
|
|
||||||
|
element.play();
|
||||||
|
}
|
||||||
|
|
||||||
|
manager.runTests(gMediaRecorderTests, startTest);
|
||||||
|
</script>
|
||||||
|
</pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -302,6 +302,11 @@ this.PermissionsTable = { geolocation: {
|
|||||||
privileged: PROMPT_ACTION,
|
privileged: PROMPT_ACTION,
|
||||||
certified: PROMPT_ACTION
|
certified: PROMPT_ACTION
|
||||||
},
|
},
|
||||||
|
"video-capture": {
|
||||||
|
app: PROMPT_ACTION,
|
||||||
|
privileged: PROMPT_ACTION,
|
||||||
|
certified: PROMPT_ACTION
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2,19 +2,155 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include "nsContentPermissionHelper.h"
|
|
||||||
#include "nsIContentPermissionPrompt.h"
|
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
#include "nsIDOMElement.h"
|
#include "nsIDOMElement.h"
|
||||||
#include "nsIPrincipal.h"
|
#include "nsIPrincipal.h"
|
||||||
#include "mozilla/dom/Element.h"
|
#include "mozilla/dom/Element.h"
|
||||||
|
#include "mozilla/dom/PContentPermission.h"
|
||||||
|
#include "mozilla/dom/PermissionMessageUtils.h"
|
||||||
|
#include "mozilla/dom/PContentPermissionRequestParent.h"
|
||||||
#include "mozilla/dom/TabParent.h"
|
#include "mozilla/dom/TabParent.h"
|
||||||
#include "mozilla/unused.h"
|
#include "mozilla/unused.h"
|
||||||
#include "nsComponentManagerUtils.h"
|
#include "nsComponentManagerUtils.h"
|
||||||
|
#include "nsArrayUtils.h"
|
||||||
|
#include "nsIMutableArray.h"
|
||||||
|
#include "nsContentPermissionHelper.h"
|
||||||
|
|
||||||
using mozilla::unused; // <snicker>
|
using mozilla::unused; // <snicker>
|
||||||
using namespace mozilla::dom;
|
using namespace mozilla::dom;
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace dom {
|
||||||
|
|
||||||
|
class ContentPermissionRequestParent : public PContentPermissionRequestParent
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ContentPermissionRequestParent(const nsTArray<PermissionRequest>& aRequests,
|
||||||
|
Element* element,
|
||||||
|
const IPC::Principal& principal);
|
||||||
|
virtual ~ContentPermissionRequestParent();
|
||||||
|
|
||||||
|
bool IsBeingDestroyed();
|
||||||
|
|
||||||
|
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||||
|
nsCOMPtr<Element> mElement;
|
||||||
|
nsCOMPtr<nsContentPermissionRequestProxy> mProxy;
|
||||||
|
nsTArray<PermissionRequest> mRequests;
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual bool Recvprompt();
|
||||||
|
virtual void ActorDestroy(ActorDestroyReason why);
|
||||||
|
};
|
||||||
|
|
||||||
|
ContentPermissionRequestParent::ContentPermissionRequestParent(const nsTArray<PermissionRequest>& aRequests,
|
||||||
|
Element* aElement,
|
||||||
|
const IPC::Principal& aPrincipal)
|
||||||
|
{
|
||||||
|
MOZ_COUNT_CTOR(ContentPermissionRequestParent);
|
||||||
|
|
||||||
|
mPrincipal = aPrincipal;
|
||||||
|
mElement = aElement;
|
||||||
|
mRequests = aRequests;
|
||||||
|
}
|
||||||
|
|
||||||
|
ContentPermissionRequestParent::~ContentPermissionRequestParent()
|
||||||
|
{
|
||||||
|
MOZ_COUNT_DTOR(ContentPermissionRequestParent);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ContentPermissionRequestParent::Recvprompt()
|
||||||
|
{
|
||||||
|
mProxy = new nsContentPermissionRequestProxy();
|
||||||
|
NS_ASSERTION(mProxy, "Alloc of request proxy failed");
|
||||||
|
if (NS_FAILED(mProxy->Init(mRequests, this))) {
|
||||||
|
mProxy->Cancel();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ContentPermissionRequestParent::ActorDestroy(ActorDestroyReason why)
|
||||||
|
{
|
||||||
|
if (mProxy) {
|
||||||
|
mProxy->OnParentDestroyed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ContentPermissionRequestParent::IsBeingDestroyed()
|
||||||
|
{
|
||||||
|
// When TabParent::Destroy() is called, we are being destroyed. It's unsafe
|
||||||
|
// to send out any message now.
|
||||||
|
TabParent* tabParent = static_cast<TabParent*>(Manager());
|
||||||
|
return tabParent->IsDestroyed();
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMPL_ISUPPORTS1(ContentPermissionType, nsIContentPermissionType)
|
||||||
|
|
||||||
|
ContentPermissionType::ContentPermissionType(const nsACString& aType,
|
||||||
|
const nsACString& aAccess)
|
||||||
|
{
|
||||||
|
mType = aType;
|
||||||
|
mAccess = aAccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
ContentPermissionType::~ContentPermissionType()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
ContentPermissionType::GetType(nsACString& aType)
|
||||||
|
{
|
||||||
|
aType = mType;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
ContentPermissionType::GetAccess(nsACString& aAccess)
|
||||||
|
{
|
||||||
|
aAccess = mAccess;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
ConvertPermissionRequestToArray(nsTArray<PermissionRequest>& aSrcArray,
|
||||||
|
nsIMutableArray* aDesArray)
|
||||||
|
{
|
||||||
|
uint32_t len = aSrcArray.Length();
|
||||||
|
for (uint32_t i = 0; i < len; i++) {
|
||||||
|
nsRefPtr<ContentPermissionType> cpt =
|
||||||
|
new ContentPermissionType(aSrcArray[i].type(), aSrcArray[i].access());
|
||||||
|
aDesArray->AppendElement(cpt, false);
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
CreatePermissionArray(const nsACString& aType,
|
||||||
|
const nsACString& aAccess,
|
||||||
|
nsIArray** aTypesArray)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIMutableArray> types = do_CreateInstance(NS_ARRAY_CONTRACTID);
|
||||||
|
nsRefPtr<ContentPermissionType> permType = new ContentPermissionType(aType,
|
||||||
|
aAccess);
|
||||||
|
types->AppendElement(permType, false);
|
||||||
|
types.forget(aTypesArray);
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
PContentPermissionRequestParent*
|
||||||
|
CreateContentPermissionRequestParent(const nsTArray<PermissionRequest>& aRequests,
|
||||||
|
Element* element,
|
||||||
|
const IPC::Principal& principal)
|
||||||
|
{
|
||||||
|
return new ContentPermissionRequestParent(aRequests, element, principal);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace dom
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
nsContentPermissionRequestProxy::nsContentPermissionRequestProxy()
|
nsContentPermissionRequestProxy::nsContentPermissionRequestProxy()
|
||||||
{
|
{
|
||||||
MOZ_COUNT_CTOR(nsContentPermissionRequestProxy);
|
MOZ_COUNT_CTOR(nsContentPermissionRequestProxy);
|
||||||
@ -26,14 +162,12 @@ nsContentPermissionRequestProxy::~nsContentPermissionRequestProxy()
|
|||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsContentPermissionRequestProxy::Init(const nsACString & type,
|
nsContentPermissionRequestProxy::Init(const nsTArray<PermissionRequest>& requests,
|
||||||
const nsACString & access,
|
|
||||||
ContentPermissionRequestParent* parent)
|
ContentPermissionRequestParent* parent)
|
||||||
{
|
{
|
||||||
NS_ASSERTION(parent, "null parent");
|
NS_ASSERTION(parent, "null parent");
|
||||||
mParent = parent;
|
mParent = parent;
|
||||||
mType = type;
|
mPermissionRequests = requests;
|
||||||
mAccess = access;
|
|
||||||
|
|
||||||
nsCOMPtr<nsIContentPermissionPrompt> prompt = do_CreateInstance(NS_CONTENT_PERMISSION_PROMPT_CONTRACTID);
|
nsCOMPtr<nsIContentPermissionPrompt> prompt = do_CreateInstance(NS_CONTENT_PERMISSION_PROMPT_CONTRACTID);
|
||||||
if (!prompt) {
|
if (!prompt) {
|
||||||
@ -53,17 +187,14 @@ nsContentPermissionRequestProxy::OnParentDestroyed()
|
|||||||
NS_IMPL_ISUPPORTS1(nsContentPermissionRequestProxy, nsIContentPermissionRequest)
|
NS_IMPL_ISUPPORTS1(nsContentPermissionRequestProxy, nsIContentPermissionRequest)
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsContentPermissionRequestProxy::GetType(nsACString & aType)
|
nsContentPermissionRequestProxy::GetTypes(nsIArray** aTypes)
|
||||||
{
|
{
|
||||||
aType = mType;
|
nsCOMPtr<nsIMutableArray> types = do_CreateInstance(NS_ARRAY_CONTRACTID);
|
||||||
return NS_OK;
|
if (ConvertPermissionRequestToArray(mPermissionRequests, types)) {
|
||||||
}
|
types.forget(aTypes);
|
||||||
|
return NS_OK;
|
||||||
NS_IMETHODIMP
|
}
|
||||||
nsContentPermissionRequestProxy::GetAccess(nsACString & aAccess)
|
return NS_ERROR_FAILURE;
|
||||||
{
|
|
||||||
aAccess = mAccess;
|
|
||||||
return NS_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
@ -134,55 +265,3 @@ nsContentPermissionRequestProxy::Allow()
|
|||||||
mParent = nullptr;
|
mParent = nullptr;
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace mozilla {
|
|
||||||
namespace dom {
|
|
||||||
|
|
||||||
ContentPermissionRequestParent::ContentPermissionRequestParent(const nsACString& aType,
|
|
||||||
const nsACString& aAccess,
|
|
||||||
Element* aElement,
|
|
||||||
const IPC::Principal& aPrincipal)
|
|
||||||
{
|
|
||||||
MOZ_COUNT_CTOR(ContentPermissionRequestParent);
|
|
||||||
|
|
||||||
mPrincipal = aPrincipal;
|
|
||||||
mElement = aElement;
|
|
||||||
mType = aType;
|
|
||||||
mAccess = aAccess;
|
|
||||||
}
|
|
||||||
|
|
||||||
ContentPermissionRequestParent::~ContentPermissionRequestParent()
|
|
||||||
{
|
|
||||||
MOZ_COUNT_DTOR(ContentPermissionRequestParent);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
ContentPermissionRequestParent::Recvprompt()
|
|
||||||
{
|
|
||||||
mProxy = new nsContentPermissionRequestProxy();
|
|
||||||
NS_ASSERTION(mProxy, "Alloc of request proxy failed");
|
|
||||||
if (NS_FAILED(mProxy->Init(mType, mAccess, this))) {
|
|
||||||
mProxy->Cancel();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ContentPermissionRequestParent::ActorDestroy(ActorDestroyReason why)
|
|
||||||
{
|
|
||||||
if (mProxy) {
|
|
||||||
mProxy->OnParentDestroyed();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
ContentPermissionRequestParent::IsBeingDestroyed()
|
|
||||||
{
|
|
||||||
// When TabParent::Destroy() is called, we are being destroyed. It's unsafe
|
|
||||||
// to send out any message now.
|
|
||||||
TabParent* tabParent = static_cast<TabParent*>(Manager());
|
|
||||||
return tabParent->IsDestroyed();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace dom
|
|
||||||
} // namespace mozilla
|
|
||||||
|
@ -6,60 +6,75 @@
|
|||||||
#define nsContentPermissionHelper_h
|
#define nsContentPermissionHelper_h
|
||||||
|
|
||||||
#include "nsIContentPermissionPrompt.h"
|
#include "nsIContentPermissionPrompt.h"
|
||||||
#include "nsString.h"
|
#include "nsTArray.h"
|
||||||
|
#include "nsIMutableArray.h"
|
||||||
#include "mozilla/dom/PermissionMessageUtils.h"
|
|
||||||
#include "mozilla/dom/PContentPermissionRequestParent.h"
|
|
||||||
|
|
||||||
class nsContentPermissionRequestProxy;
|
class nsContentPermissionRequestProxy;
|
||||||
|
|
||||||
|
// Forward declare IPC::Principal here which is defined in
|
||||||
|
// PermissionMessageUtils.h. Include this file will transitively includes
|
||||||
|
// "windows.h" and it defines
|
||||||
|
// #define CreateEvent CreateEventW
|
||||||
|
// #define LoadImage LoadImageW
|
||||||
|
// That will mess up windows build.
|
||||||
|
namespace IPC {
|
||||||
|
class Principal;
|
||||||
|
}
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace dom {
|
namespace dom {
|
||||||
|
|
||||||
class Element;
|
class Element;
|
||||||
|
class PermissionRequest;
|
||||||
|
class ContentPermissionRequestParent;
|
||||||
|
class PContentPermissionRequestParent;
|
||||||
|
|
||||||
class ContentPermissionRequestParent : public PContentPermissionRequestParent
|
class ContentPermissionType : public nsIContentPermissionType
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ContentPermissionRequestParent(const nsACString& type,
|
NS_DECL_ISUPPORTS
|
||||||
const nsACString& access,
|
NS_DECL_NSICONTENTPERMISSIONTYPE
|
||||||
Element* element,
|
|
||||||
const IPC::Principal& principal);
|
|
||||||
virtual ~ContentPermissionRequestParent();
|
|
||||||
|
|
||||||
bool IsBeingDestroyed();
|
ContentPermissionType(const nsACString& aType, const nsACString& aAccess);
|
||||||
|
virtual ~ContentPermissionType();
|
||||||
|
|
||||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
protected:
|
||||||
nsCOMPtr<Element> mElement;
|
|
||||||
nsCOMPtr<nsContentPermissionRequestProxy> mProxy;
|
|
||||||
nsCString mType;
|
nsCString mType;
|
||||||
nsCString mAccess;
|
nsCString mAccess;
|
||||||
|
|
||||||
private:
|
|
||||||
virtual bool Recvprompt();
|
|
||||||
virtual void ActorDestroy(ActorDestroyReason why);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
uint32_t ConvertPermissionRequestToArray(nsTArray<PermissionRequest>& aSrcArray,
|
||||||
|
nsIMutableArray* aDesArray);
|
||||||
|
|
||||||
|
nsresult CreatePermissionArray(const nsACString& aType,
|
||||||
|
const nsACString& aAccess,
|
||||||
|
nsIArray** aTypesArray);
|
||||||
|
|
||||||
|
PContentPermissionRequestParent*
|
||||||
|
CreateContentPermissionRequestParent(const nsTArray<PermissionRequest>& aRequests,
|
||||||
|
Element* element,
|
||||||
|
const IPC::Principal& principal);
|
||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
||||||
class nsContentPermissionRequestProxy : public nsIContentPermissionRequest
|
class nsContentPermissionRequestProxy : public nsIContentPermissionRequest
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
NS_DECL_ISUPPORTS
|
||||||
|
NS_DECL_NSICONTENTPERMISSIONREQUEST
|
||||||
|
|
||||||
nsContentPermissionRequestProxy();
|
nsContentPermissionRequestProxy();
|
||||||
virtual ~nsContentPermissionRequestProxy();
|
virtual ~nsContentPermissionRequestProxy();
|
||||||
|
|
||||||
nsresult Init(const nsACString& type, const nsACString& access, mozilla::dom::ContentPermissionRequestParent* parent);
|
nsresult Init(const nsTArray<mozilla::dom::PermissionRequest>& requests,
|
||||||
|
mozilla::dom::ContentPermissionRequestParent* parent);
|
||||||
void OnParentDestroyed();
|
void OnParentDestroyed();
|
||||||
|
|
||||||
NS_DECL_ISUPPORTS
|
|
||||||
NS_DECL_NSICONTENTPERMISSIONREQUEST
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Non-owning pointer to the ContentPermissionRequestParent object which owns this proxy.
|
// Non-owning pointer to the ContentPermissionRequestParent object which owns this proxy.
|
||||||
mozilla::dom::ContentPermissionRequestParent* mParent;
|
mozilla::dom::ContentPermissionRequestParent* mParent;
|
||||||
nsCString mType;
|
nsTArray<mozilla::dom::PermissionRequest> mPermissionRequests;
|
||||||
nsCString mAccess;
|
|
||||||
};
|
};
|
||||||
#endif // nsContentPermissionHelper_h
|
|
||||||
|
|
||||||
|
#endif // nsContentPermissionHelper_h
|
||||||
|
@ -68,8 +68,10 @@ static bool sAdapterDiscoverable = false;
|
|||||||
static nsString sAdapterBdAddress;
|
static nsString sAdapterBdAddress;
|
||||||
static nsString sAdapterBdName;
|
static nsString sAdapterBdName;
|
||||||
static uint32_t sAdapterDiscoverableTimeout;
|
static uint32_t sAdapterDiscoverableTimeout;
|
||||||
|
static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sBondingRunnableArray;
|
||||||
static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sChangeDiscoveryRunnableArray;
|
static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sChangeDiscoveryRunnableArray;
|
||||||
static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sSetPropertyRunnableArray;
|
static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sSetPropertyRunnableArray;
|
||||||
|
static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sUnbondingRunnableArray;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Static callback functions
|
* Static callback functions
|
||||||
@ -197,6 +199,24 @@ IsReady()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
StringToBdAddressType(const nsAString& aBdAddress,
|
||||||
|
bt_bdaddr_t *aRetBdAddressType)
|
||||||
|
{
|
||||||
|
const char* str = NS_ConvertUTF16toUTF8(aBdAddress).get();
|
||||||
|
|
||||||
|
for (int i = 0; i < 6; i++) {
|
||||||
|
aRetBdAddressType->address[i] = (uint8_t) strtoul(str, (char **)&str, 16);
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AdapterPropertiesChangeCallback will be called after enable() but before
|
||||||
|
* AdapterStateChangeCallback sIsBtEnabled get updated.
|
||||||
|
* At that moment, both BluetoothManager/BluetoothAdapter does not register
|
||||||
|
* observer yet.
|
||||||
|
*/
|
||||||
static void
|
static void
|
||||||
AdapterPropertiesChangeCallback(bt_status_t aStatus, int aNumProperties,
|
AdapterPropertiesChangeCallback(bt_status_t aStatus, int aNumProperties,
|
||||||
bt_property_t *aProperties)
|
bt_property_t *aProperties)
|
||||||
@ -355,6 +375,120 @@ DiscoveryStateChangedCallback(bt_discovery_state_t aState)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
PinRequestCallback(bt_bdaddr_t* aRemoteBdAddress,
|
||||||
|
bt_bdname_t* aRemoteBdName, uint32_t aRemoteClass)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(!NS_IsMainThread());
|
||||||
|
|
||||||
|
InfallibleTArray<BluetoothNamedValue> propertiesArray;
|
||||||
|
nsAutoString remoteAddress;
|
||||||
|
BdAddressTypeToString(aRemoteBdAddress, remoteAddress);
|
||||||
|
|
||||||
|
propertiesArray.AppendElement(
|
||||||
|
BluetoothNamedValue(NS_LITERAL_STRING("address"), remoteAddress));
|
||||||
|
propertiesArray.AppendElement(
|
||||||
|
BluetoothNamedValue(NS_LITERAL_STRING("method"),
|
||||||
|
NS_LITERAL_STRING("pincode")));
|
||||||
|
propertiesArray.AppendElement(
|
||||||
|
BluetoothNamedValue(NS_LITERAL_STRING("name"),
|
||||||
|
NS_ConvertUTF8toUTF16(
|
||||||
|
(const char*)aRemoteBdName->name)));
|
||||||
|
|
||||||
|
BluetoothValue value = propertiesArray;
|
||||||
|
BluetoothSignal signal(NS_LITERAL_STRING("RequestPinCode"),
|
||||||
|
NS_LITERAL_STRING(KEY_LOCAL_AGENT), value);
|
||||||
|
nsRefPtr<DistributeBluetoothSignalTask>
|
||||||
|
t = new DistributeBluetoothSignalTask(signal);
|
||||||
|
if (NS_FAILED(NS_DispatchToMainThread(t))) {
|
||||||
|
NS_WARNING("Failed to dispatch to main thread!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
SspRequestCallback(bt_bdaddr_t* aRemoteBdAddress, bt_bdname_t* aRemoteBdName,
|
||||||
|
uint32_t aRemoteClass, bt_ssp_variant_t aPairingVariant,
|
||||||
|
uint32_t aPasskey)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(!NS_IsMainThread());
|
||||||
|
|
||||||
|
InfallibleTArray<BluetoothNamedValue> propertiesArray;
|
||||||
|
nsAutoString remoteAddress;
|
||||||
|
BdAddressTypeToString(aRemoteBdAddress, remoteAddress);
|
||||||
|
|
||||||
|
propertiesArray.AppendElement(
|
||||||
|
BluetoothNamedValue(NS_LITERAL_STRING("address"), remoteAddress));
|
||||||
|
propertiesArray.AppendElement(
|
||||||
|
BluetoothNamedValue(NS_LITERAL_STRING("method"),
|
||||||
|
NS_LITERAL_STRING("confirmation")));
|
||||||
|
propertiesArray.AppendElement(
|
||||||
|
BluetoothNamedValue(NS_LITERAL_STRING("name"),
|
||||||
|
NS_ConvertUTF8toUTF16(
|
||||||
|
(const char*)aRemoteBdName->name)));
|
||||||
|
propertiesArray.AppendElement(
|
||||||
|
BluetoothNamedValue(NS_LITERAL_STRING("passkey"), aPasskey));
|
||||||
|
|
||||||
|
BluetoothValue value = propertiesArray;
|
||||||
|
BluetoothSignal signal(NS_LITERAL_STRING("RequestConfirmation"),
|
||||||
|
NS_LITERAL_STRING(KEY_LOCAL_AGENT), value);
|
||||||
|
nsRefPtr<DistributeBluetoothSignalTask>
|
||||||
|
t = new DistributeBluetoothSignalTask(signal);
|
||||||
|
if (NS_FAILED(NS_DispatchToMainThread(t))) {
|
||||||
|
NS_WARNING("Failed to dispatch to main thread!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
BondStateChangedCallback(bt_status_t aStatus, bt_bdaddr_t* aRemoteBdAddress,
|
||||||
|
bt_bond_state_t aState)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(!NS_IsMainThread());
|
||||||
|
|
||||||
|
if (aState == BT_BOND_STATE_BONDING) {
|
||||||
|
//We don't need to handle bonding state
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool bonded = (aState == BT_BOND_STATE_BONDED);
|
||||||
|
nsAutoString remoteAddress;
|
||||||
|
BdAddressTypeToString(aRemoteBdAddress, remoteAddress);
|
||||||
|
InfallibleTArray<BluetoothNamedValue> propertiesArray;
|
||||||
|
propertiesArray.AppendElement(
|
||||||
|
BluetoothNamedValue(NS_LITERAL_STRING("address"), remoteAddress));
|
||||||
|
propertiesArray.AppendElement(
|
||||||
|
BluetoothNamedValue(NS_LITERAL_STRING("status"), bonded));
|
||||||
|
|
||||||
|
BluetoothSignal newSignal(NS_LITERAL_STRING(PAIRED_STATUS_CHANGED_ID),
|
||||||
|
NS_LITERAL_STRING(KEY_ADAPTER),
|
||||||
|
BluetoothValue(propertiesArray));
|
||||||
|
NS_DispatchToMainThread(new DistributeBluetoothSignalTask(newSignal));
|
||||||
|
|
||||||
|
if (bonded && !sBondingRunnableArray.IsEmpty()) {
|
||||||
|
DispatchBluetoothReply(sBondingRunnableArray[0],
|
||||||
|
BluetoothValue(true), EmptyString());
|
||||||
|
|
||||||
|
sBondingRunnableArray.RemoveElementAt(0);
|
||||||
|
} else if (!bonded && !sUnbondingRunnableArray.IsEmpty()) {
|
||||||
|
DispatchBluetoothReply(sUnbondingRunnableArray[0],
|
||||||
|
BluetoothValue(true), EmptyString());
|
||||||
|
|
||||||
|
sUnbondingRunnableArray.RemoveElementAt(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
AclStateChangedCallback(bt_status_t aStatus, bt_bdaddr_t* aRemoteBdAddress,
|
||||||
|
bt_acl_state_t aState)
|
||||||
|
{
|
||||||
|
//FIXME: This will be implemented in the later patchset
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
CallbackThreadEvent(bt_cb_thread_evt evt)
|
||||||
|
{
|
||||||
|
//FIXME: This will be implemented in the later patchset
|
||||||
|
}
|
||||||
|
|
||||||
bt_callbacks_t sBluetoothCallbacks =
|
bt_callbacks_t sBluetoothCallbacks =
|
||||||
{
|
{
|
||||||
sizeof(sBluetoothCallbacks),
|
sizeof(sBluetoothCallbacks),
|
||||||
@ -362,7 +496,12 @@ bt_callbacks_t sBluetoothCallbacks =
|
|||||||
AdapterPropertiesChangeCallback,
|
AdapterPropertiesChangeCallback,
|
||||||
RemoteDevicePropertiesChangeCallback,
|
RemoteDevicePropertiesChangeCallback,
|
||||||
DeviceFoundCallback,
|
DeviceFoundCallback,
|
||||||
DiscoveryStateChangedCallback
|
DiscoveryStateChangedCallback,
|
||||||
|
PinRequestCallback,
|
||||||
|
SspRequestCallback,
|
||||||
|
BondStateChangedCallback,
|
||||||
|
AclStateChangedCallback,
|
||||||
|
CallbackThreadEvent
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -515,6 +654,8 @@ nsresult
|
|||||||
BluetoothServiceBluedroid::GetPairedDevicePropertiesInternal(
|
BluetoothServiceBluedroid::GetPairedDevicePropertiesInternal(
|
||||||
const nsTArray<nsString>& aDeviceAddress, BluetoothReplyRunnable* aRunnable)
|
const nsTArray<nsString>& aDeviceAddress, BluetoothReplyRunnable* aRunnable)
|
||||||
{
|
{
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -700,14 +841,50 @@ BluetoothServiceBluedroid::CreatePairedDeviceInternal(
|
|||||||
const nsAString& aDeviceAddress, int aTimeout,
|
const nsAString& aDeviceAddress, int aTimeout,
|
||||||
BluetoothReplyRunnable* aRunnable)
|
BluetoothReplyRunnable* aRunnable)
|
||||||
{
|
{
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
|
if (!IsReady()) {
|
||||||
|
NS_NAMED_LITERAL_STRING(errorStr, "Bluetooth service is not ready yet!");
|
||||||
|
DispatchBluetoothReply(aRunnable, BluetoothValue(), errorStr);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
bt_bdaddr_t remoteAddress;
|
||||||
|
StringToBdAddressType(aDeviceAddress, &remoteAddress);
|
||||||
|
|
||||||
|
int ret = sBtInterface->create_bond(&remoteAddress);
|
||||||
|
if (ret != BT_STATUS_SUCCESS) {
|
||||||
|
ReplyStatusError(aRunnable, ret, NS_LITERAL_STRING("CreatedPairedDevice"));
|
||||||
|
} else {
|
||||||
|
sBondingRunnableArray.AppendElement(aRunnable);
|
||||||
|
}
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
BluetoothServiceBluedroid::RemoveDeviceInternal(
|
BluetoothServiceBluedroid::RemoveDeviceInternal(
|
||||||
const nsAString& aDeviceObjectPath,
|
const nsAString& aDeviceAddress, BluetoothReplyRunnable* aRunnable)
|
||||||
BluetoothReplyRunnable* aRunnable)
|
|
||||||
{
|
{
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
|
if (!IsReady()) {
|
||||||
|
NS_NAMED_LITERAL_STRING(errorStr, "Bluetooth service is not ready yet!");
|
||||||
|
DispatchBluetoothReply(aRunnable, BluetoothValue(), errorStr);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
bt_bdaddr_t remoteAddress;
|
||||||
|
StringToBdAddressType(aDeviceAddress, &remoteAddress);
|
||||||
|
|
||||||
|
int ret = sBtInterface->remove_bond(&remoteAddress);
|
||||||
|
if (ret != BT_STATUS_SUCCESS) {
|
||||||
|
ReplyStatusError(aRunnable, ret,
|
||||||
|
NS_LITERAL_STRING("RemoveDevice"));
|
||||||
|
} else {
|
||||||
|
sUnbondingRunnableArray.AppendElement(aRunnable);
|
||||||
|
}
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -716,6 +893,27 @@ BluetoothServiceBluedroid::SetPinCodeInternal(
|
|||||||
const nsAString& aDeviceAddress, const nsAString& aPinCode,
|
const nsAString& aDeviceAddress, const nsAString& aPinCode,
|
||||||
BluetoothReplyRunnable* aRunnable)
|
BluetoothReplyRunnable* aRunnable)
|
||||||
{
|
{
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
|
if (!IsReady()) {
|
||||||
|
NS_NAMED_LITERAL_STRING(errorStr, "Bluetooth service is not ready yet!");
|
||||||
|
DispatchBluetoothReply(aRunnable, BluetoothValue(), errorStr);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bt_bdaddr_t remoteAddress;
|
||||||
|
StringToBdAddressType(aDeviceAddress, &remoteAddress);
|
||||||
|
|
||||||
|
int ret = sBtInterface->pin_reply(
|
||||||
|
&remoteAddress, true, aPinCode.Length(),
|
||||||
|
(bt_pin_code_t*)NS_ConvertUTF16toUTF8(aPinCode).get());
|
||||||
|
|
||||||
|
if (ret != BT_STATUS_SUCCESS) {
|
||||||
|
ReplyStatusError(aRunnable, ret, NS_LITERAL_STRING("SetPinCode"));
|
||||||
|
} else {
|
||||||
|
DispatchBluetoothReply(aRunnable, BluetoothValue(true), EmptyString());
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -732,6 +930,26 @@ BluetoothServiceBluedroid::SetPairingConfirmationInternal(
|
|||||||
const nsAString& aDeviceAddress, bool aConfirm,
|
const nsAString& aDeviceAddress, bool aConfirm,
|
||||||
BluetoothReplyRunnable* aRunnable)
|
BluetoothReplyRunnable* aRunnable)
|
||||||
{
|
{
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
|
if (!IsReady()) {
|
||||||
|
NS_NAMED_LITERAL_STRING(errorStr, "Bluetooth service is not ready yet!");
|
||||||
|
DispatchBluetoothReply(aRunnable, BluetoothValue(), errorStr);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bt_bdaddr_t remoteAddress;
|
||||||
|
StringToBdAddressType(aDeviceAddress, &remoteAddress);
|
||||||
|
|
||||||
|
int ret = sBtInterface->ssp_reply(&remoteAddress, (bt_ssp_variant_t)0,
|
||||||
|
aConfirm, 0);
|
||||||
|
if (ret != BT_STATUS_SUCCESS) {
|
||||||
|
ReplyStatusError(aRunnable, ret,
|
||||||
|
NS_LITERAL_STRING("SetPairingConfirmation"));
|
||||||
|
} else {
|
||||||
|
DispatchBluetoothReply(aRunnable, BluetoothValue(true), EmptyString());
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,6 +49,7 @@
|
|||||||
#include "nsIStringBundle.h"
|
#include "nsIStringBundle.h"
|
||||||
#include "nsIDocument.h"
|
#include "nsIDocument.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include "nsContentPermissionHelper.h"
|
||||||
|
|
||||||
#include "mozilla/dom/DeviceStorageBinding.h"
|
#include "mozilla/dom/DeviceStorageBinding.h"
|
||||||
|
|
||||||
@ -1695,17 +1696,14 @@ nsDOMDeviceStorageCursor::GetStorageType(nsAString & aType)
|
|||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsDOMDeviceStorageCursor::GetType(nsACString & aType)
|
nsDOMDeviceStorageCursor::GetTypes(nsIArray** aTypes)
|
||||||
{
|
{
|
||||||
return DeviceStorageTypeChecker::GetPermissionForType(mFile->mStorageType,
|
nsCString type;
|
||||||
aType);
|
nsresult rv =
|
||||||
}
|
DeviceStorageTypeChecker::GetPermissionForType(mFile->mStorageType, type);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
NS_IMETHODIMP
|
return CreatePermissionArray(type, NS_LITERAL_CSTRING("read"), aTypes);
|
||||||
nsDOMDeviceStorageCursor::GetAccess(nsACString & aAccess)
|
|
||||||
{
|
|
||||||
aAccess = NS_LITERAL_CSTRING("read");
|
|
||||||
return NS_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
@ -2180,8 +2178,10 @@ public:
|
|||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
nsTArray<PermissionRequest> permArray;
|
||||||
|
permArray.AppendElement(PermissionRequest(type, access));
|
||||||
child->SendPContentPermissionRequestConstructor(
|
child->SendPContentPermissionRequestConstructor(
|
||||||
this, type, access, IPC::Principal(mPrincipal));
|
this, permArray, IPC::Principal(mPrincipal));
|
||||||
|
|
||||||
Sendprompt();
|
Sendprompt();
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
@ -2195,26 +2195,23 @@ public:
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHOD GetType(nsACString & aType)
|
NS_IMETHODIMP GetTypes(nsIArray** aTypes)
|
||||||
{
|
{
|
||||||
nsCString type;
|
nsCString type;
|
||||||
nsresult rv
|
nsresult rv =
|
||||||
= DeviceStorageTypeChecker::GetPermissionForType(mFile->mStorageType,
|
DeviceStorageTypeChecker::GetPermissionForType(mFile->mStorageType, type);
|
||||||
aType);
|
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHOD GetAccess(nsACString & aAccess)
|
nsCString access;
|
||||||
{
|
rv = DeviceStorageTypeChecker::GetAccessForRequest(
|
||||||
nsresult rv = DeviceStorageTypeChecker::GetAccessForRequest(
|
DeviceStorageRequestType(mRequestType), access);
|
||||||
DeviceStorageRequestType(mRequestType), aAccess);
|
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
return NS_OK;
|
|
||||||
|
return CreatePermissionArray(type, access, aTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHOD GetPrincipal(nsIPrincipal * *aRequestingPrincipal)
|
NS_IMETHOD GetPrincipal(nsIPrincipal * *aRequestingPrincipal)
|
||||||
@ -3191,8 +3188,10 @@ nsDOMDeviceStorage::EnumerateInternal(const nsAString& aPath,
|
|||||||
if (aRv.Failed()) {
|
if (aRv.Failed()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
child->SendPContentPermissionRequestConstructor(r, type,
|
nsTArray<PermissionRequest> permArray;
|
||||||
NS_LITERAL_CSTRING("read"),
|
permArray.AppendElement(PermissionRequest(type, NS_LITERAL_CSTRING("read")));
|
||||||
|
child->SendPContentPermissionRequestConstructor(r,
|
||||||
|
permArray,
|
||||||
IPC::Principal(mPrincipal));
|
IPC::Principal(mPrincipal));
|
||||||
|
|
||||||
r->Sendprompt();
|
r->Sendprompt();
|
||||||
|
@ -401,6 +401,14 @@ dictionary MozStkTimer
|
|||||||
unsigned short timerAction;
|
unsigned short timerAction;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
dictionary MozStkBipMessage
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Text String
|
||||||
|
*/
|
||||||
|
DOMString text;
|
||||||
|
};
|
||||||
|
|
||||||
dictionary MozStkCommand
|
dictionary MozStkCommand
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
@ -469,6 +477,13 @@ dictionary MozStkCommand
|
|||||||
* option is MozStkTimer
|
* option is MozStkTimer
|
||||||
*
|
*
|
||||||
* When typeOfCommand is
|
* When typeOfCommand is
|
||||||
|
* - STK_CMD_OPEN_CHANNEL
|
||||||
|
* - STK_CMD_CLOSE_CHANNEL
|
||||||
|
* - STK_CMD_SEND_DATA
|
||||||
|
* - STK_CMD_RECEIVE_DATA
|
||||||
|
* options is MozStkBipMessage
|
||||||
|
*
|
||||||
|
* When typeOfCommand is
|
||||||
* - STK_CMD_POLL_OFF
|
* - STK_CMD_POLL_OFF
|
||||||
* options is null.
|
* options is null.
|
||||||
*
|
*
|
||||||
|
@ -9,7 +9,7 @@ interface nsIDOMDOMRequest;
|
|||||||
interface nsIDOMEventListener;
|
interface nsIDOMEventListener;
|
||||||
interface nsIDOMMozIccInfo;
|
interface nsIDOMMozIccInfo;
|
||||||
|
|
||||||
[scriptable, builtinclass, uuid(b403e307-e4ff-47a0-ac1e-c97b042b4595)]
|
[scriptable, builtinclass, uuid(50782fe0-4185-4471-a374-e362b73febdb)]
|
||||||
interface nsIDOMMozIccManager : nsIDOMEventTarget
|
interface nsIDOMMozIccManager : nsIDOMEventTarget
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
@ -50,6 +50,10 @@ interface nsIDOMMozIccManager : nsIDOMEventTarget
|
|||||||
const unsigned short STK_CMD_PROVIDE_LOCAL_INFO = 0x26;
|
const unsigned short STK_CMD_PROVIDE_LOCAL_INFO = 0x26;
|
||||||
const unsigned short STK_CMD_TIMER_MANAGEMENT = 0x27;
|
const unsigned short STK_CMD_TIMER_MANAGEMENT = 0x27;
|
||||||
const unsigned short STK_CMD_SET_UP_IDLE_MODE_TEXT = 0x28;
|
const unsigned short STK_CMD_SET_UP_IDLE_MODE_TEXT = 0x28;
|
||||||
|
const unsigned short STK_CMD_OPEN_CHANNEL = 0x30;
|
||||||
|
const unsigned short STK_CMD_CLOSE_CHANNEL = 0x31;
|
||||||
|
const unsigned short STK_CMD_RECEIVE_DATA = 0x32;
|
||||||
|
const unsigned short STK_CMD_SEND_DATA = 0x33;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* STK Result code.
|
* STK Result code.
|
||||||
|
@ -7,15 +7,13 @@
|
|||||||
interface nsIPrincipal;
|
interface nsIPrincipal;
|
||||||
interface nsIDOMWindow;
|
interface nsIDOMWindow;
|
||||||
interface nsIDOMElement;
|
interface nsIDOMElement;
|
||||||
|
interface nsIArray;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface allows access to a content to request
|
* Interface provides the request type and its access.
|
||||||
* permission to perform a privileged operation such as
|
|
||||||
* geolocation.
|
|
||||||
*/
|
*/
|
||||||
[scriptable, uuid(1de67000-2de8-11e2-81c1-0800200c9a66)]
|
[scriptable, builtinclass, uuid(384b6cc4-a66b-4bea-98e0-eb10562a9ba4)]
|
||||||
interface nsIContentPermissionRequest : nsISupports {
|
interface nsIContentPermissionType : nsISupports {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type of the permission request, such as
|
* The type of the permission request, such as
|
||||||
* "geolocation".
|
* "geolocation".
|
||||||
@ -27,8 +25,22 @@ interface nsIContentPermissionRequest : nsISupports {
|
|||||||
* "read".
|
* "read".
|
||||||
*/
|
*/
|
||||||
readonly attribute ACString access;
|
readonly attribute ACString access;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface allows access to a content to request
|
||||||
|
* permission to perform a privileged operation such as
|
||||||
|
* geolocation.
|
||||||
|
*/
|
||||||
|
[scriptable, uuid(69a39d88-d1c4-4ba9-9b19-bafc7a1bb783)]
|
||||||
|
interface nsIContentPermissionRequest : nsISupports {
|
||||||
/**
|
/**
|
||||||
|
* The array will include the request types. Elements of this array are
|
||||||
|
* nsIContentPermissionType object.
|
||||||
|
*/
|
||||||
|
readonly attribute nsIArray types;
|
||||||
|
|
||||||
|
/*
|
||||||
* The principal of the permission request.
|
* The principal of the permission request.
|
||||||
*/
|
*/
|
||||||
readonly attribute nsIPrincipal principal;
|
readonly attribute nsIPrincipal principal;
|
||||||
|
@ -6,15 +6,27 @@
|
|||||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include "AppProcessChecker.h"
|
#include "AppProcessChecker.h"
|
||||||
|
#include "nsIPermissionManager.h"
|
||||||
#ifdef MOZ_CHILD_PERMISSIONS
|
#ifdef MOZ_CHILD_PERMISSIONS
|
||||||
#include "ContentParent.h"
|
#include "ContentParent.h"
|
||||||
#include "mozIApplication.h"
|
#include "mozIApplication.h"
|
||||||
#include "mozilla/hal_sandbox/PHalParent.h"
|
#include "mozilla/hal_sandbox/PHalParent.h"
|
||||||
|
#include "nsIAppsService.h"
|
||||||
|
#include "nsIPrincipal.h"
|
||||||
|
#include "nsIScriptSecurityManager.h"
|
||||||
|
#include "nsIURI.h"
|
||||||
|
#include "nsNetUtil.h"
|
||||||
|
#include "nsServiceManagerUtils.h"
|
||||||
#include "TabParent.h"
|
#include "TabParent.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
using namespace mozilla::dom;
|
using namespace mozilla::dom;
|
||||||
using namespace mozilla::hal_sandbox;
|
using namespace mozilla::hal_sandbox;
|
||||||
using namespace mozilla::services;
|
using namespace mozilla::services;
|
||||||
|
#else
|
||||||
|
class PContentParent;
|
||||||
|
class nsIPrincipal;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
@ -126,6 +138,106 @@ AssertAppProcess(PHalParent* aActor,
|
|||||||
return AssertAppProcess(aActor->Manager(), aType, aCapability);
|
return AssertAppProcess(aActor->Manager(), aType, aCapability);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
AssertAppPrincipal(PContentParent* aActor,
|
||||||
|
nsIPrincipal* aPrincipal)
|
||||||
|
{
|
||||||
|
if (!aPrincipal) {
|
||||||
|
NS_WARNING("Principal is invalid, killing app process");
|
||||||
|
static_cast<ContentParent*>(aActor)->KillHard();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t principalAppId = aPrincipal->GetAppId();
|
||||||
|
bool inBrowserElement = aPrincipal->GetIsInBrowserElement();
|
||||||
|
|
||||||
|
// Check if the permission's appId matches a child we manage.
|
||||||
|
const InfallibleTArray<PBrowserParent*>& browsers =
|
||||||
|
aActor->ManagedPBrowserParent();
|
||||||
|
for (uint32_t i = 0; i < browsers.Length(); ++i) {
|
||||||
|
TabParent* tab = static_cast<TabParent*>(browsers[i]);
|
||||||
|
if (tab->OwnOrContainingAppId() == principalAppId) {
|
||||||
|
// If the child only runs inBrowserElement content and the principal claims
|
||||||
|
// it's not in a browser element, it's lying.
|
||||||
|
if (!tab->IsBrowserElement() || inBrowserElement) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_WARNING("Principal is invalid, killing app process");
|
||||||
|
static_cast<ContentParent*>(aActor)->KillHard();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
already_AddRefed<nsIPrincipal>
|
||||||
|
GetAppPrincipal(uint32_t aAppId)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID);
|
||||||
|
|
||||||
|
nsString manifestURL;
|
||||||
|
nsresult rv = appsService->GetManifestURLByLocalId(aAppId, manifestURL);
|
||||||
|
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||||
|
|
||||||
|
nsCOMPtr<nsIURI> uri;
|
||||||
|
NS_NewURI(getter_AddRefs(uri), manifestURL);
|
||||||
|
|
||||||
|
nsCOMPtr<nsIScriptSecurityManager> secMan =
|
||||||
|
do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID);
|
||||||
|
|
||||||
|
nsCOMPtr<nsIPrincipal> appPrincipal;
|
||||||
|
rv = secMan->GetAppCodebasePrincipal(uri, aAppId, false,
|
||||||
|
getter_AddRefs(appPrincipal));
|
||||||
|
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||||
|
return appPrincipal.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
CheckPermission(PContentParent* aActor,
|
||||||
|
nsIPrincipal* aPrincipal,
|
||||||
|
const char* aPermission)
|
||||||
|
{
|
||||||
|
if (!AssertAppPrincipal(aActor, aPrincipal)) {
|
||||||
|
return nsIPermissionManager::DENY_ACTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIPermissionManager> pm =
|
||||||
|
do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
|
||||||
|
NS_ENSURE_TRUE(pm, nsIPermissionManager::DENY_ACTION);
|
||||||
|
|
||||||
|
// Make sure that `aPermission' is an app permission before checking the origin.
|
||||||
|
nsCOMPtr<nsIPrincipal> appPrincipal = GetAppPrincipal(aPrincipal->GetAppId());
|
||||||
|
uint32_t appPerm = nsIPermissionManager::UNKNOWN_ACTION;
|
||||||
|
nsresult rv = pm->TestExactPermissionFromPrincipal(appPrincipal, aPermission, &appPerm);
|
||||||
|
NS_ENSURE_SUCCESS(rv, nsIPermissionManager::UNKNOWN_ACTION);
|
||||||
|
if (appPerm == nsIPermissionManager::UNKNOWN_ACTION ||
|
||||||
|
appPerm == nsIPermissionManager::DENY_ACTION) {
|
||||||
|
return appPerm;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t permission = nsIPermissionManager::UNKNOWN_ACTION;
|
||||||
|
rv = pm->TestExactPermissionFromPrincipal(aPrincipal, aPermission, &permission);
|
||||||
|
NS_ENSURE_SUCCESS(rv, nsIPermissionManager::UNKNOWN_ACTION);
|
||||||
|
if (permission == nsIPermissionManager::UNKNOWN_ACTION ||
|
||||||
|
permission == nsIPermissionManager::DENY_ACTION) {
|
||||||
|
return permission;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (appPerm == nsIPermissionManager::PROMPT_ACTION ||
|
||||||
|
permission == nsIPermissionManager::PROMPT_ACTION) {
|
||||||
|
return nsIPermissionManager::PROMPT_ACTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (appPerm == nsIPermissionManager::ALLOW_ACTION ||
|
||||||
|
permission == nsIPermissionManager::ALLOW_ACTION) {
|
||||||
|
return nsIPermissionManager::ALLOW_ACTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_RUNTIMEABORT("Invalid permission value");
|
||||||
|
return nsIPermissionManager::DENY_ACTION;
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -167,6 +279,21 @@ AssertAppProcess(mozilla::hal_sandbox::PHalParent* aActor,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
AssertAppPrincipal(PContentParent* aActor,
|
||||||
|
nsIPrincipal* aPrincipal)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
CheckPermission(PContentParent*,
|
||||||
|
nsIPrincipal*,
|
||||||
|
const char*)
|
||||||
|
{
|
||||||
|
return nsIPermissionManager::ALLOW_ACTION;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
@ -8,6 +8,10 @@
|
|||||||
#ifndef mozilla_AppProcessChecker_h
|
#ifndef mozilla_AppProcessChecker_h
|
||||||
#define mozilla_AppProcessChecker_h
|
#define mozilla_AppProcessChecker_h
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
class nsIPrincipal;
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
namespace dom {
|
namespace dom {
|
||||||
@ -66,6 +70,21 @@ AssertAppProcess(mozilla::hal_sandbox::PHalParent* aActor,
|
|||||||
// return AssertAppProcess(aActor->Manager(), aType);
|
// return AssertAppProcess(aActor->Manager(), aType);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
bool
|
||||||
|
AssertAppPrincipal(mozilla::dom::PContentParent* aParent,
|
||||||
|
nsIPrincipal* aPrincipal);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the specified principal is valid, and return the saved permission
|
||||||
|
* value for permission `aPermission' on that principal.
|
||||||
|
* See nsIPermissionManager.idl for possible return values.
|
||||||
|
*
|
||||||
|
* nsIPermissionManager::UNKNOWN_ACTION is retuned if the principal is invalid.
|
||||||
|
*/
|
||||||
|
uint32_t
|
||||||
|
CheckPermission(mozilla::dom::PContentParent* aParent,
|
||||||
|
nsIPrincipal* aPrincipal, const char* aPermission);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inline function for asserting the process's permission.
|
* Inline function for asserting the process's permission.
|
||||||
*/
|
*/
|
||||||
|
@ -16,6 +16,7 @@ include protocol PIndexedDB;
|
|||||||
include DOMTypes;
|
include DOMTypes;
|
||||||
include JavaScriptTypes;
|
include JavaScriptTypes;
|
||||||
include URIParams;
|
include URIParams;
|
||||||
|
include PContentPermission;
|
||||||
|
|
||||||
|
|
||||||
using class IPC::Principal from "mozilla/dom/PermissionMessageUtils.h";
|
using class IPC::Principal from "mozilla/dom/PermissionMessageUtils.h";
|
||||||
@ -202,10 +203,8 @@ parent:
|
|||||||
* Initiates an asynchronous request for permission for the
|
* Initiates an asynchronous request for permission for the
|
||||||
* provided principal.
|
* provided principal.
|
||||||
*
|
*
|
||||||
* @param aType
|
* @param aRequests
|
||||||
* The type of permission to request.
|
* The array of permissions to request.
|
||||||
* @param aAccess
|
|
||||||
* Access type. "read" for example.
|
|
||||||
* @param aPrincipal
|
* @param aPrincipal
|
||||||
* The principal of the request.
|
* The principal of the request.
|
||||||
*
|
*
|
||||||
@ -213,7 +212,7 @@ parent:
|
|||||||
* principals that can live in the content process should
|
* principals that can live in the content process should
|
||||||
* provided.
|
* provided.
|
||||||
*/
|
*/
|
||||||
PContentPermissionRequest(nsCString aType, nsCString aAccess, Principal principal);
|
PContentPermissionRequest(PermissionRequest[] aRequests, Principal aPrincipal);
|
||||||
|
|
||||||
PContentDialog(uint32_t aType, nsCString aName, nsCString aFeatures,
|
PContentDialog(uint32_t aType, nsCString aName, nsCString aFeatures,
|
||||||
int32_t[] aIntParams, nsString[] aStringParams);
|
int32_t[] aIntParams, nsString[] aStringParams);
|
||||||
|
14
dom/ipc/PContentPermission.ipdlh
Normal file
14
dom/ipc/PContentPermission.ipdlh
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace dom {
|
||||||
|
|
||||||
|
struct PermissionRequest {
|
||||||
|
nsCString type;
|
||||||
|
nsCString access;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace dom
|
||||||
|
} // namespace mozilla
|
@ -2008,7 +2008,8 @@ TabChild::DeallocPContentDialogChild(PContentDialogChild* aDialog)
|
|||||||
}
|
}
|
||||||
|
|
||||||
PContentPermissionRequestChild*
|
PContentPermissionRequestChild*
|
||||||
TabChild::AllocPContentPermissionRequestChild(const nsCString& aType, const nsCString& aAccess, const IPC::Principal&)
|
TabChild::AllocPContentPermissionRequestChild(const InfallibleTArray<PermissionRequest>& aRequests,
|
||||||
|
const IPC::Principal& aPrincipal)
|
||||||
{
|
{
|
||||||
NS_RUNTIMEABORT("unused");
|
NS_RUNTIMEABORT("unused");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -269,13 +269,11 @@ public:
|
|||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
virtual PContentPermissionRequestChild*
|
virtual PContentPermissionRequestChild*
|
||||||
SendPContentPermissionRequestConstructor(PContentPermissionRequestChild* aActor,
|
SendPContentPermissionRequestConstructor(PContentPermissionRequestChild* aActor,
|
||||||
const nsCString& aType,
|
const InfallibleTArray<PermissionRequest>& aRequests,
|
||||||
const nsCString& aAccess,
|
|
||||||
const IPC::Principal& aPrincipal);
|
const IPC::Principal& aPrincipal);
|
||||||
#endif /* DEBUG */
|
#endif /* DEBUG */
|
||||||
|
|
||||||
virtual PContentPermissionRequestChild* AllocPContentPermissionRequestChild(const nsCString& aType,
|
virtual PContentPermissionRequestChild* AllocPContentPermissionRequestChild(const InfallibleTArray<PermissionRequest>& aRequests,
|
||||||
const nsCString& aAccess,
|
|
||||||
const IPC::Principal& aPrincipal);
|
const IPC::Principal& aPrincipal);
|
||||||
virtual bool DeallocPContentPermissionRequestChild(PContentPermissionRequestChild* actor);
|
virtual bool DeallocPContentPermissionRequestChild(PContentPermissionRequestChild* actor);
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include "mozilla/BrowserElementParent.h"
|
#include "mozilla/BrowserElementParent.h"
|
||||||
#include "mozilla/docshell/OfflineCacheUpdateParent.h"
|
#include "mozilla/docshell/OfflineCacheUpdateParent.h"
|
||||||
#include "mozilla/dom/ContentParent.h"
|
#include "mozilla/dom/ContentParent.h"
|
||||||
|
#include "mozilla/dom/PContentPermissionRequestParent.h"
|
||||||
#include "mozilla/Hal.h"
|
#include "mozilla/Hal.h"
|
||||||
#include "mozilla/ipc/DocumentRendererParent.h"
|
#include "mozilla/ipc/DocumentRendererParent.h"
|
||||||
#include "mozilla/layers/CompositorParent.h"
|
#include "mozilla/layers/CompositorParent.h"
|
||||||
@ -570,9 +571,10 @@ TabParent::DeallocPDocumentRendererParent(PDocumentRendererParent* actor)
|
|||||||
}
|
}
|
||||||
|
|
||||||
PContentPermissionRequestParent*
|
PContentPermissionRequestParent*
|
||||||
TabParent::AllocPContentPermissionRequestParent(const nsCString& type, const nsCString& access, const IPC::Principal& principal)
|
TabParent::AllocPContentPermissionRequestParent(const InfallibleTArray<PermissionRequest>& aRequests,
|
||||||
|
const IPC::Principal& aPrincipal)
|
||||||
{
|
{
|
||||||
return new ContentPermissionRequestParent(type, access, mFrameElement, principal);
|
return CreateContentPermissionRequestParent(aRequests, mFrameElement, aPrincipal);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -215,7 +215,8 @@ public:
|
|||||||
virtual bool DeallocPDocumentRendererParent(PDocumentRendererParent* actor);
|
virtual bool DeallocPDocumentRendererParent(PDocumentRendererParent* actor);
|
||||||
|
|
||||||
virtual PContentPermissionRequestParent*
|
virtual PContentPermissionRequestParent*
|
||||||
AllocPContentPermissionRequestParent(const nsCString& aType, const nsCString& aAccess, const IPC::Principal& aPrincipal);
|
AllocPContentPermissionRequestParent(const InfallibleTArray<PermissionRequest>& aRequests,
|
||||||
|
const IPC::Principal& aPrincipal);
|
||||||
virtual bool DeallocPContentPermissionRequestParent(PContentPermissionRequestParent* actor);
|
virtual bool DeallocPContentPermissionRequestParent(PContentPermissionRequestParent* actor);
|
||||||
|
|
||||||
virtual POfflineCacheUpdateParent* AllocPOfflineCacheUpdateParent(
|
virtual POfflineCacheUpdateParent* AllocPOfflineCacheUpdateParent(
|
||||||
|
@ -64,6 +64,7 @@ IPDL_SOURCES += [
|
|||||||
'PBrowser.ipdl',
|
'PBrowser.ipdl',
|
||||||
'PContent.ipdl',
|
'PContent.ipdl',
|
||||||
'PContentDialog.ipdl',
|
'PContentDialog.ipdl',
|
||||||
|
'PContentPermission.ipdlh',
|
||||||
'PContentPermissionRequest.ipdl',
|
'PContentPermissionRequest.ipdl',
|
||||||
'PCrashReporter.ipdl',
|
'PCrashReporter.ipdl',
|
||||||
'PDocumentRenderer.ipdl',
|
'PDocumentRenderer.ipdl',
|
||||||
|
@ -43,7 +43,7 @@
|
|||||||
#include "MediaEngineWebRTC.h"
|
#include "MediaEngineWebRTC.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef MOZ_WIDGET_GONK
|
#ifdef MOZ_B2G
|
||||||
#include "MediaPermissionGonk.h"
|
#include "MediaPermissionGonk.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -810,7 +810,6 @@ public:
|
|||||||
, mListener(aListener)
|
, mListener(aListener)
|
||||||
, mPrefs(aPrefs)
|
, mPrefs(aPrefs)
|
||||||
, mDeviceChosen(false)
|
, mDeviceChosen(false)
|
||||||
, mBackendChosen(false)
|
|
||||||
, mManager(MediaManager::GetInstance())
|
, mManager(MediaManager::GetInstance())
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@ -832,15 +831,11 @@ public:
|
|||||||
, mListener(aListener)
|
, mListener(aListener)
|
||||||
, mPrefs(aPrefs)
|
, mPrefs(aPrefs)
|
||||||
, mDeviceChosen(false)
|
, mDeviceChosen(false)
|
||||||
, mBackendChosen(true)
|
|
||||||
, mBackend(aBackend)
|
, mBackend(aBackend)
|
||||||
, mManager(MediaManager::GetInstance())
|
, mManager(MediaManager::GetInstance())
|
||||||
{}
|
{}
|
||||||
|
|
||||||
~GetUserMediaRunnable() {
|
~GetUserMediaRunnable() {
|
||||||
if (mBackendChosen) {
|
|
||||||
delete mBackend;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHOD
|
NS_IMETHOD
|
||||||
@ -848,10 +843,7 @@ public:
|
|||||||
{
|
{
|
||||||
NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread");
|
NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread");
|
||||||
|
|
||||||
// Was a backend provided?
|
mBackend = mManager->GetBackend(mWindowID);
|
||||||
if (!mBackendChosen) {
|
|
||||||
mBackend = mManager->GetBackend(mWindowID);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Was a device provided?
|
// Was a device provided?
|
||||||
if (!mDeviceChosen) {
|
if (!mDeviceChosen) {
|
||||||
@ -1038,7 +1030,6 @@ private:
|
|||||||
MediaEnginePrefs mPrefs;
|
MediaEnginePrefs mPrefs;
|
||||||
|
|
||||||
bool mDeviceChosen;
|
bool mDeviceChosen;
|
||||||
bool mBackendChosen;
|
|
||||||
|
|
||||||
MediaEngine* mBackend;
|
MediaEngine* mBackend;
|
||||||
nsRefPtr<MediaManager> mManager; // get ref to this when creating the runnable
|
nsRefPtr<MediaManager> mManager; // get ref to this when creating the runnable
|
||||||
@ -1256,10 +1247,10 @@ MediaManager::GetUserMedia(JSContext* aCx, bool aPrivileged,
|
|||||||
// Force MediaManager to startup before we try to access it from other threads
|
// Force MediaManager to startup before we try to access it from other threads
|
||||||
// Hack: should init singleton earlier unless it's expensive (mem or CPU)
|
// Hack: should init singleton earlier unless it's expensive (mem or CPU)
|
||||||
(void) MediaManager::Get();
|
(void) MediaManager::Get();
|
||||||
#ifdef MOZ_WIDGET_GONK
|
#ifdef MOZ_B2G
|
||||||
// Initialize MediaPermissionManager before send out any permission request.
|
// Initialize MediaPermissionManager before send out any permission request.
|
||||||
(void) MediaPermissionManager::GetInstance();
|
(void) MediaPermissionManager::GetInstance();
|
||||||
#endif //MOZ_WIDGET_GONK
|
#endif //MOZ_B2G
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store the WindowID in a hash table and mark as active. The entry is removed
|
// Store the WindowID in a hash table and mark as active. The entry is removed
|
||||||
@ -1311,7 +1302,7 @@ MediaManager::GetUserMedia(JSContext* aCx, bool aPrivileged,
|
|||||||
if (c.mFake) {
|
if (c.mFake) {
|
||||||
// Fake stream from default backend.
|
// Fake stream from default backend.
|
||||||
gUMRunnable = new GetUserMediaRunnable(c, onSuccess.forget(),
|
gUMRunnable = new GetUserMediaRunnable(c, onSuccess.forget(),
|
||||||
onError.forget(), windowID, listener, mPrefs, new MediaEngineDefault());
|
onError.forget(), windowID, listener, mPrefs, GetBackend(windowID, true));
|
||||||
} else {
|
} else {
|
||||||
// Stream from default device from WebRTC backend.
|
// Stream from default device from WebRTC backend.
|
||||||
gUMRunnable = new GetUserMediaRunnable(c, onSuccess.forget(),
|
gUMRunnable = new GetUserMediaRunnable(c, onSuccess.forget(),
|
||||||
@ -1392,22 +1383,26 @@ MediaManager::GetUserMediaDevices(nsPIDOMWindow* aWindow,
|
|||||||
}
|
}
|
||||||
|
|
||||||
MediaEngine*
|
MediaEngine*
|
||||||
MediaManager::GetBackend(uint64_t aWindowId)
|
MediaManager::GetBackend(uint64_t aWindowId, bool aFake)
|
||||||
{
|
{
|
||||||
// Plugin backends as appropriate. The default engine also currently
|
// Plugin backends as appropriate. The default engine also currently
|
||||||
// includes picture support for Android.
|
// includes picture support for Android.
|
||||||
// This IS called off main-thread.
|
// This IS called off main-thread.
|
||||||
MutexAutoLock lock(mMutex);
|
MutexAutoLock lock(mMutex);
|
||||||
if (!mBackend) {
|
if (!mBackend) {
|
||||||
|
if (aFake) {
|
||||||
|
mBackend = new MediaEngineDefault();
|
||||||
|
} else {
|
||||||
#if defined(MOZ_WEBRTC)
|
#if defined(MOZ_WEBRTC)
|
||||||
#ifndef MOZ_B2G_CAMERA
|
#ifndef MOZ_B2G_CAMERA
|
||||||
mBackend = new MediaEngineWebRTC();
|
mBackend = new MediaEngineWebRTC();
|
||||||
#else
|
|
||||||
mBackend = new MediaEngineWebRTC(mCameraManager, aWindowId);
|
|
||||||
#endif
|
|
||||||
#else
|
#else
|
||||||
mBackend = new MediaEngineDefault();
|
mBackend = new MediaEngineWebRTC(mCameraManager, aWindowId);
|
||||||
#endif
|
#endif
|
||||||
|
#else
|
||||||
|
mBackend = new MediaEngineDefault();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return mBackend;
|
return mBackend;
|
||||||
}
|
}
|
||||||
|
@ -405,7 +405,7 @@ public:
|
|||||||
NS_DECL_NSIOBSERVER
|
NS_DECL_NSIOBSERVER
|
||||||
NS_DECL_NSIMEDIAMANAGERSERVICE
|
NS_DECL_NSIMEDIAMANAGERSERVICE
|
||||||
|
|
||||||
MediaEngine* GetBackend(uint64_t aWindowId = 0);
|
MediaEngine* GetBackend(uint64_t aWindowId = 0, bool aFake = false);
|
||||||
StreamListeners *GetWindowListeners(uint64_t aWindowId) {
|
StreamListeners *GetWindowListeners(uint64_t aWindowId) {
|
||||||
NS_ASSERTION(NS_IsMainThread(), "Only access windowlist on main thread");
|
NS_ASSERTION(NS_IsMainThread(), "Only access windowlist on main thread");
|
||||||
|
|
||||||
@ -469,7 +469,7 @@ private:
|
|||||||
|
|
||||||
static StaticRefPtr<MediaManager> sSingleton;
|
static StaticRefPtr<MediaManager> sSingleton;
|
||||||
|
|
||||||
#ifdef MOZ_WIDGET_GONK
|
#ifdef MOZ_B2G_CAMERA
|
||||||
nsRefPtr<nsDOMCameraManager> mCameraManager;
|
nsRefPtr<nsDOMCameraManager> mCameraManager;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
@ -20,14 +20,36 @@
|
|||||||
#include "mozilla/dom/MediaStreamTrackBinding.h"
|
#include "mozilla/dom/MediaStreamTrackBinding.h"
|
||||||
#include "nsISupportsPrimitives.h"
|
#include "nsISupportsPrimitives.h"
|
||||||
#include "nsServiceManagerUtils.h"
|
#include "nsServiceManagerUtils.h"
|
||||||
|
#include "nsArrayUtils.h"
|
||||||
|
#include "nsContentPermissionHelper.h"
|
||||||
#include "mozilla/dom/PermissionMessageUtils.h"
|
#include "mozilla/dom/PermissionMessageUtils.h"
|
||||||
|
|
||||||
#define AUDIO_PERMISSION_NAME "audio-capture"
|
#define AUDIO_PERMISSION_NAME "audio-capture"
|
||||||
|
#define VIDEO_PERMISSION_NAME "video-capture"
|
||||||
|
|
||||||
|
using namespace mozilla::dom;
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
static MediaPermissionManager *gMediaPermMgr = nullptr;
|
static MediaPermissionManager *gMediaPermMgr = nullptr;
|
||||||
|
|
||||||
|
static uint32_t
|
||||||
|
ConvertArrayToPermissionRequest(nsIArray* aSrcArray,
|
||||||
|
nsTArray<PermissionRequest>& aDesArray)
|
||||||
|
{
|
||||||
|
uint32_t len = 0;
|
||||||
|
aSrcArray->GetLength(&len);
|
||||||
|
for (uint32_t i = 0; i < len; i++) {
|
||||||
|
nsCOMPtr<nsIContentPermissionType> cpt = do_QueryElementAt(aSrcArray, i);
|
||||||
|
nsAutoCString type;
|
||||||
|
nsAutoCString access;
|
||||||
|
cpt->GetType(type);
|
||||||
|
cpt->GetAccess(access);
|
||||||
|
aDesArray.AppendElement(PermissionRequest(type, access));
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
// Helper function for notifying permission granted
|
// Helper function for notifying permission granted
|
||||||
static nsresult
|
static nsresult
|
||||||
NotifyPermissionAllow(const nsAString &aCallID, nsTArray<nsCOMPtr<nsIMediaDevice> > &aDevices)
|
NotifyPermissionAllow(const nsAString &aCallID, nsTArray<nsCOMPtr<nsIMediaDevice> > &aDevices)
|
||||||
@ -93,6 +115,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
bool mAudio; // Request for audio permission
|
bool mAudio; // Request for audio permission
|
||||||
|
bool mVideo; // Request for video permission
|
||||||
nsRefPtr<dom::GetUserMediaRequest> mRequest;
|
nsRefPtr<dom::GetUserMediaRequest> mRequest;
|
||||||
nsTArray<nsCOMPtr<nsIMediaDevice> > mDevices; // candiate device list
|
nsTArray<nsCOMPtr<nsIMediaDevice> > mDevices; // candiate device list
|
||||||
};
|
};
|
||||||
@ -108,6 +131,7 @@ MediaPermissionRequest::MediaPermissionRequest(nsRefPtr<dom::GetUserMediaRequest
|
|||||||
mRequest->GetConstraints(constraints);
|
mRequest->GetConstraints(constraints);
|
||||||
|
|
||||||
mAudio = constraints.mAudio;
|
mAudio = constraints.mAudio;
|
||||||
|
mVideo = constraints.mVideo;
|
||||||
|
|
||||||
for (uint32_t i = 0; i < aDevices.Length(); ++i) {
|
for (uint32_t i = 0; i < aDevices.Length(); ++i) {
|
||||||
nsCOMPtr<nsIMediaDevice> device(aDevices[i]);
|
nsCOMPtr<nsIMediaDevice> device(aDevices[i]);
|
||||||
@ -116,10 +140,34 @@ MediaPermissionRequest::MediaPermissionRequest(nsRefPtr<dom::GetUserMediaRequest
|
|||||||
if (mAudio && deviceType.EqualsLiteral("audio")) {
|
if (mAudio && deviceType.EqualsLiteral("audio")) {
|
||||||
mDevices.AppendElement(device);
|
mDevices.AppendElement(device);
|
||||||
}
|
}
|
||||||
|
if (mVideo && deviceType.EqualsLiteral("video")) {
|
||||||
|
mDevices.AppendElement(device);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// nsIContentPermissionRequest methods
|
// nsIContentPermissionRequest methods
|
||||||
|
NS_IMETHODIMP
|
||||||
|
MediaPermissionRequest::GetTypes(nsIArray** aTypes)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIMutableArray> types = do_CreateInstance(NS_ARRAY_CONTRACTID);
|
||||||
|
if (mAudio) {
|
||||||
|
nsCOMPtr<ContentPermissionType> AudioType =
|
||||||
|
new ContentPermissionType(NS_LITERAL_CSTRING(AUDIO_PERMISSION_NAME),
|
||||||
|
NS_LITERAL_CSTRING("unused"));
|
||||||
|
types->AppendElement(AudioType, false);
|
||||||
|
}
|
||||||
|
if (mVideo) {
|
||||||
|
nsCOMPtr<ContentPermissionType> VideoType =
|
||||||
|
new ContentPermissionType(NS_LITERAL_CSTRING(VIDEO_PERMISSION_NAME),
|
||||||
|
NS_LITERAL_CSTRING("unused"));
|
||||||
|
types->AppendElement(VideoType, false);
|
||||||
|
}
|
||||||
|
NS_IF_ADDREF(*aTypes = types);
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
MediaPermissionRequest::GetPrincipal(nsIPrincipal **aRequestingPrincipal)
|
MediaPermissionRequest::GetPrincipal(nsIPrincipal **aRequestingPrincipal)
|
||||||
{
|
{
|
||||||
@ -135,24 +183,6 @@ MediaPermissionRequest::GetPrincipal(nsIPrincipal **aRequestingPrincipal)
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
MediaPermissionRequest::GetType(nsACString &aType)
|
|
||||||
{
|
|
||||||
if (mAudio) {
|
|
||||||
aType = AUDIO_PERMISSION_NAME;
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
MediaPermissionRequest::GetAccess(nsACString &aAccess)
|
|
||||||
{
|
|
||||||
aAccess = "unused";
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
MediaPermissionRequest::GetWindow(nsIDOMWindow** aRequestingWindow)
|
MediaPermissionRequest::GetWindow(nsIDOMWindow** aRequestingWindow)
|
||||||
{
|
{
|
||||||
@ -278,13 +308,12 @@ MediaDeviceSuccessCallback::DoPrompt(nsRefPtr<MediaPermissionRequest> &req)
|
|||||||
dom::TabChild* child = dom::TabChild::GetFrom(window->GetDocShell());
|
dom::TabChild* child = dom::TabChild::GetFrom(window->GetDocShell());
|
||||||
NS_ENSURE_TRUE(child, NS_ERROR_FAILURE);
|
NS_ENSURE_TRUE(child, NS_ERROR_FAILURE);
|
||||||
|
|
||||||
nsAutoCString type;
|
nsCOMPtr<nsIArray> typeArray;
|
||||||
rv = req->GetType(type);
|
rv = req->GetTypes(getter_AddRefs(typeArray));
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
nsAutoCString access;
|
nsTArray<PermissionRequest> permArray;
|
||||||
rv = req->GetAccess(access);
|
ConvertArrayToPermissionRequest(typeArray, permArray);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
nsCOMPtr<nsIPrincipal> principal;
|
nsCOMPtr<nsIPrincipal> principal;
|
||||||
rv = req->GetPrincipal(getter_AddRefs(principal));
|
rv = req->GetPrincipal(getter_AddRefs(principal));
|
||||||
@ -292,8 +321,7 @@ MediaDeviceSuccessCallback::DoPrompt(nsRefPtr<MediaPermissionRequest> &req)
|
|||||||
|
|
||||||
req->AddRef();
|
req->AddRef();
|
||||||
child->SendPContentPermissionRequestConstructor(req,
|
child->SendPContentPermissionRequestConstructor(req,
|
||||||
type,
|
permArray,
|
||||||
access,
|
|
||||||
IPC::Principal(principal));
|
IPC::Principal(principal));
|
||||||
|
|
||||||
req->Sendprompt();
|
req->Sendprompt();
|
||||||
|
@ -7,3 +7,9 @@ ifdef MOZ_WEBRTC_LEAKING_TESTS
|
|||||||
MOCHITEST_FILES += \
|
MOCHITEST_FILES += \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifdef MOZ_B2G_CAMERA
|
||||||
|
MOCHITEST_FILES += \
|
||||||
|
test_getUserMedia_permission.html \
|
||||||
|
$(NULL)
|
||||||
|
endif
|
||||||
|
77
dom/media/tests/mochitest/test_getUserMedia_permission.html
Normal file
77
dom/media/tests/mochitest/test_getUserMedia_permission.html
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<!--
|
||||||
|
https://bugzilla.mozilla.org/show_bug.cgi?id=853356
|
||||||
|
-->
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>mozGetUserMedia Permission Test</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||||
|
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<script type="application/javascript" src="head.js"></script>
|
||||||
|
<script type="application/javascript" src="mediaStreamPlayback.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=853356">Display camera/microphone permission acquisition prompt</a>
|
||||||
|
<script type="application/javascript">
|
||||||
|
var MockPermissionPrompt = SpecialPowers.MockPermissionPrompt;
|
||||||
|
MockPermissionPrompt.init();
|
||||||
|
|
||||||
|
var gCount = 0;
|
||||||
|
var gTests = [
|
||||||
|
{
|
||||||
|
constraints: {video: true, audio: false}
|
||||||
|
}
|
||||||
|
,
|
||||||
|
{
|
||||||
|
constraints: {video: false, audio: true}
|
||||||
|
}
|
||||||
|
,
|
||||||
|
{
|
||||||
|
constraints: {video: true, audio: true},
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
function gUM(data) {
|
||||||
|
var gum_success = function (stream) {
|
||||||
|
SimpleTest.info("TEST-INFO | Got succss callback for " + JSON.stringify(data.constraints));
|
||||||
|
|
||||||
|
var hasAudioTrack = stream.getAudioTracks().length > 0;
|
||||||
|
var hasVideoTrack = stream.getVideoTracks().length > 0;
|
||||||
|
|
||||||
|
is(data.constraints.audio, hasAudioTrack, "Request audio track:" +
|
||||||
|
data.constraints.audio + " contain audio track:" + hasAudioTrack);
|
||||||
|
is(data.constraints.video, hasVideoTrack, "Request video track:" +
|
||||||
|
data.constraints.video + " contain audio track:" + hasVideoTrack);
|
||||||
|
gCount++;
|
||||||
|
if (gCount < gTests.length) {
|
||||||
|
gUM(gTests[gCount]);
|
||||||
|
} else {
|
||||||
|
SimpleTest.finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var gum_fail = function () {
|
||||||
|
ok(false, "permission not granted for " + JSON.stringify(data.constraints));
|
||||||
|
|
||||||
|
SimpleTest.finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
SimpleTest.info("TEST-INFO | Call getUserMedia for " + JSON.stringify(data.constraints));
|
||||||
|
navigator.mozGetUserMedia(data.constraints, gum_success, gum_fail);
|
||||||
|
}
|
||||||
|
|
||||||
|
SpecialPowers.pushPrefEnv({"set": [["media.navigator.permission.disabled", false]]},
|
||||||
|
function () {
|
||||||
|
SpecialPowers.addPermission('video-capture',
|
||||||
|
Ci.nsIPermissionManager.ALLOW_ACTION, document);
|
||||||
|
SpecialPowers.addPermission('audio-capture',
|
||||||
|
Ci.nsIPermissionManager.ALLOW_ACTION, document);
|
||||||
|
|
||||||
|
gUM(gTests[gCount]);
|
||||||
|
});
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
</script>
|
||||||
|
</pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -14,7 +14,7 @@ dictionary SmsThreadListItem
|
|||||||
unsigned long long unreadCount;
|
unsigned long long unreadCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
[scriptable, uuid(5f82f826-1956-11e3-a2bb-9b043b33de27)]
|
[scriptable, uuid(58780660-4080-11e3-8397-a7bb1b58cf12)]
|
||||||
interface nsIMobileMessageCallback : nsISupports
|
interface nsIMobileMessageCallback : nsISupports
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
@ -31,6 +31,7 @@ interface nsIMobileMessageCallback : nsISupports
|
|||||||
const unsigned short RADIO_DISABLED_ERROR = 6;
|
const unsigned short RADIO_DISABLED_ERROR = 6;
|
||||||
const unsigned short INVALID_ADDRESS_ERROR = 7;
|
const unsigned short INVALID_ADDRESS_ERROR = 7;
|
||||||
const unsigned short FDN_CHECK_ERROR = 8;
|
const unsigned short FDN_CHECK_ERROR = 8;
|
||||||
|
const unsigned short NON_ACTIVE_SIM_CARD_ERROR = 9;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* |message| can be nsIDOMMoz{Mms,Sms}Message.
|
* |message| can be nsIDOMMoz{Mms,Sms}Message.
|
||||||
|
@ -106,6 +106,9 @@ MobileMessageCallback::NotifyError(int32_t aError, bool aAsync)
|
|||||||
case nsIMobileMessageCallback::FDN_CHECK_ERROR:
|
case nsIMobileMessageCallback::FDN_CHECK_ERROR:
|
||||||
errorStr = NS_LITERAL_STRING("FdnCheckError");
|
errorStr = NS_LITERAL_STRING("FdnCheckError");
|
||||||
break;
|
break;
|
||||||
|
case nsIMobileMessageCallback::NON_ACTIVE_SIM_CARD_ERROR:
|
||||||
|
errorStr = NS_LITERAL_STRING("NonActiveSimCardError");
|
||||||
|
break;
|
||||||
default: // SUCCESS_NO_ERROR is handled above.
|
default: // SUCCESS_NO_ERROR is handled above.
|
||||||
MOZ_CRASH("Should never get here!");
|
MOZ_CRASH("Should never get here!");
|
||||||
}
|
}
|
||||||
|
@ -1698,13 +1698,21 @@ MmsService.prototype = {
|
|||||||
|
|
||||||
this.broadcastReceivedMessageEvent(domMessage);
|
this.broadcastReceivedMessageEvent(domMessage);
|
||||||
|
|
||||||
// In roaming environment, we send notify response only in
|
// In the roaming environment, we send notify response only for the
|
||||||
// automatic retrieval mode.
|
// automatic retrieval mode.
|
||||||
if ((retrievalMode !== RETRIEVAL_MODE_AUTOMATIC) &&
|
if ((retrievalMode !== RETRIEVAL_MODE_AUTOMATIC) &&
|
||||||
mmsConnection.isVoiceRoaming()) {
|
mmsConnection.isVoiceRoaming()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Under the "automatic" retrieval mode, for the non-active SIM, we have to
|
||||||
|
// download the MMS as if it is downloaded by the "manual" retrieval mode.
|
||||||
|
if ((retrievalMode == RETRIEVAL_MODE_AUTOMATIC ||
|
||||||
|
retrievalMode == RETRIEVAL_MODE_AUTOMATIC_HOME) &&
|
||||||
|
mmsConnection.serviceId != this.mmsDefaultServiceId) {
|
||||||
|
retrievalMode = RETRIEVAL_MODE_MANUAL;
|
||||||
|
}
|
||||||
|
|
||||||
if (RETRIEVAL_MODE_MANUAL === retrievalMode ||
|
if (RETRIEVAL_MODE_MANUAL === retrievalMode ||
|
||||||
RETRIEVAL_MODE_NEVER === retrievalMode) {
|
RETRIEVAL_MODE_NEVER === retrievalMode) {
|
||||||
let mmsStatus = RETRIEVAL_MODE_NEVER === retrievalMode
|
let mmsStatus = RETRIEVAL_MODE_NEVER === retrievalMode
|
||||||
@ -1722,6 +1730,7 @@ MmsService.prototype = {
|
|||||||
transaction.run();
|
transaction.run();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let url = savableMessage.headers["x-mms-content-location"].uri;
|
let url = savableMessage.headers["x-mms-content-location"].uri;
|
||||||
|
|
||||||
// For RETRIEVAL_MODE_AUTOMATIC or RETRIEVAL_MODE_AUTOMATIC_HOME but not
|
// For RETRIEVAL_MODE_AUTOMATIC or RETRIEVAL_MODE_AUTOMATIC_HOME but not
|
||||||
@ -2187,6 +2196,15 @@ MmsService.prototype = {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// To support DSDS, we have to stop users retrieving MMS when the needed
|
||||||
|
// SIM is not active, thus avoiding the data disconnection of the current
|
||||||
|
// SIM. Users have to manually swith the default SIM before retrieving.
|
||||||
|
if (serviceId != this.mmsDefaultServiceId) {
|
||||||
|
if (DEBUG) debug("RIL service is not active to retrieve MMS.");
|
||||||
|
aRequest.notifyGetMessageFailed(Ci.nsIMobileMessageCallback.NON_ACTIVE_SIM_CARD_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let mmsConnection = gMmsConnections.getConnByServiceId(serviceId);
|
let mmsConnection = gMmsConnections.getConnByServiceId(serviceId);
|
||||||
|
|
||||||
let url = aMessageRecord.headers["x-mms-content-location"].uri;
|
let url = aMessageRecord.headers["x-mms-content-location"].uri;
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include "nsServiceManagerUtils.h"
|
#include "nsServiceManagerUtils.h"
|
||||||
#include "nsContentUtils.h"
|
#include "nsContentUtils.h"
|
||||||
#include "nsCxPusher.h"
|
#include "nsCxPusher.h"
|
||||||
|
#include "nsContentPermissionHelper.h"
|
||||||
#include "nsIDocument.h"
|
#include "nsIDocument.h"
|
||||||
#include "nsIObserverService.h"
|
#include "nsIObserverService.h"
|
||||||
#include "nsPIDOMWindow.h"
|
#include "nsPIDOMWindow.h"
|
||||||
@ -385,17 +386,11 @@ nsGeolocationRequest::GetPrincipal(nsIPrincipal * *aRequestingPrincipal)
|
|||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsGeolocationRequest::GetType(nsACString & aType)
|
nsGeolocationRequest::GetTypes(nsIArray** aTypes)
|
||||||
{
|
{
|
||||||
aType = "geolocation";
|
return CreatePermissionArray(NS_LITERAL_CSTRING("geolocation"),
|
||||||
return NS_OK;
|
NS_LITERAL_CSTRING("unused"),
|
||||||
}
|
aTypes);
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsGeolocationRequest::GetAccess(nsACString & aAccess)
|
|
||||||
{
|
|
||||||
aAccess = "unused";
|
|
||||||
return NS_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
@ -1452,12 +1447,15 @@ Geolocation::RegisterRequestWithPrompt(nsGeolocationRequest* request)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsTArray<PermissionRequest> permArray;
|
||||||
|
permArray.AppendElement(PermissionRequest(NS_LITERAL_CSTRING("geolocation"),
|
||||||
|
NS_LITERAL_CSTRING("unused")));
|
||||||
|
|
||||||
// Retain a reference so the object isn't deleted without IPDL's knowledge.
|
// Retain a reference so the object isn't deleted without IPDL's knowledge.
|
||||||
// Corresponding release occurs in DeallocPContentPermissionRequest.
|
// Corresponding release occurs in DeallocPContentPermissionRequest.
|
||||||
request->AddRef();
|
request->AddRef();
|
||||||
child->SendPContentPermissionRequestConstructor(request,
|
child->SendPContentPermissionRequestConstructor(request,
|
||||||
NS_LITERAL_CSTRING("geolocation"),
|
permArray,
|
||||||
NS_LITERAL_CSTRING("unused"),
|
|
||||||
IPC::Principal(mPrincipal));
|
IPC::Principal(mPrincipal));
|
||||||
|
|
||||||
request->Sendprompt();
|
request->Sendprompt();
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include "PCOMContentPermissionRequestChild.h"
|
#include "PCOMContentPermissionRequestChild.h"
|
||||||
#include "nsIScriptSecurityManager.h"
|
#include "nsIScriptSecurityManager.h"
|
||||||
#include "nsServiceManagerUtils.h"
|
#include "nsServiceManagerUtils.h"
|
||||||
|
#include "PermissionMessageUtils.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace dom {
|
namespace dom {
|
||||||
@ -177,9 +178,12 @@ DesktopNotification::Init()
|
|||||||
// Corresponding release occurs in DeallocPContentPermissionRequest.
|
// Corresponding release occurs in DeallocPContentPermissionRequest.
|
||||||
nsRefPtr<DesktopNotificationRequest> copy = request;
|
nsRefPtr<DesktopNotificationRequest> copy = request;
|
||||||
|
|
||||||
|
nsTArray<PermissionRequest> permArray;
|
||||||
|
permArray.AppendElement(PermissionRequest(
|
||||||
|
NS_LITERAL_CSTRING("desktop-notification"),
|
||||||
|
NS_LITERAL_CSTRING("unused")));
|
||||||
child->SendPContentPermissionRequestConstructor(copy.forget().get(),
|
child->SendPContentPermissionRequestConstructor(copy.forget().get(),
|
||||||
NS_LITERAL_CSTRING("desktop-notification"),
|
permArray,
|
||||||
NS_LITERAL_CSTRING("unused"),
|
|
||||||
IPC::Principal(mPrincipal));
|
IPC::Principal(mPrincipal));
|
||||||
|
|
||||||
request->Sendprompt();
|
request->Sendprompt();
|
||||||
@ -351,17 +355,11 @@ DesktopNotificationRequest::Allow()
|
|||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
DesktopNotificationRequest::GetType(nsACString & aType)
|
DesktopNotificationRequest::GetTypes(nsIArray** aTypes)
|
||||||
{
|
{
|
||||||
aType = "desktop-notification";
|
return CreatePermissionArray(NS_LITERAL_CSTRING("desktop-notification"),
|
||||||
return NS_OK;
|
NS_LITERAL_CSTRING("unused"),
|
||||||
}
|
aTypes);
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
DesktopNotificationRequest::GetAccess(nsACString & aAccess)
|
|
||||||
{
|
|
||||||
aAccess = "unused";
|
|
||||||
return NS_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include "nsDOMJSUtils.h"
|
#include "nsDOMJSUtils.h"
|
||||||
#include "nsIScriptSecurityManager.h"
|
#include "nsIScriptSecurityManager.h"
|
||||||
#include "mozilla/dom/PermissionMessageUtils.h"
|
#include "mozilla/dom/PermissionMessageUtils.h"
|
||||||
|
#include "nsContentPermissionHelper.h"
|
||||||
#ifdef MOZ_B2G
|
#ifdef MOZ_B2G
|
||||||
#include "nsIDOMDesktopNotification.h"
|
#include "nsIDOMDesktopNotification.h"
|
||||||
#endif
|
#endif
|
||||||
@ -267,9 +268,11 @@ NotificationPermissionRequest::Run()
|
|||||||
// Corresponding release occurs in DeallocPContentPermissionRequest.
|
// Corresponding release occurs in DeallocPContentPermissionRequest.
|
||||||
AddRef();
|
AddRef();
|
||||||
|
|
||||||
NS_NAMED_LITERAL_CSTRING(type, "desktop-notification");
|
nsTArray<PermissionRequest> permArray;
|
||||||
NS_NAMED_LITERAL_CSTRING(access, "unused");
|
permArray.AppendElement(PermissionRequest(
|
||||||
child->SendPContentPermissionRequestConstructor(this, type, access,
|
NS_LITERAL_CSTRING("desktop-notification"),
|
||||||
|
NS_LITERAL_CSTRING("unused")));
|
||||||
|
child->SendPContentPermissionRequestConstructor(this, permArray,
|
||||||
IPC::Principal(mPrincipal));
|
IPC::Principal(mPrincipal));
|
||||||
|
|
||||||
Sendprompt();
|
Sendprompt();
|
||||||
@ -342,17 +345,11 @@ NotificationPermissionRequest::CallCallback()
|
|||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
NotificationPermissionRequest::GetAccess(nsACString& aAccess)
|
NotificationPermissionRequest::GetTypes(nsIArray** aTypes)
|
||||||
{
|
{
|
||||||
aAccess.AssignLiteral("unused");
|
return CreatePermissionArray(NS_LITERAL_CSTRING("desktop-notification"),
|
||||||
return NS_OK;
|
NS_LITERAL_CSTRING("unused"),
|
||||||
}
|
aTypes);
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
NotificationPermissionRequest::GetType(nsACString& aType)
|
|
||||||
{
|
|
||||||
aType.AssignLiteral("desktop-notification");
|
|
||||||
return NS_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -750,6 +750,10 @@ this.STK_CMD_SEND_USSD = 0x12;
|
|||||||
this.STK_CMD_SEND_SMS = 0x13;
|
this.STK_CMD_SEND_SMS = 0x13;
|
||||||
this.STK_CMD_SEND_DTMF = 0x14;
|
this.STK_CMD_SEND_DTMF = 0x14;
|
||||||
this.STK_CMD_LAUNCH_BROWSER = 0x15;
|
this.STK_CMD_LAUNCH_BROWSER = 0x15;
|
||||||
|
this.STK_CMD_OPEN_CHANNEL = 0x16;
|
||||||
|
this.STK_CMD_CLOSE_CHANNEL = 0x17;
|
||||||
|
this.STK_CMD_RECEIVE_DATA = 0x18;
|
||||||
|
this.STK_CMD_SEND_DATA = 0x19;
|
||||||
this.STK_CMD_PLAY_TONE = 0x20;
|
this.STK_CMD_PLAY_TONE = 0x20;
|
||||||
this.STK_CMD_DISPLAY_TEXT = 0x21;
|
this.STK_CMD_DISPLAY_TEXT = 0x21;
|
||||||
this.STK_CMD_GET_INKEY = 0x22;
|
this.STK_CMD_GET_INKEY = 0x22;
|
||||||
@ -1043,6 +1047,12 @@ this.STK_TERMINAL_SUPPORT_PROACTIVE_LANGUAGE_NOTIFICATION = 0;
|
|||||||
this.STK_TERMINAL_SUPPORT_PROACTIVE_LAUNCH_BROWSER = 1;
|
this.STK_TERMINAL_SUPPORT_PROACTIVE_LAUNCH_BROWSER = 1;
|
||||||
this.STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_ACCESS_TECH = 0;
|
this.STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_ACCESS_TECH = 0;
|
||||||
|
|
||||||
|
this.STK_TERMINAL_SUPPORT_BIP_COMMAND_OPEN_CHANNEL = 1;
|
||||||
|
this.STK_TERMINAL_SUPPORT_BIP_COMMAND_CLOSE_CHANNEL = 1;
|
||||||
|
this.STK_TERMINAL_SUPPORT_BIP_COMMAND_RECEIVE_DATA = 1;
|
||||||
|
this.STK_TERMINAL_SUPPORT_BIP_COMMAND_SEND_DATA = 1;
|
||||||
|
this.STK_TERMINAL_SUPPORT_BIP_COMMAND_GET_CHANNEL_STATUS = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SAT profile
|
* SAT profile
|
||||||
*
|
*
|
||||||
@ -1124,6 +1134,13 @@ this.STK_TERMINAL_PROFILE_PROACTIVE_4 =
|
|||||||
(STK_TERMINAL_SUPPORT_PROACTIVE_LAUNCH_BROWSER << 6) |
|
(STK_TERMINAL_SUPPORT_PROACTIVE_LAUNCH_BROWSER << 6) |
|
||||||
(STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_ACCESS_TECH << 7);
|
(STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_ACCESS_TECH << 7);
|
||||||
|
|
||||||
|
this.STK_TERMINAL_PROFILE_BIP_COMMAND =
|
||||||
|
(STK_TERMINAL_SUPPORT_BIP_COMMAND_OPEN_CHANNEL << 0) |
|
||||||
|
(STK_TERMINAL_SUPPORT_BIP_COMMAND_CLOSE_CHANNEL << 1) |
|
||||||
|
(STK_TERMINAL_SUPPORT_BIP_COMMAND_RECEIVE_DATA << 2) |
|
||||||
|
(STK_TERMINAL_SUPPORT_BIP_COMMAND_SEND_DATA << 3) |
|
||||||
|
(STK_TERMINAL_SUPPORT_BIP_COMMAND_GET_CHANNEL_STATUS << 4);
|
||||||
|
|
||||||
this.STK_SUPPORTED_TERMINAL_PROFILE = [
|
this.STK_SUPPORTED_TERMINAL_PROFILE = [
|
||||||
STK_TERMINAL_PROFILE_DOWNLOAD,
|
STK_TERMINAL_PROFILE_DOWNLOAD,
|
||||||
STK_TERMINAL_PROFILE_OTHER,
|
STK_TERMINAL_PROFILE_OTHER,
|
||||||
@ -1136,7 +1153,7 @@ this.STK_SUPPORTED_TERMINAL_PROFILE = [
|
|||||||
STK_TERMINAL_PROFILE_PROACTIVE_4,
|
STK_TERMINAL_PROFILE_PROACTIVE_4,
|
||||||
0x00, // Softkey support
|
0x00, // Softkey support
|
||||||
0x00, // Softkey information
|
0x00, // Softkey information
|
||||||
0x00, // BIP proactive commands
|
STK_TERMINAL_PROFILE_BIP_COMMAND,
|
||||||
0x00, // BIP supported bearers
|
0x00, // BIP supported bearers
|
||||||
0x00, // Screen height
|
0x00, // Screen height
|
||||||
0x00, // Screen width
|
0x00, // Screen width
|
||||||
|
@ -9900,6 +9900,26 @@ let StkCommandParamsFactory = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return timer;
|
return timer;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a param for BIP commands.
|
||||||
|
*
|
||||||
|
* @param cmdDetails
|
||||||
|
* The value object of CommandDetails TLV.
|
||||||
|
* @param ctlvs
|
||||||
|
* The all TLVs in this proactive command.
|
||||||
|
*/
|
||||||
|
processBipMessage: function processBipMessage(cmdDetails, ctlvs) {
|
||||||
|
let bipMsg = {};
|
||||||
|
|
||||||
|
let ctlv = StkProactiveCmdHelper.searchForTag(
|
||||||
|
COMPREHENSIONTLV_TAG_ALPHA_ID, ctlvs);
|
||||||
|
if (ctlv) {
|
||||||
|
bipMsg.text = ctlv.value.identifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bipMsg;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
StkCommandParamsFactory[STK_CMD_REFRESH] = function STK_CMD_REFRESH(cmdDetails, ctlvs) {
|
StkCommandParamsFactory[STK_CMD_REFRESH] = function STK_CMD_REFRESH(cmdDetails, ctlvs) {
|
||||||
@ -9959,6 +9979,18 @@ StkCommandParamsFactory[STK_CMD_PLAY_TONE] = function STK_CMD_PLAY_TONE(cmdDetai
|
|||||||
StkCommandParamsFactory[STK_CMD_TIMER_MANAGEMENT] = function STK_CMD_TIMER_MANAGEMENT(cmdDetails, ctlvs) {
|
StkCommandParamsFactory[STK_CMD_TIMER_MANAGEMENT] = function STK_CMD_TIMER_MANAGEMENT(cmdDetails, ctlvs) {
|
||||||
return this.processTimerManagement(cmdDetails, ctlvs);
|
return this.processTimerManagement(cmdDetails, ctlvs);
|
||||||
};
|
};
|
||||||
|
StkCommandParamsFactory[STK_CMD_OPEN_CHANNEL] = function STK_CMD_OPEN_CHANNEL(cmdDetails, ctlvs) {
|
||||||
|
return this.processBipMessage(cmdDetails, ctlvs);
|
||||||
|
};
|
||||||
|
StkCommandParamsFactory[STK_CMD_CLOSE_CHANNEL] = function STK_CMD_CLOSE_CHANNEL(cmdDetails, ctlvs) {
|
||||||
|
return this.processBipMessage(cmdDetails, ctlvs);
|
||||||
|
};
|
||||||
|
StkCommandParamsFactory[STK_CMD_RECEIVE_DATA] = function STK_CMD_RECEIVE_DATA(cmdDetails, ctlvs) {
|
||||||
|
return this.processBipMessage(cmdDetails, ctlvs);
|
||||||
|
};
|
||||||
|
StkCommandParamsFactory[STK_CMD_SEND_DATA] = function STK_CMD_SEND_DATA(cmdDetails, ctlvs) {
|
||||||
|
return this.processBipMessage(cmdDetails, ctlvs);
|
||||||
|
};
|
||||||
|
|
||||||
let StkProactiveCmdHelper = {
|
let StkProactiveCmdHelper = {
|
||||||
retrieve: function retrieve(tag, length) {
|
retrieve: function retrieve(tag, length) {
|
||||||
|
@ -763,6 +763,110 @@ add_test(function test_stk_proactive_command_provide_local_information() {
|
|||||||
run_next_test();
|
run_next_test();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify Proactive command : BIP Messages
|
||||||
|
*/
|
||||||
|
add_test(function test_stk_proactive_command_open_channel() {
|
||||||
|
let worker = newUint8Worker();
|
||||||
|
let pduHelper = worker.GsmPDUHelper;
|
||||||
|
let berHelper = worker.BerTlvHelper;
|
||||||
|
let stkHelper = worker.StkProactiveCmdHelper;
|
||||||
|
|
||||||
|
// Open Channel
|
||||||
|
let open_channel = [
|
||||||
|
0xD0,
|
||||||
|
0x0F,
|
||||||
|
0x81, 0x03, 0x01, 0x16, 0x00,
|
||||||
|
0x82, 0x02, 0x81, 0x82,
|
||||||
|
0x85, 0x04, 0x4F, 0x70, 0x65, 0x6E //alpha id: "Open"
|
||||||
|
];
|
||||||
|
|
||||||
|
for (let i = 0; i < open_channel.length; i++) {
|
||||||
|
pduHelper.writeHexOctet(open_channel[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
let berTlv = berHelper.decode(open_channel.length);
|
||||||
|
let ctlvs = berTlv.value;
|
||||||
|
let tlv = stkHelper.searchForTag(COMPREHENSIONTLV_TAG_COMMAND_DETAILS, ctlvs);
|
||||||
|
do_check_eq(tlv.value.commandNumber, 0x01);
|
||||||
|
do_check_eq(tlv.value.typeOfCommand, STK_CMD_OPEN_CHANNEL);
|
||||||
|
do_check_eq(tlv.value.commandQualifier, 0x00);
|
||||||
|
|
||||||
|
tlv = stkHelper.searchForTag(COMPREHENSIONTLV_TAG_ALPHA_ID, ctlvs);
|
||||||
|
do_check_eq(tlv.value.identifier, "Open");
|
||||||
|
|
||||||
|
// Close Channel
|
||||||
|
let close_channel = [
|
||||||
|
0xD0,
|
||||||
|
0x10,
|
||||||
|
0x81, 0x03, 0x01, 0x17, 0x00,
|
||||||
|
0x82, 0x02, 0x81, 0x82,
|
||||||
|
0x85, 0x05, 0x43, 0x6C, 0x6F, 0x73, 0x65 //alpha id: "Close"
|
||||||
|
];
|
||||||
|
|
||||||
|
for (let i = 0; i < close_channel.length; i++) {
|
||||||
|
pduHelper.writeHexOctet(close_channel[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
berTlv = berHelper.decode(close_channel.length);
|
||||||
|
ctlvs = berTlv.value;
|
||||||
|
tlv = stkHelper.searchForTag(COMPREHENSIONTLV_TAG_COMMAND_DETAILS, ctlvs);
|
||||||
|
do_check_eq(tlv.value.commandNumber, 0x01);
|
||||||
|
do_check_eq(tlv.value.typeOfCommand, STK_CMD_CLOSE_CHANNEL);
|
||||||
|
do_check_eq(tlv.value.commandQualifier, 0x00);
|
||||||
|
|
||||||
|
tlv = stkHelper.searchForTag(COMPREHENSIONTLV_TAG_ALPHA_ID, ctlvs);
|
||||||
|
do_check_eq(tlv.value.identifier, "Close");
|
||||||
|
|
||||||
|
// Receive Data
|
||||||
|
let receive_data = [
|
||||||
|
0XD0,
|
||||||
|
0X12,
|
||||||
|
0x81, 0x03, 0x01, 0x18, 0x00,
|
||||||
|
0x82, 0x02, 0x81, 0x82,
|
||||||
|
0x85, 0x07, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65 //alpha id: "Receive"
|
||||||
|
];
|
||||||
|
|
||||||
|
for (let i = 0; i < receive_data.length; i++) {
|
||||||
|
pduHelper.writeHexOctet(receive_data[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
berTlv = berHelper.decode(receive_data.length);
|
||||||
|
ctlvs = berTlv.value;
|
||||||
|
tlv = stkHelper.searchForTag(COMPREHENSIONTLV_TAG_COMMAND_DETAILS, ctlvs);
|
||||||
|
do_check_eq(tlv.value.commandNumber, 0x01);
|
||||||
|
do_check_eq(tlv.value.typeOfCommand, STK_CMD_RECEIVE_DATA);
|
||||||
|
do_check_eq(tlv.value.commandQualifier, 0x00);
|
||||||
|
|
||||||
|
tlv = stkHelper.searchForTag(COMPREHENSIONTLV_TAG_ALPHA_ID, ctlvs);
|
||||||
|
do_check_eq(tlv.value.identifier, "Receive");
|
||||||
|
|
||||||
|
// Send Data
|
||||||
|
let send_data = [
|
||||||
|
0xD0,
|
||||||
|
0x0F,
|
||||||
|
0x81, 0x03, 0x01, 0x19, 0x00,
|
||||||
|
0x82, 0x02, 0x81, 0x82,
|
||||||
|
0x85, 0x04, 0x53, 0x65, 0x6E, 0x64 //alpha id: "Send"
|
||||||
|
];
|
||||||
|
|
||||||
|
for (let i = 0; i < send_data.length; i++) {
|
||||||
|
pduHelper.writeHexOctet(send_data[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
berTlv = berHelper.decode(send_data.length);
|
||||||
|
ctlvs = berTlv.value;
|
||||||
|
tlv = stkHelper.searchForTag(COMPREHENSIONTLV_TAG_COMMAND_DETAILS, ctlvs);
|
||||||
|
do_check_eq(tlv.value.commandNumber, 0x01);
|
||||||
|
do_check_eq(tlv.value.typeOfCommand, STK_CMD_SEND_DATA);
|
||||||
|
do_check_eq(tlv.value.commandQualifier, 0x00);
|
||||||
|
|
||||||
|
tlv = stkHelper.searchForTag(COMPREHENSIONTLV_TAG_ALPHA_ID, ctlvs);
|
||||||
|
do_check_eq(tlv.value.identifier, "Send");
|
||||||
|
|
||||||
|
run_next_test();
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verify Event Download Command : Location Status
|
* Verify Event Download Command : Location Status
|
||||||
*/
|
*/
|
||||||
|
@ -301,15 +301,16 @@ public class GeckoSmsManager
|
|||||||
* defined in dom/mobilemessage/interfaces/nsISmsRequestManager.idl. They are owned
|
* defined in dom/mobilemessage/interfaces/nsISmsRequestManager.idl. They are owned
|
||||||
* owned by the interface.
|
* owned by the interface.
|
||||||
*/
|
*/
|
||||||
public final static int kNoError = 0;
|
public final static int kNoError = 0;
|
||||||
public final static int kNoSignalError = 1;
|
public final static int kNoSignalError = 1;
|
||||||
public final static int kNotFoundError = 2;
|
public final static int kNotFoundError = 2;
|
||||||
public final static int kUnknownError = 3;
|
public final static int kUnknownError = 3;
|
||||||
public final static int kInternalError = 4;
|
public final static int kInternalError = 4;
|
||||||
public final static int kNoSimCardError = 5;
|
public final static int kNoSimCardError = 5;
|
||||||
public final static int kRadioDisabledError = 6;
|
public final static int kRadioDisabledError = 6;
|
||||||
public final static int kInvalidAddressError = 7;
|
public final static int kInvalidAddressError = 7;
|
||||||
public final static int kFdnCheckError = 8;
|
public final static int kFdnCheckError = 8;
|
||||||
|
public final static int kNonActiveSimCardError = 9;
|
||||||
|
|
||||||
private final static int kMaxMessageSize = 160;
|
private final static int kMaxMessageSize = 160;
|
||||||
|
|
||||||
|
@ -37,7 +37,6 @@ import org.json.JSONObject;
|
|||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.content.ContentResolver;
|
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
@ -1475,15 +1474,6 @@ abstract public class BrowserApp extends GeckoApp
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the keywordUrl is in ReadingList, convert the url to an about:reader url and load it.
|
|
||||||
final ContentResolver cr = getContentResolver();
|
|
||||||
final boolean inReadingList = BrowserDB.isReadingListItem(cr, keywordUrl);
|
|
||||||
if (inReadingList) {
|
|
||||||
final String readerUrl = ReaderModeUtils.getAboutReaderForUrl(keywordUrl);
|
|
||||||
Tabs.getInstance().loadUrl(readerUrl, Tabs.LOADURL_USER_ENTERED);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
recordSearch(null, "barkeyword");
|
recordSearch(null, "barkeyword");
|
||||||
|
|
||||||
// Otherwise, construct a search query from the bookmark keyword.
|
// Otherwise, construct a search query from the bookmark keyword.
|
||||||
|
@ -295,15 +295,16 @@ public class GeckoSmsManager
|
|||||||
* dom/mobilemessage/src/Types.h
|
* dom/mobilemessage/src/Types.h
|
||||||
* The error code are owned by the DOM.
|
* The error code are owned by the DOM.
|
||||||
*/
|
*/
|
||||||
public final static int kNoError = 0;
|
public final static int kNoError = 0;
|
||||||
public final static int kNoSignalError = 1;
|
public final static int kNoSignalError = 1;
|
||||||
public final static int kNotFoundError = 2;
|
public final static int kNotFoundError = 2;
|
||||||
public final static int kUnknownError = 3;
|
public final static int kUnknownError = 3;
|
||||||
public final static int kInternalError = 4;
|
public final static int kInternalError = 4;
|
||||||
public final static int kNoSimCardError = 5;
|
public final static int kNoSimCardError = 5;
|
||||||
public final static int kRadioDisabledError = 6;
|
public final static int kRadioDisabledError = 6;
|
||||||
public final static int kInvalidAddressError = 7;
|
public final static int kInvalidAddressError = 7;
|
||||||
public final static int kFdnCheckError = 8;
|
public final static int kFdnCheckError = 8;
|
||||||
|
public final static int kNonActiveSimCardError = 9;
|
||||||
|
|
||||||
private final static int kMaxMessageSize = 160;
|
private final static int kMaxMessageSize = 160;
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user