Merge last PGO green changeset on inbound to m-c.

This commit is contained in:
Ryan VanderMeulen 2012-05-08 21:32:23 -04:00
Родитель fa5e947e16 ad84909722
Коммит 6d2ef14f81
181 изменённых файлов: 5258 добавлений и 2364 удалений

Просмотреть файл

@ -632,9 +632,9 @@ ApplicationAccessibleWrap::Init()
if (NS_SUCCEEDED(rv)) {
// init atk-bridge
(*sAtkBridge.init)();
}
else
} else {
MAI_LOG_DEBUG(("Fail to load lib: %s\n", sAtkBridge.libName));
}
if (!sToplevel_event_hook_added) {
sToplevel_event_hook_added = true;

Просмотреть файл

@ -1382,10 +1382,11 @@ nsresult
nsAccessibleWrap::FireAtkShowHideEvent(AccEvent* aEvent,
AtkObject *aObject, bool aIsAdded)
{
if (aIsAdded)
if (aIsAdded) {
MAI_LOG_DEBUG(("\n\nReceived: Show event\n"));
else
} else {
MAI_LOG_DEBUG(("\n\nReceived: Hide event\n"));
}
PRInt32 indexInParent = getIndexInParentCB(aObject);
AtkObject *parentObject = getParentCB(aObject);

Просмотреть файл

@ -280,7 +280,7 @@ XULDescriptionIterator::Next()
IDRefsIterator::
IDRefsIterator(nsDocAccessible* aDoc, nsIContent* aContent,
nsIAtom* aIDRefsAttr) :
mCurrIdx(0), mContent(aContent), mDoc(aDoc)
mContent(aContent), mDoc(aDoc), mCurrIdx(0)
{
if (mContent->IsInDoc())
mContent->GetAttr(kNameSpaceID_None, aIDRefsAttr, mIDs);

Просмотреть файл

@ -63,8 +63,8 @@ public:
* Constructor. Used to expose default text attributes.
*/
TextAttrsMgr(nsHyperTextAccessible* aHyperTextAcc) :
mHyperTextAcc(aHyperTextAcc), mIncludeDefAttrs(true),
mOffsetAcc(nsnull), mOffsetAccIdx(-1) { }
mOffsetAcc(nsnull), mHyperTextAcc(aHyperTextAcc),
mOffsetAccIdx(-1), mIncludeDefAttrs(true) { }
/**
* Constructor. Used to expose text attributes at the given offset.
@ -82,8 +82,8 @@ public:
bool aIncludeDefAttrs,
nsAccessible* aOffsetAcc,
PRInt32 aOffsetAccIdx) :
mHyperTextAcc(aHyperTextAcc), mIncludeDefAttrs(aIncludeDefAttrs),
mOffsetAcc(aOffsetAcc), mOffsetAccIdx(aOffsetAccIdx) { }
mOffsetAcc(aOffsetAcc), mHyperTextAcc(aHyperTextAcc),
mOffsetAccIdx(aOffsetAccIdx), mIncludeDefAttrs(aIncludeDefAttrs) { }
/*
* Return text attributes and hyper text offsets where these attributes are
@ -118,8 +118,8 @@ protected:
private:
nsAccessible* mOffsetAcc;
nsHyperTextAccessible* mHyperTextAcc;
PRInt32 mOffsetAccIdx;
bool mIncludeDefAttrs;
PRInt32 mOffsetAccIdx;
bool mIncludeDefAttrs;
protected:

Просмотреть файл

@ -301,8 +301,8 @@
; JavaScript components
@BINPATH@/components/ConsoleAPI.manifest
@BINPATH@/components/ConsoleAPI.js
@BINPATH@/components/BrowserElementAPI.manifest
@BINPATH@/components/BrowserElementAPI.js
@BINPATH@/components/BrowserElementParent.manifest
@BINPATH@/components/BrowserElementParent.js
@BINPATH@/components/ContactManager.js
@BINPATH@/components/ContactManager.manifest
@BINPATH@/components/FeedProcessor.manifest

Просмотреть файл

@ -1147,9 +1147,14 @@ pref("browser.newtab.url", "about:newtab");
// Toggles the content of 'about:newtab'. Shows the grid when enabled.
pref("browser.newtabpage.enabled", true);
// Enable the DOM full-screen API.
// Enable the DOM fullscreen API.
pref("full-screen-api.enabled", true);
// True if the fullscreen API requires approval upon a domain entering fullscreen.
// Domains that have already had fullscreen permission granted won't re-request
// approval.
pref("full-screen-api.approval-required", true);
// Startup Crash Tracking
// number of startup crashes that can occur before starting into safe mode automatically
// (this pref has no effect if more than 6 hours have passed since the last crash)

Просмотреть файл

@ -372,6 +372,16 @@ window[chromehidden~="toolbar"] toolbar:not(.toolbar-primary):not(.chromeclass-m
#full-screen-warning-message {
pointer-events: auto;
/* We must specify a max-width, otherwise word-wrap:break-word doesn't
work in descendant <description> and <label> elements. Bug 630864. */
max-width: 800px;
}
#full-screen-domain-text,
#full-screen-remember-decision > .checkbox-label-box > .checkbox-label {
word-wrap: break-word;
/* We must specify a min-width, otherwise word-wrap:break-word doesn't work. Bug 630864. */
min-width: 1px;
}
#nav-bar[mode="text"] > #window-controls > toolbarbutton > .toolbarbutton-icon {

Просмотреть файл

@ -434,7 +434,7 @@ function findChildShell(aDocument, aDocShell, aSoughtURI) {
var gPopupBlockerObserver = {
_reportButton: null,
onReportButtonClick: function (aEvent)
{
if (aEvent.button != 0 || aEvent.target != this._reportButton)
@ -564,7 +564,7 @@ var gPopupBlockerObserver = {
if (pageReport) {
for (var i = 0; i < pageReport.length; ++i) {
// popupWindowURI will be null if the file picker popup is blocked.
// xxxdz this should make the option say "Show file picker" and do it (Bug 590306)
// xxxdz this should make the option say "Show file picker" and do it (Bug 590306)
if (!pageReport[i].popupWindowURI)
continue;
var popupURIspec = pageReport[i].popupWindowURI.spec;
@ -1674,16 +1674,12 @@ function delayedStartup(isLoadingBlank, mustLoadSidebar) {
// Called when we enter DOM full-screen mode. Note we can already be in browser
// full-screen mode when we enter DOM full-screen mode.
window.addEventListener("mozfullscreenchange", onMozFullScreenChange, true);
// When a restricted key is pressed in DOM full-screen mode, we should display
// the "Press ESC to exit" warning message.
window.addEventListener("MozShowFullScreenWarning", onShowFullScreenWarning, true);
window.addEventListener("MozEnteredDomFullscreen", onMozEnteredDomFullscreen, true);
if (window.fullScreen)
onFullScreen();
if (document.mozFullScreen)
onMozFullScreenChange();
onMozEnteredDomFullscreen();
#ifdef MOZ_SERVICES_SYNC
// initialize the sync UI
@ -2929,12 +2925,8 @@ function onFullScreen(event) {
FullScreen.toggle(event);
}
function onMozFullScreenChange(event) {
FullScreen.enterDomFullScreen(event);
}
function onShowFullScreenWarning(event) {
FullScreen.showWarning(false);
function onMozEnteredDomFullscreen(event) {
FullScreen.enterDomFullscreen(event);
}
function getWebNavigation()
@ -3148,7 +3140,7 @@ function FillInHTMLTooltip(tipElement)
[titleText, XLinkTitleText, SVGTitleText].forEach(function (t) {
if (t && /\S/.test(t)) {
// Make CRLF and CR render one line break each.
// Make CRLF and CR render one line break each.
t = t.replace(/\r\n?/g, '\n');
tipNode.setAttribute("label", t);
@ -3483,7 +3475,7 @@ const BrowserSearch = {
}
win = window.openDialog(getBrowserURL(), "_blank",
"chrome,all,dialog=no", "about:blank");
Services.obs.addObserver(observer, "browser-delayed-startup-finished", false);
Services.obs.addObserver(observer, "browser-delayed-startup-finished", false);
}
return;
}
@ -4019,33 +4011,29 @@ var FullScreen = {
// middle of window lowering. See bug 729872.
setTimeout(this.exitDomFullScreen.bind(this), 0);
break;
case "transitionend":
if (event.propertyName == "opacity")
this.cancelWarning();
break;
}
},
enterDomFullScreen : function(event) {
if (!document.mozFullScreen) {
enterDomFullscreen : function(event) {
if (!document.mozFullScreen)
return;
// However, if we receive a "MozEnteredDomFullScreen" event for a document
// which is not a subdocument of the currently selected tab, we know that
// we've switched tabs since the request to enter full-screen was made,
// so we should exit full-screen since the "full-screen document" isn't
// acutally visible.
if (event.target.defaultView.top != gBrowser.contentWindow) {
document.mozCancelFullScreen();
return;
}
// We receive "mozfullscreenchange" events for each subdocument which
// is an ancestor of the document containing the element which requested
// full-screen. Only add listeners and show warning etc when the event we
// receive is targeted at the chrome document, i.e. only once every time
// we enter DOM full-screen mode.
if (event.target != document) {
// However, if we receive a "mozfullscreenchange" event for a document
// which is not a subdocument of the currently selected tab, we know that
// we've switched tabs since the request to enter full-screen was made,
// so we should exit full-screen since the "full-screen document" isn't
// acutally visible.
if (event.target.defaultView.top != gBrowser.contentWindow) {
document.mozCancelFullScreen();
}
return;
}
let focusManger = Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager);
if (focusManger.activeWindow != window) {
let focusManager = Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager);
if (focusManager.activeWindow != window) {
// The top-level window has lost focus since the request to enter
// full-screen was made. Cancel full-screen.
document.mozCancelFullScreen();
@ -4059,7 +4047,7 @@ var FullScreen = {
if (gFindBarInitialized)
gFindBar.close();
this.showWarning(true);
this.showWarning(event.target);
// Exit DOM full-screen mode upon open, close, or change tab.
gBrowser.tabContainer.addEventListener("TabOpen", this.exitDomFullScreen);
@ -4104,9 +4092,8 @@ var FullScreen = {
gBrowser.tabContainer.removeEventListener("TabOpen", this.exitDomFullScreen);
gBrowser.tabContainer.removeEventListener("TabClose", this.exitDomFullScreen);
gBrowser.tabContainer.removeEventListener("TabSelect", this.exitDomFullScreen);
if (!this.useLionFullScreen) {
if (!this.useLionFullScreen)
window.removeEventListener("deactivate", this);
}
}
},
@ -4240,81 +4227,116 @@ var FullScreen = {
},
cancelWarning: function(event) {
if (!this.warningBox) {
if (!this.warningBox)
return;
}
if (this.onWarningHidden) {
this.warningBox.removeEventListener("transitionend", this.onWarningHidden, false);
this.onWarningHidden = null;
}
this.fullscreenDocUri = null;
this.warningBox.removeEventListener("transitionend", this);
if (this.warningFadeOutTimeout) {
clearTimeout(this.warningFadeOutTimeout);
this.warningFadeOutTimeout = null;
}
if (this.revealBrowserTimeout) {
clearTimeout(this.revealBrowserTimeout);
this.revealBrowserTimeout = null;
}
this.warningBox.removeAttribute("fade-warning-out");
this.warningBox.removeAttribute("stop-obscuring-browser");
this.warningBox.removeAttribute("obscure-browser");
// Ensure focus switches away from the (now hidden) warning box. If the user
// clicked buttons in the fullscreen key authorization UI, it would have been
// focused, and any key events would be directed at the (now hidden) chrome
// document instead of the target document.
gBrowser.selectedBrowser.focus();
this.warningBox.setAttribute("hidden", true);
this.warningBox.removeAttribute("fade-warning-out");
this.warningBox.removeAttribute("obscure-browser");
this.warningBox = null;
},
setFullscreenAllowed: function(isApproved) {
let remember = document.getElementById("full-screen-remember-decision").checked;
if (remember)
Services.perms.add(this.fullscreenDocUri,
"fullscreen",
isApproved ? Services.perms.ALLOW_ACTION : Services.perms.DENY_ACTION,
Services.perms.EXPIRE_NEVER);
else if (isApproved) {
// The user has only temporarily approved fullscren for this domain.
// Add the permission (so Gecko knows fullscreen is approved) but add a
// listener to remove the permission when the chrome document exits fullscreen.
Services.perms.add(this.fullscreenDocUri,
"fullscreen",
Services.perms.ALLOW_ACTION,
Services.perms.EXPIRE_SESSION);
let host = this.fullscreenDocUri.host;
function onFullscreenchange(event) {
if (event.target == document && document.mozFullScreenElement == null) {
// The chrome document has left fullscreen. Remove the temporary permission grant.
Services.perms.remove(host, "fullscreen");
document.removeEventListener("mozfullscreenchange", onFullscreenchange);
}
}
document.addEventListener("mozfullscreenchange", onFullscreenchange);
}
if (this.warningBox)
this.warningBox.setAttribute("fade-warning-out", "true");
if (!isApproved)
document.mozCancelFullScreen();
},
warningBox: null,
warningFadeOutTimeout: null,
revealBrowserTimeout: null,
onWarningHidden: null,
fullscreenDocUri: null,
// Fade in a warning that document has entered full-screen, and then fade it
// out after a few seconds.
showWarning: function(obscureBackground) {
if (!document.mozFullScreen || !gPrefService.getBoolPref("full-screen-api.warning.enabled")) {
// Shows the fullscreen approval UI, or if the domain has already been approved
// for fullscreen, shows a warning that the site has entered fullscreen for a short
// duration.
showWarning: function(targetDoc) {
if (!document.mozFullScreen ||
!gPrefService.getBoolPref("full-screen-api.approval-required"))
return;
}
if (this.warningBox) {
// Warning is already showing. Reset the timer which fades out the warning message,
// and we'll restart the timer down below.
if (this.warningFadeOutTimeout) {
clearTimeout(this.warningFadeOutTimeout);
this.warningFadeOutTimeout = null;
}
} else {
// Set the strings on the fullscreen approval UI.
this.fullscreenDocUri = targetDoc.nodePrincipal.URI;
let utils = {};
Cu.import("resource://gre/modules/DownloadUtils.jsm", utils);
let [displayHost, fullHost] = utils.DownloadUtils.getURIHost(this.fullscreenDocUri.spec);
let bundle = Services.strings.createBundle("chrome://browser/locale/browser.properties");
let domainText = bundle.formatStringFromName("fullscreen.entered", [displayHost], 1);
document.getElementById("full-screen-domain-text").textContent = domainText;
let rememberText = bundle.formatStringFromName("fullscreen.rememberDecision", [displayHost], 1);
document.getElementById("full-screen-remember-decision").label = rememberText;
// Note: the warning box can be non-null if the warning box from the previous request
// wasn't hidden before another request was made.
if (!this.warningBox) {
this.warningBox = document.getElementById("full-screen-warning-container");
// Add a listener to clean up state after the warning is hidden.
this.onWarningHidden =
function(event) {
if (event.propertyName != "opacity")
return;
this.cancelWarning();
}.bind(this);
this.warningBox.addEventListener("transitionend", this.onWarningHidden, false);
this.warningBox.addEventListener("transitionend", this);
this.warningBox.removeAttribute("hidden");
}
if (obscureBackground) {
// Partially obscure the <browser> element underneath the warning panel...
// If fullscreen mode has not yet been approved for the fullscreen
// document's domain, show the approval UI and don't auto fade out the
// fullscreen warning box. Otherwise, we're just notifying of entry into
// fullscreen mode.
let isApproved =
Services.perms.testPermission(this.fullscreenDocUri, "fullscreen") == Services.perms.ALLOW_ACTION;
let authUI = document.getElementById("full-screen-approval-pane");
document.getElementById("full-screen-remember-decision").checked = false;
if (isApproved)
authUI.setAttribute("hidden", "true");
else {
// Partially obscure the <browser> element underneath the approval UI.
this.warningBox.setAttribute("obscure-browser", "true");
// ...But set a timeout to stop obscuring the browser after a few moments.
this.warningBox.removeAttribute("stop-obscuring-browser");
this.revealBrowserTimeout =
authUI.removeAttribute("hidden");
}
// If we're not showing the fullscreen approval UI, we're just notifying the user
// of the transition, so set a timeout to fade the warning out after a few moments.
if (isApproved)
this.warningFadeOutTimeout =
setTimeout(
function() {
if (this.warningBox)
this.warningBox.setAttribute("stop-obscuring-browser", "true");
this.warningBox.setAttribute("fade-warning-out", "true");
}.bind(this),
1250);
}
// Set a timeout to fade the warning out after a few moments.
this.warningFadeOutTimeout =
setTimeout(
function() {
if (this.warningBox)
this.warningBox.setAttribute("fade-warning-out", "true");
}.bind(this),
3000);
3000);
},
mouseoverToggle: function(aShow, forceHide)
@ -6146,7 +6168,7 @@ function UpdateCharsetDetector(target) {
prefvalue = gPrefService.getComplexValue("intl.charset.detector", Ci.nsIPrefLocalizedString).data;
}
catch (ex) {}
if (!prefvalue)
prefvalue = "off";
@ -9127,12 +9149,12 @@ XPCOMUtils.defineLazyGetter(this, "HUDConsoleUI", function () {
}
});
// Prompt user to restart the browser in safe mode
// Prompt user to restart the browser in safe mode
function safeModeRestart()
{
// prompt the user to confirm
// prompt the user to confirm
let promptTitle = gNavigatorBundle.getString("safeModeRestartPromptTitle");
let promptMessage =
let promptMessage =
gNavigatorBundle.getString("safeModeRestartPromptMessage");
let restartText = gNavigatorBundle.getString("safeModeRestartButton");
let buttonFlags = (Services.prompt.BUTTON_POS_0 *

Просмотреть файл

@ -409,7 +409,7 @@
<label class="tooltip-label" value="&backForwardButtonMenu.tooltip;"/>
#endif
</tooltip>
<tooltip id="forward-button-tooltip">
<label class="tooltip-label" value="&forwardButton.tooltip;"/>
#ifdef XP_MACOSX
@ -989,9 +989,22 @@
<hbox id="full-screen-warning-container" hidden="true" fadeout="true">
<hbox style="width: 100%;" pack="center"> <!-- Inner hbox needed due to bug 579776. -->
<hbox id="full-screen-warning-message">
<description id="full-screen-warning-text" value="&domFullScreenWarning.label;"></description>
</hbox>
<vbox id="full-screen-warning-message" align="center">
<description id="full-screen-domain-text"/>
<description class="full-screen-description" value="&fullscreenExitHint.value;"/>
<vbox id="full-screen-approval-pane" align="center">
<description class="full-screen-description" value="&fullscreenApproval.value;"/>
<hbox>
<button label="&fullscreenAllowButton.label;"
oncommand="FullScreen.setFullscreenAllowed(true);"
class="full-screen-approval-button"/>
<button label="&fullscreenExitButton.label;"
oncommand="FullScreen.setFullscreenAllowed(false);"
class="full-screen-approval-button"/>
</hbox>
<checkbox id="full-screen-remember-decision"/>
</vbox>
</vbox>
</hbox>
</hbox>

Просмотреть файл

@ -89,6 +89,7 @@
<command id="cmd_popupDef" oncommand="onCheckboxClick('popup');"/>
<command id="cmd_cookieDef" oncommand="onCheckboxClick('cookie');"/>
<command id="cmd_installDef" oncommand="onCheckboxClick('install');"/>
<command id="cmd_fullscreenDef" oncommand="onCheckboxClick('fullscreen');"/>
<command id="cmd_geoDef" oncommand="onCheckboxClick('geo');"/>
<command id="cmd_indexedDBDef" oncommand="onCheckboxClick('indexedDB');"/>
<command id="cmd_pluginsDef" oncommand="onCheckboxClick('plugins');"/>
@ -96,6 +97,7 @@
<command id="cmd_popupToggle" oncommand="onRadioClick('popup');"/>
<command id="cmd_cookieToggle" oncommand="onRadioClick('cookie');"/>
<command id="cmd_installToggle" oncommand="onRadioClick('install');"/>
<command id="cmd_fullscreenToggle" oncommand="onRadioClick('fullscreen');"/>
<command id="cmd_geoToggle" oncommand="onRadioClick('geo');"/>
<command id="cmd_indexedDBToggle" oncommand="onRadioClick('indexedDB');"/>
<command id="cmd_pluginsToggle" oncommand="onRadioClick('plugins');"/>
@ -416,6 +418,19 @@
</radiogroup>
</hbox>
</vbox>
<vbox class="permission">
<label class="permissionLabel" id="permFullscreenLabel"
value="&permFullscreen;" control="fullscreenRadioGroup"/>
<hbox role="group" aria-labelledby="permFullscreenLabel">
<checkbox id="fullscreenDef" command="cmd_fullscreenDef" label="&permUseDefault;"/>
<spacer flex="1"/>
<radiogroup id="fullscreenRadioGroup" orient="horizontal">
<radio id="fullscreen#0" command="cmd_fullscreenToggle" label="&permAskAlways;"/>
<radio id="fullscreen#1" command="cmd_fullscreenToggle" label="&permAllow;"/>
<radio id="fullscreen#2" command="cmd_fullscreenToggle" label="&permBlock;"/>
</radiogroup>
</hbox>
</vbox>
</vbox>
</vbox>

Просмотреть файл

@ -33,9 +33,11 @@
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
const ALLOW = nsIPermissionManager.ALLOW_ACTION; // 1
const BLOCK = nsIPermissionManager.DENY_ACTION; // 2
const SESSION = nsICookiePermission.ACCESS_SESSION;// 8
const UNKNOWN = nsIPermissionManager.UNKNOWN_ACTION; // 0
const ALLOW = nsIPermissionManager.ALLOW_ACTION; // 1
const BLOCK = nsIPermissionManager.DENY_ACTION; // 2
const SESSION = nsICookiePermission.ACCESS_SESSION; // 8
const nsIIndexedDatabaseManager =
Components.interfaces.nsIIndexedDatabaseManager;
@ -88,6 +90,10 @@ var gPermObj = {
if (gPrefs.getBoolPref("plugins.click_to_play"))
return BLOCK;
return ALLOW;
},
fullscreen: function getFullscreenDefaultPermissions()
{
return UNKNOWN;
}
};
@ -200,6 +206,9 @@ function onRadioClick(aPartId)
if (aPartId == "indexedDB" && permission == BLOCK) {
permissionManager.remove(gPermURI.host, "indexedDB-unlimited");
}
if (aPartId == "fullscreen" && permission == UNKNOWN) {
permissionManager.remove(gPermURI.host, "fullscreen");
}
}
function setRadioState(aPartId, aValue)

Просмотреть файл

@ -364,6 +364,17 @@ let PermissionDefaults = {
set plugins(aValue) {
let value = (aValue != this.ALLOW);
Services.prefs.setBoolPref("plugins.click_to_play", value);
},
get fullscreen() {
if (!Services.prefs.getBoolPref("full-screen-api.enabled")) {
return this.DENY;
}
return this.UNKNOWN;
},
set fullscreen(aValue) {
let value = (aValue != this.DENY);
Services.prefs.setBoolPref("full-screen-api.enabled", value);
}
}
@ -403,12 +414,12 @@ let AboutPermissions = {
*
* Potential future additions: "sts/use", "sts/subd"
*/
_supportedPermissions: ["password", "cookie", "geo", "indexedDB", "popup", "plugins"],
_supportedPermissions: ["password", "cookie", "geo", "indexedDB", "popup", "plugins", "fullscreen"],
/**
* Permissions that don't have a global "Allow" option.
*/
_noGlobalAllow: ["geo", "indexedDB"],
_noGlobalAllow: ["geo", "indexedDB", "fullscreen"],
/**
* Permissions that don't have a global "Deny" option.
@ -436,6 +447,7 @@ let AboutPermissions = {
Services.prefs.addObserver("dom.indexedDB.enabled", this, false);
Services.prefs.addObserver("dom.disable_open_during_load", this, false);
Services.prefs.addObserver("plugins.click_to_play", this, false);
Services.prefs.addObserver("full-screen-api.enabled", this, false);
Services.obs.addObserver(this, "perm-changed", false);
Services.obs.addObserver(this, "passwordmgr-storage-changed", false);
@ -457,6 +469,7 @@ let AboutPermissions = {
Services.prefs.removeObserver("dom.indexedDB.enabled", this, false);
Services.prefs.removeObserver("dom.disable_open_during_load", this, false);
Services.prefs.removeObserver("plugins.click_to_play", this, false);
Services.prefs.removeObserver("full-screen-api.enabled", this, false);
Services.obs.removeObserver(this, "perm-changed", false);
Services.obs.removeObserver(this, "passwordmgr-storage-changed", false);

Просмотреть файл

@ -244,6 +244,27 @@
</vbox>
</hbox>
<!-- Fullscreen -->
<hbox id="fullscreen-pref-item"
class="pref-item" align="top">
<image class="pref-icon" type="fullscreen"/>
<vbox>
<label class="pref-title" value="&fullscreen.label;"/>
<hbox align="center">
<menulist id="fullscreen-menulist"
class="pref-menulist"
type="fullscreen"
oncommand="AboutPermissions.onPermissionCommand(event);">
<menupopup>
<menuitem id="fullscreen-0" value="0" label="&permission.alwaysAsk;"/>
<menuitem id="fullscreen-1" value="1" label="&permission.allow;"/>
<menuitem id="fullscreen-2" value="2" label="&permission.block;"/>
</menupopup>
</menulist>
</hbox>
</vbox>
</hbox>
</vbox>
</hbox>

Просмотреть файл

@ -22,16 +22,18 @@ const TEST_PERMS = {
"geo": PERM_UNKNOWN,
"indexedDB": PERM_UNKNOWN,
"popup": PERM_DENY,
"plugins" : PERM_ALLOW
"plugins" : PERM_ALLOW,
"fullscreen" : PERM_UNKNOWN,
};
const NO_GLOBAL_ALLOW = [
"geo",
"indexedDB"
"indexedDB",
"fullscreen"
];
// number of managed permissions in the interface
const TEST_PERMS_COUNT = 6;
const TEST_PERMS_COUNT = 7;
function test() {
waitForExplicitFinish();

Просмотреть файл

@ -107,6 +107,10 @@ let PageThumbs = {
* containing the image data.
*/
capture: function PageThumbs_capture(aWindow, aCallback) {
if (!this._prefEnabled()) {
return;
}
let telemetryCaptureTime = new Date();
let [sw, sh, scale] = this._determineCropSize(aWindow);
@ -137,6 +141,10 @@ let PageThumbs = {
* @param aCallback The function to be called when finished (optional).
*/
captureAndStore: function PageThumbs_captureAndStore(aBrowser, aCallback) {
if (!this._prefEnabled()) {
return;
}
let url = aBrowser.currentURI.spec;
let channel = aBrowser.docShell.currentDocumentChannel;
let originalURL = channel.originalURI.spec;
@ -224,7 +232,16 @@ let PageThumbs = {
this._thumbnailHeight = Math.round(height.value / 3);
}
return [this._thumbnailWidth, this._thumbnailHeight];
}
},
_prefEnabled: function PageThumbs_prefEnabled() {
try {
return Services.prefs.getBoolPref("browser.pageThumbs.enabled");
}
catch (e) {
return true;
}
},
};
let PageThumbsStorage = {

Просмотреть файл

@ -294,8 +294,8 @@
; JavaScript components
@BINPATH@/components/ConsoleAPI.manifest
@BINPATH@/components/ConsoleAPI.js
@BINPATH@/components/BrowserElementAPI.manifest
@BINPATH@/components/BrowserElementAPI.js
@BINPATH@/components/BrowserElementParent.manifest
@BINPATH@/components/BrowserElementParent.js
@BINPATH@/components/FeedProcessor.manifest
@BINPATH@/components/FeedProcessor.js
@BINPATH@/components/BrowserFeeds.manifest

Просмотреть файл

@ -90,7 +90,10 @@ can reach it easily. -->
<!ENTITY fullScreenAutohide.accesskey "H">
<!ENTITY fullScreenExit.label "Exit Full Screen Mode">
<!ENTITY fullScreenExit.accesskey "F">
<!ENTITY domFullScreenWarning.label "Press ESC to leave full-screen mode">
<!ENTITY fullscreenAllowButton.label "Allow">
<!ENTITY fullscreenExitButton.label "Deny">
<!ENTITY fullscreenApproval.value "Allow fullscreen?">
<!ENTITY fullscreenExitHint.value "Press ESC at any time to exit fullscreen.">
<!ENTITY closeWindow.label "Close Window">
<!ENTITY closeWindow.accesskey "d">

Просмотреть файл

@ -352,3 +352,8 @@ webapps.requestInstall = Do you want to install "%1$S" from this site (%2$S)?
# LOCALIZATION NOTE (telemetryOptOutPrompt): %1$S and %3$S will be replaced by
# brandFullName, and %2$S by the value of the toolkit.telemetry.server_owner preference.
telemetryOptOutPrompt = %1$S sends information about performance, hardware, usage and customizations back to %2$S to help improve %3$S.
# LOCALIZATION NOTE (fullscreen.entered): displayed when we enter HTML5 fullscreen mode, %S is the domain name of the focused website (e.g. mozilla.com).
fullscreen.entered=%S is now fullscreen.
# LOCALIZATION NOTE (fullscreen.rememberDecision): displayed when we enter HTML5 fullscreen mode, %S is the domain name of the focused website (e.g. mozilla.com).
fullscreen.rememberDecision=Remember decision for %S

Просмотреть файл

@ -99,6 +99,7 @@
<!ENTITY permInstall "Install Extensions or Themes">
<!ENTITY permGeo "Share Location">
<!ENTITY permPlugins "Activate Plugins">
<!ENTITY permFullscreen "Enter Fullscreen">
<!ENTITY permIndexedDB "Maintain Offline Storage">
<!ENTITY permClearStorage "Clear Storage">

Просмотреть файл

@ -35,3 +35,5 @@
<!ENTITY indexedDB.label "Maintain Offline Storage">
<!ENTITY popup.label "Open Pop-up Windows">
<!ENTITY fullscreen.label "Fullscreen">

Просмотреть файл

@ -207,7 +207,7 @@ menuitem.bookmark-item {
list-style-image: url("moz-icon://stock/gtk-directory?size=menu");
}
.bookmark-item[container][livemark] {
.bookmark-item[container][livemark] {
list-style-image: url("chrome://browser/skin/feeds/feedIcon16.png");
}
@ -1307,7 +1307,7 @@ toolbar[iconsize="small"] #feed-button {
}
#treecolAutoCompleteImage {
max-width : 36px;
max-width : 36px;
}
.ac-result-type-bookmark,
@ -1359,7 +1359,7 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
color: inherit !important;
}
.autocomplete-treebody::-moz-tree-cell-text(suggesthint, treecolAutoCompleteComment),
.autocomplete-treebody::-moz-tree-cell-text(suggesthint, treecolAutoCompleteComment),
.autocomplete-treebody::-moz-tree-cell-text(suggestfirst, treecolAutoCompleteComment) {
color: GrayText;
font-size: smaller;
@ -2152,7 +2152,6 @@ html|*#highlighter-nodeinfobar-pseudo-classes {
#full-screen-warning-message {
background-color: hsl(0,0%,15%);
color: white;
font-size: 32px;
border-radius: 8px;
margin-top: 30px;
padding: 30px 50px;
@ -2160,13 +2159,20 @@ html|*#highlighter-nodeinfobar-pseudo-classes {
}
#full-screen-warning-container[obscure-browser] {
background-color: rgba(0,0,0,0.75);
background-color: rgba(0,0,0,0.3);
}
#full-screen-warning-container[stop-obscuring-browser] {
-moz-transition-property: background-color;
-moz-transition-duration: 500ms;
background-color: rgba(0,0,0,0);
.full-screen-description {
font-size: 150%;
}
#full-screen-domain-text {
font-size: 300%;
}
.full-screen-approval-button,
#full-screen-remember-decision {
font-size: 120%;
}
/* Highlighter toolbar - breadcrumbs */

Просмотреть файл

@ -90,6 +90,9 @@
.pref-icon[type="plugins"] {
list-style-image: url(chrome://mozapps/skin/plugins/pluginGeneric.png);
}
.pref-icon[type="fullscreen"] {
list-style-image: url(chrome://global/skin/icons/question-64.png);
}
.pref-title {
font-size: 125%;

Просмотреть файл

@ -1207,8 +1207,8 @@ window[tabsontop="false"] richlistitem[type~="action"][actiontype="switchtab"][s
color: inherit !important;
}
.autocomplete-treebody::-moz-tree-cell-text(suggesthint, treecolAutoCompleteComment),
.autocomplete-treebody::-moz-tree-cell-text(suggestfirst, treecolAutoCompleteComment)
.autocomplete-treebody::-moz-tree-cell-text(suggesthint, treecolAutoCompleteComment),
.autocomplete-treebody::-moz-tree-cell-text(suggestfirst, treecolAutoCompleteComment)
{
color: GrayText;
font-size: smaller;
@ -1224,8 +1224,8 @@ window[tabsontop="false"] richlistitem[type~="action"][actiontype="switchtab"][s
#go-button,
#urlbar > toolbarbutton {
margin: 0;
-moz-padding-start: 2px;
-moz-padding-end: 1px;
-moz-padding-start: 2px;
-moz-padding-end: 1px;
background-origin: border-box;
list-style-image: url("chrome://browser/skin/reload-stop-go.png");
}
@ -2901,7 +2901,6 @@ html|*#highlighter-nodeinfobar-pseudo-classes {
#full-screen-warning-message {
background-color: hsl(0,0%,15%);
color: white;
font-size: 32px;
border-radius: 8px;
margin-top: 30px;
padding: 30px 50px;
@ -2909,13 +2908,20 @@ html|*#highlighter-nodeinfobar-pseudo-classes {
}
#full-screen-warning-container[obscure-browser] {
background-color: rgba(0,0,0,0.75);
background-color: rgba(0,0,0,0.3);
}
#full-screen-warning-container[stop-obscuring-browser] {
-moz-transition-property: background-color;
-moz-transition-duration: 500ms;
background-color: rgba(0,0,0,0);
.full-screen-description {
font-size: 150%;
}
#full-screen-domain-text {
font-size: 300%;
}
.full-screen-approval-button,
#full-screen-remember-decision {
font-size: 120%;
}
/* Highlighter toolbar - breadcrumbs */

Просмотреть файл

@ -94,6 +94,9 @@
.pref-icon[type="plugins"] {
list-style-image: url(chrome://mozapps/skin/plugins/pluginGeneric.png);
}
.pref-icon[type="fullscreen"] {
list-style-image: url(chrome://global/skin/icons/question-64.png);
}
.pref-title {
font-size: 125%;

Просмотреть файл

@ -603,7 +603,7 @@ menuitem.bookmark-item {
-moz-image-region: rect(16px, 32px, 32px, 16px);
}
.bookmark-item[container][livemark] {
.bookmark-item[container][livemark] {
list-style-image: url("chrome://browser/skin/livemark-folder.png");
-moz-image-region: auto;
}
@ -1299,7 +1299,7 @@ html|*.urlbar-input:-moz-lwtheme:-moz-placeholder,
.urlbar-textbox-container {
-moz-box-align: stretch;
}
.urlbar-input-box {
-moz-margin-start: 0;
}
@ -1504,7 +1504,7 @@ html|*.urlbar-input:-moz-lwtheme:-moz-placeholder,
.autocomplete-treebody::-moz-tree-image(bookmark, treecolAutoCompleteImage) {
list-style-image: url("chrome://browser/skin/places/editBookmark.png");
-moz-image-region: rect(0px 16px 16px 0px);
width: 16px;
width: 16px;
height: 16px;
}
@ -1519,7 +1519,7 @@ html|*.urlbar-input:-moz-lwtheme:-moz-placeholder,
.ac-result-type-tag,
.autocomplete-treebody::-moz-tree-image(tag, treecolAutoCompleteImage) {
list-style-image: url("chrome://browser/skin/places/tag.png");
width: 16px;
width: 16px;
height: 16px;
}
@ -1565,8 +1565,8 @@ richlistitem[type~="action"][actiontype="switchtab"][selected="true"] > .ac-url-
color: inherit !important;
}
.autocomplete-treebody::-moz-tree-cell-text(suggesthint, treecolAutoCompleteComment),
.autocomplete-treebody::-moz-tree-cell-text(suggestfirst, treecolAutoCompleteComment)
.autocomplete-treebody::-moz-tree-cell-text(suggesthint, treecolAutoCompleteComment),
.autocomplete-treebody::-moz-tree-cell-text(suggestfirst, treecolAutoCompleteComment)
{
color: GrayText;
font-size: smaller;
@ -1670,7 +1670,7 @@ richlistitem[type~="action"][actiontype="switchtab"][selected="true"] > .ac-url-
#star-button:hover {
background-image: -moz-radial-gradient(center, circle closest-side, hsla(45,100%,73%,.3), hsla(45,100%,73%,0));
-moz-image-region: rect(0px 32px 16px 16px);
-moz-image-region: rect(0px 32px 16px 16px);
}
#star-button:hover:active {
@ -2822,7 +2822,6 @@ html|*#highlighter-nodeinfobar-pseudo-classes {
#full-screen-warning-message {
background-color: hsl(0,0%,15%);
color: white;
font-size: 32px;
border-radius: 8px;
margin-top: 30px;
padding: 30px 50px;
@ -2830,13 +2829,20 @@ html|*#highlighter-nodeinfobar-pseudo-classes {
}
#full-screen-warning-container[obscure-browser] {
background-color: rgba(0,0,0,0.75);
background-color: rgba(0,0,0,0.3);
}
#full-screen-warning-container[stop-obscuring-browser] {
-moz-transition-property: background-color;
-moz-transition-duration: 500ms;
background-color: rgba(0,0,0,0);
.full-screen-description {
font-size: 150%;
}
#full-screen-domain-text {
font-size: 300%;
}
.full-screen-approval-button,
#full-screen-remember-decision {
font-size: 120%;
}
/* Highlighter toolbar - breadcrumbs */

Просмотреть файл

@ -93,6 +93,9 @@
.pref-icon[type="plugins"] {
list-style-image: url(chrome://mozapps/skin/plugins/pluginGeneric.png);
}
.pref-icon[type="fullscreen"] {
list-style-image: url(chrome://global/skin/icons/question-64.png);
}
.pref-title {
font-size: 125%;

Просмотреть файл

@ -24,6 +24,7 @@ class DeviceManagerADB(DeviceManager):
self.useZip = False
self.packageName = None
self.tempDir = None
self.deviceRoot = None
# the path to adb, or 'adb' to assume that it's on the PATH
self.adbPath = adbPath
@ -50,6 +51,9 @@ class DeviceManagerADB(DeviceManager):
# verify that we can connect to the device. can't continue
self.verifyDevice()
# set up device root
self.setupDeviceRoot()
# Can we use run-as? (currently not required)
try:
self.verifyRunAs()
@ -91,9 +95,16 @@ class DeviceManagerADB(DeviceManager):
# success: <return code>
# failure: None
def shell(self, cmd, outputfile, env=None, cwd=None):
# need to quote special characters here
# need to quote and escape special characters here
for (index, arg) in enumerate(cmd):
if arg.find(" ") or arg.find("(") or arg.find(")") or arg.find("\""):
arg.replace('&', '\&')
needsQuoting = False
for char in [ ' ', '(', ')', '"', '&' ]:
if arg.find(char):
needsQuoting = True
break
if needsQuoting:
cmd[index] = '\'%s\'' % arg
# This is more complex than you'd think because adb doesn't actually
@ -171,6 +182,9 @@ class DeviceManagerADB(DeviceManager):
result = self.runCmdAs(["shell", "mkdir", name]).stdout.read()
if 'read-only file system' in result.lower():
return None
if 'file exists' in result.lower():
return name
self.chmodDir(name)
return name
except:
@ -525,6 +539,26 @@ class DeviceManagerADB(DeviceManager):
data = p = subprocess.Popen(["ls", "-l", filename], stdout=subprocess.PIPE).stdout.read()
return data.split()[4]
# Internal method to setup the device root and cache its value
def setupDeviceRoot(self):
# /mnt/sdcard/tests is preferred to /data/local/tests, but this can be
# over-ridden by creating /data/local/tests
testRoot = "/data/local/tests"
if (self.dirExists(testRoot)):
self.deviceRoot = testRoot
return
for (basePath, subPath) in [('/mnt/sdcard', 'tests'),
('/data/local', 'tests')]:
if self.dirExists(basePath):
testRoot = os.path.join(basePath, subPath)
if self.mkDir(testRoot):
self.deviceRoot = testRoot
return
raise DMError("Unable to set up device root as /mnt/sdcard/tests "
"or /data/local/tests")
# Gets the device root for the testing area on the device
# For all devices we will use / type slashes and depend on the device-agent
# to sort those out. The agent will return us the device location where we
@ -543,22 +577,7 @@ class DeviceManagerADB(DeviceManager):
# success: path for device root
# failure: None
def getDeviceRoot(self):
# /mnt/sdcard/tests is preferred to /data/local/tests, but this can be
# over-ridden by creating /data/local/tests
testRoot = "/data/local/tests"
if (self.dirExists(testRoot)):
return testRoot
root = "/mnt/sdcard"
if self.dirExists(root):
testRoot = root + "/tests"
if self.mkDir(testRoot):
return testRoot
testRoot = "/data/local/tests"
if (not self.dirExists(testRoot)):
self.mkDir(testRoot)
return testRoot
return self.deviceRoot
# Gets the temporary directory we are using on this device
# base on our device root, ensuring also that it exists.

Просмотреть файл

@ -9,9 +9,8 @@ import StringIO
class DroidMixin(object):
"""Mixin to extend DeviceManager with Android-specific functionality"""
def launchApplication(self, app, activity="App",
intent="android.intent.action.VIEW", env=None,
url=None, extra_args=None):
def launchApplication(self, appName, activityName, intent, url=None,
extras=None):
"""
Launches an Android application
returns:
@ -19,26 +18,26 @@ class DroidMixin(object):
failure: False
"""
# only one instance of an application may be running at once
if self.processExist(app):
if self.processExist(appName):
return False
acmd = [ "am", "start", "-W", "-n", "%s/.%s" % (app, activity)]
acmd = [ "am", "start", "-W", "-n", "%s/%s" % (appName, activityName)]
if intent:
acmd.extend(["-a", intent])
if extra_args:
acmd.extend(["--es", "args", " ".join(extra_args)])
if env:
envCnt = 0
# env is expected to be a dict of environment variables
for envkey, envval in env.iteritems():
acmd.extend(["--es", "env" + str(envCnt), envkey + "=" + envval])
envCnt += 1
if extras:
for (key, val) in extras.iteritems():
if type(val) is int:
extraTypeParam = "--ei"
elif type(val) is bool:
extraTypeParam = "--ez"
else:
extraTypeParam = "--es"
acmd.extend([extraTypeParam, str(key), str(val)])
if url:
acmd.extend(["-d", ''.join(["'", url, "'"])])
acmd.extend(["-d", url])
# shell output not that interesting and debugging logs should already
# show what's going on here... so just create an empty memory buffer
@ -49,6 +48,34 @@ class DroidMixin(object):
return False
def launchFennec(self, appName, intent="android.intent.action.VIEW",
mozEnv=None, extraArgs=None, url=None):
"""
Convenience method to launch Fennec on Android with various debugging
arguments
WARNING: FIXME: This would go better in mozrunner. Please do not
use this method if you are not comfortable with it going away sometime
in the near future
returns:
success: True
failure: False
"""
extras = {}
if mozEnv:
# mozEnv is expected to be a dictionary of environment variables: Fennec
# itself will set them when launched
for (envCnt, (envkey, envval)) in enumerate(mozEnv.iteritems()):
extras["env" + str(envCnt)] = envkey + "=" + envval
# Additional command line arguments that fennec will read and use (e.g.
# with a custom profile)
if extraArgs:
extras['args'] = " ".join(extraArgs)
return self.launchApplication(appName, ".App", intent, url=url,
extras=extras)
class DroidADB(DeviceManagerADB, DroidMixin):
pass

Просмотреть файл

@ -254,6 +254,7 @@ if not os.path.exists(source_dir):
extract(gmp_source_tar, source_dir)
extract(gcc_source_tar, source_dir)
patch('plugin_finish_decl.diff', 0, gcc_source_dir)
patch('libtool-74c8993c178a1386ea5e2363a01d919738402f30.patch', 1, gcc_source_dir)
patch('pr49911.diff', 1, gcc_source_dir)
patch('r159628-r163231-r171807.patch', 1, gcc_source_dir)
patch('gcc-fixinc.patch', 1, gcc_source_dir)

Просмотреть файл

@ -0,0 +1,12 @@
diff -ruN a/ltmain.sh b/ltmain.sh
--- a/ltmain.sh 2009-12-05 12:18:53.000000000 -0500
+++ b/ltmain.sh 2012-05-07 16:19:31.871827967 -0400
@@ -2932,7 +2932,7 @@
func_extract_an_archive "$my_xdir" "$my_xabs"
;;
esac
- my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP`
+ my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP`
done
func_extract_archives_result="$my_oldobjs"

Просмотреть файл

@ -614,10 +614,17 @@ public:
static void SplitExpatName(const PRUnichar *aExpatName, nsIAtom **aPrefix,
nsIAtom **aTagName, PRInt32 *aNameSpaceID);
// Get a permission-manager setting for the given uri and type.
// Get a permission-manager setting for the given principal and type.
// If the pref doesn't exist or if it isn't ALLOW_ACTION, false is
// returned, otherwise true is returned.
static bool IsSitePermAllow(nsIURI* aURI, const char* aType);
// returned, otherwise true is returned. Always returns true for the
// system principal, and false for a null principal.
static bool IsSitePermAllow(nsIPrincipal* aPrincipal, const char* aType);
// Get a permission-manager setting for the given principal and type.
// If the pref doesn't exist or if it isn't DENY_ACTION, false is
// returned, otherwise true is returned. Always returns false for the
// system principal, and true for a null principal.
static bool IsSitePermDeny(nsIPrincipal* aPrincipal, const char* aType);
static nsILineBreaker* LineBreaker()
{
@ -1842,13 +1849,6 @@ public:
*/
static bool IsRequestFullScreenAllowed();
/**
* Returns true if key input is restricted in DOM full-screen mode
* to non-alpha-numeric key codes only. This mirrors the
* "full-screen-api.key-input-restricted" pref.
*/
static bool IsFullScreenKeyInputRestricted();
/**
* Returns true if the doc tree branch which contains aDoc contains any
* plugins which we don't control event dispatch for, i.e. do any plugins
@ -2121,7 +2121,6 @@ private:
static bool sAllowXULXBL_for_file;
static bool sIsFullScreenApiEnabled;
static bool sTrustedFullScreenOnly;
static bool sFullScreenKeyInputRestricted;
static PRUint32 sHandlingInputTimeout;
static nsHtml5StringParser* sHTMLFragmentParser;

Просмотреть файл

@ -44,6 +44,7 @@ interface nsIURI;
interface nsIFrame;
interface nsIChromeFrameMessageManager;
interface nsIVariant;
interface nsIDOMElement;
typedef unsigned long long nsContentViewId;
@ -141,7 +142,7 @@ interface nsIContentViewManager : nsISupports
readonly attribute nsIContentView rootContentView;
};
[scriptable, uuid(efc0b731-45dc-4189-8ffa-d3eeeb850977)]
[scriptable, uuid(fc338eea-47dc-475e-add7-a3933fcfa07c)]
interface nsIFrameLoader : nsISupports
{
/**
@ -272,6 +273,14 @@ interface nsIFrameLoader : nsISupports
* Defaults to true.
*/
attribute boolean clampScrollPosition;
/**
* The element which owns this frame loader.
*
* For example, if this is a frame loader for an <iframe>, this attribute
* returns the iframe element.
*/
readonly attribute nsIDOMElement ownerElement;
};
native alreadyAddRefed_nsFrameLoader(already_AddRefed<nsFrameLoader>);

Просмотреть файл

@ -288,7 +288,6 @@ nsString* nsContentUtils::sModifierSeparator = nsnull;
bool nsContentUtils::sInitialized = false;
bool nsContentUtils::sIsFullScreenApiEnabled = false;
bool nsContentUtils::sTrustedFullScreenOnly = true;
bool nsContentUtils::sFullScreenKeyInputRestricted = true;
PRUint32 nsContentUtils::sHandlingInputTimeout = 1000;
@ -425,9 +424,6 @@ nsContentUtils::Init()
Preferences::AddBoolVarCache(&sTrustedFullScreenOnly,
"full-screen-api.allow-trusted-requests-only");
Preferences::AddBoolVarCache(&sFullScreenKeyInputRestricted,
"full-screen-api.key-input-restricted");
Preferences::AddUintVarCache(&sHandlingInputTimeout,
"dom.event.handling-user-input-time-limit",
1000);
@ -2805,18 +2801,44 @@ nsContentUtils::IsDraggableLink(const nsIContent* aContent) {
return aContent->IsLink(getter_AddRefs(absURI));
}
bool
nsContentUtils::IsSitePermAllow(nsIURI* aURI, const char* aType)
static bool
TestSitePerm(nsIPrincipal* aPrincipal, const char* aType, PRUint32 aPerm)
{
if (nsContentUtils::IsSystemPrincipal(aPrincipal)) {
// System principal is always allowed and never denied permission.
return aPerm == nsIPermissionManager::ALLOW_ACTION;
}
nsCOMPtr<nsIURI> uri;
if (NS_FAILED(!aPrincipal ||
aPrincipal->GetURI(getter_AddRefs(uri))) ||
!uri) {
// We always deny (i.e. don't allow) the permission if we don't
// have a principal or we don't know the URI.
return aPerm != nsIPermissionManager::ALLOW_ACTION;
}
nsCOMPtr<nsIPermissionManager> permMgr =
do_GetService("@mozilla.org/permissionmanager;1");
NS_ENSURE_TRUE(permMgr, false);
PRUint32 perm;
nsresult rv = permMgr->TestPermission(aURI, aType, &perm);
nsresult rv = permMgr->TestPermission(uri, aType, &perm);
NS_ENSURE_SUCCESS(rv, false);
return perm == nsIPermissionManager::ALLOW_ACTION;
return perm == aPerm;
}
bool
nsContentUtils::IsSitePermAllow(nsIPrincipal* aPrincipal, const char* aType)
{
return TestSitePerm(aPrincipal, aType, nsIPermissionManager::ALLOW_ACTION);
}
bool
nsContentUtils::IsSitePermDeny(nsIPrincipal* aPrincipal, const char* aType)
{
return TestSitePerm(aPrincipal, aType, nsIPermissionManager::DENY_ACTION);
}
static const char *gEventNames[] = {"event"};
@ -3451,19 +3473,10 @@ nsContentUtils::DispatchChromeEvent(nsIDocument *aDoc,
if (!aDoc->GetWindow())
return NS_ERROR_INVALID_ARG;
nsIDOMEventTarget* piTarget = aDoc->GetWindow()->GetChromeEventHandler();
nsIDOMEventTarget* piTarget = aDoc->GetWindow()->GetParentTarget();
if (!piTarget)
return NS_ERROR_INVALID_ARG;
nsCOMPtr<nsIFrameLoaderOwner> flo = do_QueryInterface(piTarget);
if (flo) {
nsRefPtr<nsFrameLoader> fl = flo->GetFrameLoader();
if (fl) {
nsIDOMEventTarget* t = fl->GetTabChildGlobalAsEventTarget();
piTarget = t ? t : piTarget;
}
}
nsEventStatus status = nsEventStatus_eIgnore;
rv = piTarget->DispatchDOMEvent(nsnull, event, nsnull, &status);
if (aDefaultAction) {
@ -6339,7 +6352,7 @@ nsContentUtils::AllowXULXBLForPrincipal(nsIPrincipal* aPrincipal)
return princURI &&
((sAllowXULXBL_for_file && SchemeIs(princURI, "file")) ||
IsSitePermAllow(princURI, "allowXULXBL"));
IsSitePermAllow(aPrincipal, "allowXULXBL"));
}
already_AddRefed<nsIDocumentLoaderFactory>
@ -6512,19 +6525,14 @@ nsContentUtils::IsFullScreenApiEnabled()
return sIsFullScreenApiEnabled;
}
bool nsContentUtils::IsRequestFullScreenAllowed()
bool
nsContentUtils::IsRequestFullScreenAllowed()
{
return !sTrustedFullScreenOnly ||
nsEventStateManager::IsHandlingUserInput() ||
IsCallerChrome();
}
bool
nsContentUtils::IsFullScreenKeyInputRestricted()
{
return sFullScreenKeyInputRestricted;
}
static void
CheckForWindowedPlugins(nsIContent* aContent, void* aResult)
{

Просмотреть файл

@ -1702,6 +1702,7 @@ NS_INTERFACE_TABLE_HEAD(nsDocument)
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIDOMDocumentTouch)
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsITouchEventReceiver)
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIInlineEventHandlers)
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIObserver)
NS_OFFSET_AND_INTERFACE_TABLE_END
NS_OFFSET_AND_INTERFACE_TABLE_TO_MAP_SEGUE
NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsDocument)
@ -8758,6 +8759,20 @@ nsDocument::RestorePreviousFullScreenState()
} else {
// Else we popped the top of the stack, and there's still another
// element in there, so that will become the full-screen element.
if (fullScreenDoc != doc) {
// We've popped so enough off the stack that we've rolled back to
// a fullscreen element in a parent document. If this document isn't
// authorized for fullscreen, dispatch an event to chrome so it
// knows to show the authorization UI.
if (!nsContentUtils::IsSitePermAllow(doc->NodePrincipal(), "fullscreen")) {
nsRefPtr<nsAsyncDOMEvent> e =
new nsAsyncDOMEvent(doc,
NS_LITERAL_STRING("MozEnteredDomFullscreen"),
true,
true);
e->PostDOMEvent();
}
}
sFullScreenDoc = do_GetWeakReference(doc);
break;
}
@ -9076,6 +9091,13 @@ nsDocument::RequestFullScreen(Element* aElement, bool aWasCallerChrome)
DispatchFullScreenChange(changed[changed.Length() - i - 1]);
}
nsRefPtr<nsAsyncDOMEvent> e =
new nsAsyncDOMEvent(this,
NS_LITERAL_STRING("MozEnteredDomFullscreen"),
true,
true);
e->PostDOMEvent();
// Remember this is the requesting full-screen document.
sFullScreenDoc = do_GetWeakReference(static_cast<nsIDocument*>(this));
@ -9225,6 +9247,159 @@ DispatchPointerLockError(nsIDocument* aTarget)
e->PostDOMEvent();
}
// Manages asynchronously requesting pointer lock. Used to dispatch an
// event to request pointer lock once fullscreen has been approved.
class nsAsyncPointerLockRequest : public nsRunnable
{
public:
NS_IMETHOD Run()
{
sInstance = nsnull;
if (mDocument && mElement) {
mDocument->RequestPointerLock(mElement);
}
return NS_OK;
}
static void Request(Element* aElement, nsIDocument* aDocument)
{
if (sInstance) {
// We already have an event instance pending. Change the requestee
// to the new pointer lock requestee.
sInstance->mElement = aElement;
sInstance->mDocument = aDocument;
} else {
// Create a new event instance. Owning ref is held by the nsIEventTarget
// to which this is dispatched.
sInstance = new nsAsyncPointerLockRequest(aElement, aDocument);
NS_DispatchToCurrentThread(sInstance);
}
}
static void Cancel()
{
if (sInstance) {
// Revoke references to requesting element/document, when the
// dispatched event runs. The event will do nothing, and then be
// destroyed.
sInstance->mElement = nsnull;
sInstance->mDocument = nsnull;
}
}
private:
nsAsyncPointerLockRequest(Element* aElement, nsIDocument* aDocument)
: mElement(aElement),
mDocument(aDocument)
{
MOZ_COUNT_CTOR(nsAsyncPointerLockRequest);
}
~nsAsyncPointerLockRequest()
{
MOZ_COUNT_DTOR(nsAsyncPointerLockRequest);
}
// Reference to the instance of any pending event. This is not an owning
// reference; the nsIEventTarget to which this is dispatched holds the only
// owning reference to this instance. This reference is valid between
// an instance being created, and its Run() method being called.
static nsAsyncPointerLockRequest* sInstance;
// Element and document which reqested pointer lock.
nsCOMPtr<Element> mElement;
nsCOMPtr<nsIDocument> mDocument;
};
nsAsyncPointerLockRequest* nsAsyncPointerLockRequest::sInstance = nsnull;
nsWeakPtr nsDocument::sPendingPointerLockDoc;
nsWeakPtr nsDocument::sPendingPointerLockElement;
/* static */
void
nsDocument::ClearPendingPointerLockRequest(bool aDispatchErrorEvents)
{
nsAsyncPointerLockRequest::Cancel();
if (!sPendingPointerLockDoc) {
// No pending request.
return;
}
nsCOMPtr<nsIDocument> doc(do_QueryReferent(sPendingPointerLockDoc));
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
if (!os) {
NS_WARNING("Lost observer service in ClearPendingPointerLockRequest()!");
return;
}
nsCOMPtr<nsIObserver> obs(do_QueryInterface(doc));
if (!os) {
NS_WARNING("Document must implement nsIObserver");
return;
}
os->RemoveObserver(obs, "perm-changed");
if (aDispatchErrorEvents) {
DispatchPointerLockError(doc);
}
nsCOMPtr<Element> element(do_QueryReferent(sPendingPointerLockElement));
#ifdef DEBUG
nsCOMPtr<Element> pointerLockedElement =
do_QueryReferent(nsEventStateManager::sPointerLockedElement);
NS_ASSERTION(pointerLockedElement != element,
"We shouldn't be clearing pointer locked flag on pointer locked element!");
#endif
if (element) {
element->ClearPointerLock();
}
sPendingPointerLockDoc = nsnull;
sPendingPointerLockElement = nsnull;
}
/* static */
nsresult
nsDocument::SetPendingPointerLockRequest(Element* aElement)
{
// If there's an existing pending pointer lock request, deny it.
ClearPendingPointerLockRequest(true);
NS_ENSURE_TRUE(aElement != nsnull, NS_ERROR_FAILURE);
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
NS_ENSURE_TRUE(os != nsnull, NS_ERROR_FAILURE);
nsCOMPtr<nsIObserver> obs(do_QueryInterface(aElement->OwnerDoc()));
NS_ENSURE_TRUE(obs != nsnull, NS_ERROR_FAILURE);
nsresult res = os->AddObserver(obs, "perm-changed", true);
NS_ENSURE_SUCCESS(res, res);
sPendingPointerLockDoc = do_GetWeakReference(aElement->OwnerDoc());
sPendingPointerLockElement = do_GetWeakReference(aElement);
// Set the pointer lock flag, so that if the element is removed from
// its document we know to cancel the pending request.
aElement->SetPointerLock();
return NS_OK;
}
nsresult
nsDocument::Observe(nsISupports *aSubject,
const char *aTopic,
const PRUnichar *aData)
{
if (strcmp("perm-changed", aTopic) == 0) {
nsCOMPtr<nsIDocument> doc(do_QueryReferent(sPendingPointerLockDoc));
if (nsContentUtils::IsSitePermAllow(doc->NodePrincipal(), "fullscreen")) {
nsCOMPtr<Element> element(do_QueryReferent(sPendingPointerLockElement));
nsDocument::ClearPendingPointerLockRequest(false);
nsAsyncPointerLockRequest::Request(element, doc);
}
}
return NS_OK;
}
void
nsDocument::RequestPointerLock(Element* aElement)
{
@ -9238,8 +9413,25 @@ nsDocument::RequestPointerLock(Element* aElement)
return;
}
if (!ShouldLockPointer(aElement) ||
!SetPointerLock(aElement, NS_STYLE_CURSOR_NONE)) {
if (!ShouldLockPointer(aElement)) {
DispatchPointerLockError(this);
return;
}
if (!nsContentUtils::IsSitePermAllow(NodePrincipal(), "fullscreen")) {
// Domain isn't yet approved for fullscreen, so we must wait until
// it's been approved.
if (NS_FAILED(SetPendingPointerLockRequest(aElement))) {
NS_WARNING("Failed to make pointer lock request pending!");
DispatchPointerLockError(this);
}
return;
}
// If there's an existing pending pointer lock request, deny it.
nsDocument::ClearPendingPointerLockRequest(true);
if (!SetPointerLock(aElement, NS_STYLE_CURSOR_NONE)) {
DispatchPointerLockError(this);
return;
}
@ -9353,6 +9545,10 @@ nsDocument::SetPointerLock(Element* aElement, int aCursorStyle)
void
nsDocument::UnlockPointer()
{
// If our pointer lock request is pending awaiting authorization, deny the
// request.
ClearPendingPointerLockRequest(true);
if (!nsEventStateManager::sIsPointerLocked) {
return;
}

Просмотреть файл

@ -500,7 +500,8 @@ class nsDocument : public nsIDocument,
public nsIApplicationCacheContainer,
public nsStubMutationObserver,
public nsIDOMDocumentTouch,
public nsIInlineEventHandlers
public nsIInlineEventHandlers,
public nsIObserver
{
public:
typedef mozilla::dom::Element Element;
@ -788,6 +789,9 @@ public:
// nsIInlineEventHandlers
NS_DECL_NSIINLINEEVENTHANDLERS
// nsIObserver
NS_DECL_NSIOBSERVER
virtual nsresult Init();
virtual void AddXMLEventsContent(nsIContent * aXMLEventsElement);
@ -1134,6 +1138,15 @@ protected:
// document is hidden/navigation occurs.
static nsWeakPtr sFullScreenRootDoc;
// Weak reference to the document which owned the pending pointer lock
// element, at the time it requested pointer lock.
static nsWeakPtr sPendingPointerLockDoc;
// Weak reference to the element which requested pointer lock. This request
// is "pending", and will be processed once the element's document has had
// the "fullscreen" permission granted.
static nsWeakPtr sPendingPointerLockElement;
// Stack of full-screen elements. When we request full-screen we push the
// full-screen element onto this stack, and when we cancel full-screen we
// pop one off this stack, restoring the previous full-screen state
@ -1194,9 +1207,6 @@ protected:
// "mozaudioavailable" event.
bool mHasAudioAvailableListener:1;
// Whether we are currently in full-screen mode, as per the DOM API.
bool mIsFullScreen:1;
// Whether we're currently under a FlushPendingNotifications call to
// our presshell. This is used to handle flush reentry correctly.
bool mInFlush:1;
@ -1244,6 +1254,16 @@ private:
nsresult CheckFrameOptions();
nsresult InitCSP();
// Sets aElement to be the pending pointer lock element. Once this document's
// node principal's URI is granted the "fullscreen" permission, the pointer
// lock request will be processed. At any one time there can be only one
// pending pointer lock request; calling this clears the previous pending
// request.
static nsresult SetPendingPointerLockRequest(Element* aElement);
// Clears any pending pointer lock request.
static void ClearPendingPointerLockRequest(bool aDispatchErrorEvents);
/**
* See if aDocument is a child of this. If so, return the frame element in
* this document that holds currentDoc (or an ancestor).

Просмотреть файл

@ -933,6 +933,12 @@ nsFrameLoader::ShowRemoteFrame(const nsIntSize& size)
mRemoteBrowserShown = true;
EnsureMessageManager();
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
if (OwnerIsBrowserFrame() && os) {
os->NotifyObservers(NS_ISUPPORTS_CAST(nsIFrameLoader*, this),
"remote-browser-frame-shown", NULL);
}
} else {
nsRect dimensions;
NS_ENSURE_SUCCESS(GetWindowDimensions(dimensions), false);
@ -1512,11 +1518,11 @@ nsFrameLoader::MaybeCreateDocShell()
mDocShell->SetChromeEventHandler(chromeEventHandler);
}
nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(mOwnerContent);
if (browserFrame) {
bool isBrowserFrame = false;
browserFrame->GetReallyIsBrowser(&isBrowserFrame);
mDocShell->SetIsBrowserFrame(isBrowserFrame);
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
if (OwnerIsBrowserFrame() && os) {
mDocShell->SetIsBrowserFrame(true);
os->NotifyObservers(NS_ISUPPORTS_CAST(nsIFrameLoader*, this),
"in-process-browser-frame-shown", NULL);
}
// This is nasty, this code (the do_GetInterface(mDocShell) below)
@ -2182,7 +2188,7 @@ nsFrameLoader::EnsureMessageManager()
return rv;
}
if (!mIsTopLevelContent && !mRemoteFrame) {
if (!mIsTopLevelContent && !OwnerIsBrowserFrame() && !mRemoteFrame) {
return NS_OK;
}
@ -2217,10 +2223,7 @@ nsFrameLoader::EnsureMessageManager()
mRemoteBrowserShown ? this : nsnull,
static_cast<nsFrameMessageManager*>(parentManager.get()),
cx);
NS_ENSURE_TRUE(mMessageManager, NS_ERROR_OUT_OF_MEMORY);
} else
{
} else {
mMessageManager = new nsFrameMessageManager(true,
nsnull,
SendAsyncMessageToChild,
@ -2228,7 +2231,6 @@ nsFrameLoader::EnsureMessageManager()
nsnull,
static_cast<nsFrameMessageManager*>(parentManager.get()),
cx);
NS_ENSURE_TRUE(mMessageManager, NS_ERROR_OUT_OF_MEMORY);
mChildMessageManager =
new nsInProcessTabChildGlobal(mDocShell, mOwnerContent, mMessageManager);
mMessageManager->SetCallbackData(this);
@ -2241,3 +2243,11 @@ nsFrameLoader::GetTabChildGlobalAsEventTarget()
{
return static_cast<nsInProcessTabChildGlobal*>(mChildMessageManager.get());
}
NS_IMETHODIMP
nsFrameLoader::GetOwnerElement(nsIDOMElement **aElement)
{
nsCOMPtr<nsIDOMElement> ownerElement = do_QueryInterface(mOwnerContent);
ownerElement.forget(aElement);
return NS_OK;
}

Просмотреть файл

@ -285,14 +285,14 @@ public:
nsFrameMessageManager* GetFrameMessageManager() { return mMessageManager; }
mozilla::dom::Element* GetOwnerContent() { return mOwnerContent; }
void SetOwnerContent(mozilla::dom::Element* aContent);
bool ShouldClipSubdocument() { return mClipSubdocument; }
bool ShouldClampScrollPosition() { return mClampScrollPosition; }
private:
void SetOwnerContent(mozilla::dom::Element* aContent);
bool ShouldUseRemoteProcess();
/**

Просмотреть файл

@ -6482,6 +6482,20 @@ nsINode::Length() const
}
}
static const char*
GetFullScreenError(nsIDocument* aDoc)
{
if (!nsContentUtils::IsRequestFullScreenAllowed()) {
return "FullScreenDeniedNotInputDriven";
}
if (nsContentUtils::IsSitePermDeny(aDoc->NodePrincipal(), "fullscreen")) {
return "FullScreenDeniedBlocked";
}
return nsnull;
}
nsresult nsGenericElement::MozRequestFullScreen()
{
// Only grant full-screen requests if this is called from inside a trusted
@ -6489,11 +6503,12 @@ nsresult nsGenericElement::MozRequestFullScreen()
// This stops the full-screen from being abused similar to the popups of old,
// and it also makes it harder for bad guys' script to go full-screen and
// spoof the browser chrome/window and phish logins etc.
if (!nsContentUtils::IsRequestFullScreenAllowed()) {
const char* error = GetFullScreenError(OwnerDoc());
if (error) {
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
"DOM", OwnerDoc(),
nsContentUtils::eDOM_PROPERTIES,
"FullScreenDeniedNotInputDriven");
error);
nsRefPtr<nsAsyncDOMEvent> e =
new nsAsyncDOMEvent(OwnerDoc(),
NS_LITERAL_STRING("mozfullscreenerror"),

Просмотреть файл

@ -51,6 +51,7 @@
#include "nsFrameLoader.h"
#include "nsIPrivateDOMEvent.h"
#include "xpcpublic.h"
#include "nsIMozBrowserFrame.h"
bool SendSyncMessageToParent(void* aCallbackData,
const nsAString& aMessage,
@ -115,6 +116,15 @@ nsInProcessTabChildGlobal::nsInProcessTabChildGlobal(nsIDocShell* aShell,
: mDocShell(aShell), mInitialized(false), mLoadingScript(false),
mDelayedDisconnect(false), mOwner(aOwner), mChromeMessageManager(aChrome)
{
// If owner corresponds to an <iframe mozbrowser>, we'll have to tweak our
// PreHandleEvent implementation.
nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(mOwner);
bool isBrowser = false;
if (browserFrame) {
browserFrame->GetReallyIsBrowser(&isBrowser);
}
mIsBrowserFrame = isBrowser;
}
nsInProcessTabChildGlobal::~nsInProcessTabChildGlobal()
@ -270,7 +280,17 @@ nsresult
nsInProcessTabChildGlobal::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
{
aVisitor.mCanHandle = true;
aVisitor.mParentTarget = mOwner;
if (mIsBrowserFrame) {
if (mOwner) {
nsPIDOMWindow* innerWindow = mOwner->OwnerDoc()->GetInnerWindow();
if (innerWindow) {
aVisitor.mParentTarget = innerWindow->GetParentTarget();
}
}
} else {
aVisitor.mParentTarget = mOwner;
}
#ifdef DEBUG
if (mOwner) {

Просмотреть файл

@ -142,6 +142,10 @@ protected:
bool mInitialized;
bool mLoadingScript;
bool mDelayedDisconnect;
// Is this the message manager for an in-process <iframe mozbrowser>? This
// affects where events get sent, so it affects PreHandleEvent.
bool mIsBrowserFrame;
public:
nsIContent* mOwner;
nsFrameMessageManager* mChromeMessageManager;

Просмотреть файл

@ -69,6 +69,7 @@ CPPSRCS = \
DocumentRendererParent.cpp \
DocumentRendererChild.cpp \
ImageData.cpp \
WebGLExtensionCompressedTextureS3TC.cpp \
$(NULL)
ifdef MOZ_WEBGL
@ -82,6 +83,7 @@ CPPSRCS += \
WebGLExtensionStandardDerivatives.cpp \
WebGLExtensionTextureFilterAnisotropic.cpp \
WebGLExtensionLoseContext.cpp \
WebGLTexelConversions.cpp \
$(NULL)
DEFINES += -DUSE_ANGLE

Просмотреть файл

@ -501,6 +501,41 @@ WebGLContext::SetDimensions(PRInt32 width, PRInt32 height)
}
#endif
#ifdef ANDROID
// bug 736123, blacklist WebGL on Adreno
//
// The Adreno driver in WebGL context creation, specifically in the first MakeCurrent
// call on the newly created OpenGL context.
//
// Notice that we can't rely on GfxInfo for this blacklisting,
// as GfxInfo on Android currently doesn't know the GL strings, which are,
// AFAIK, the only way to identify Adreno GPUs.
//
// Somehow, the Layers' OpenGL context creation doesn't crash, and neither does
// the global GL context creation. So we currently use the Renderer() id from the
// global context. This is not future-proof, as the plan is to get rid of the global
// context soon with OMTC. We need to replace this by getting the renderer id from
// the Layers' GL context, but as with OMTC the LayerManager lives on a different
// thread, this will have to involve some message-passing.
if (!forceEnabled) {
GLContext *globalContext = GLContextProvider::GetGlobalContext();
if (!globalContext) {
// make sure that we don't forget to update this code once the globalContext
// is removed
NS_RUNTIMEABORT("No global context anymore? Then you need to update "
"this code, or force-enable WebGL.");
}
int renderer = globalContext->Renderer();
if (renderer == gl::GLContext::RendererAdreno200 ||
renderer == gl::GLContext::RendererAdreno205)
{
LogMessage("WebGL blocked on this Adreno driver!");
return NS_ERROR_FAILURE;
}
}
#endif
// if we're forcing osmesa, do it first
if (forceOSMesa) {
gl = gl::GLContextProviderOSMesa::CreateOffscreen(gfxIntSize(width, height), format);
@ -883,10 +918,13 @@ bool WebGLContext::IsExtensionSupported(WebGLExtensionID ei)
case WebGL_EXT_texture_filter_anisotropic:
isSupported = gl->IsExtensionSupported(GLContext::EXT_texture_filter_anisotropic);
break;
case WebGL_MOZ_WEBGL_lose_context:
case WebGL_WEBGL_lose_context:
// We always support this extension.
isSupported = true;
break;
case WebGL_WEBGL_compressed_texture_s3tc:
isSupported = gl->IsExtensionSupported(GLContext::EXT_texture_compression_s3tc);
break;
default:
isSupported = false;
}
@ -927,8 +965,12 @@ WebGLContext::GetExtension(const nsAString& aName)
ei = WebGL_EXT_texture_filter_anisotropic;
}
else if (aName.EqualsLiteral("MOZ_WEBGL_lose_context")) {
if (IsExtensionSupported(WebGL_MOZ_WEBGL_lose_context))
ei = WebGL_MOZ_WEBGL_lose_context;
if (IsExtensionSupported(WebGL_WEBGL_lose_context))
ei = WebGL_WEBGL_lose_context;
}
else if (aName.EqualsLiteral("MOZ_WEBGL_compressed_texture_s3tc")) {
if (IsExtensionSupported(WebGL_WEBGL_compressed_texture_s3tc))
ei = WebGL_WEBGL_compressed_texture_s3tc;
}
if (ei != WebGLExtensionID_Max) {
@ -940,9 +982,12 @@ WebGLContext::GetExtension(const nsAString& aName)
case WebGL_EXT_texture_filter_anisotropic:
mEnabledExtensions[ei] = new WebGLExtensionTextureFilterAnisotropic(this);
break;
case WebGL_MOZ_WEBGL_lose_context:
case WebGL_WEBGL_lose_context:
mEnabledExtensions[ei] = new WebGLExtensionLoseContext(this);
break;
case WebGL_WEBGL_compressed_texture_s3tc:
mEnabledExtensions[ei] = new WebGLExtensionCompressedTextureS3TC(this);
break;
// create an extension for any types that don't
// have any additional tokens or methods
default:
@ -1518,8 +1563,10 @@ WebGLContext::GetSupportedExtensions(Nullable< nsTArray<nsString> > &retval)
arr.AppendElement(NS_LITERAL_STRING("OES_standard_derivatives"));
if (IsExtensionSupported(WebGL_EXT_texture_filter_anisotropic))
arr.AppendElement(NS_LITERAL_STRING("MOZ_EXT_texture_filter_anisotropic"));
if (IsExtensionSupported(WebGL_MOZ_WEBGL_lose_context))
if (IsExtensionSupported(WebGL_WEBGL_lose_context))
arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_lose_context"));
if (IsExtensionSupported(WebGL_WEBGL_compressed_texture_s3tc))
arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_compressed_texture_s3tc"));
}
NS_IMETHODIMP

Просмотреть файл

@ -128,16 +128,51 @@ struct BackbufferClearingStatus {
enum { NotClearedSinceLastPresented, ClearedToDefaultValues, HasBeenDrawnTo };
};
struct WebGLTexelFormat {
enum { Generic, Auto, RGBA8, RGB8, RGBX8, BGRA8, BGR8, BGRX8, RGBA5551, RGBA4444, RGB565, R8, RA8, A8,
RGBA32F, RGB32F, A32F, R32F, RA32F };
namespace WebGLTexelConversions {
/*
* The formats that may participate, either as source or destination formats,
* in WebGL texture conversions. This includes:
* - all the formats accepted by WebGL.texImage2D, e.g. RGBA4444
* - additional formats provided by extensions, e.g. RGB32F
* - additional source formats, depending on browser details, used when uploading
* textures from DOM elements. See gfxImageSurface::Format().
*/
enum WebGLTexelFormat
{
// dummy error code returned by GetWebGLTexelFormat in error cases,
// after assertion failure (so this never happens in debug builds)
BadFormat,
// dummy pseudo-format meaning "use the other format".
// For example, if SrcFormat=Auto and DstFormat=RGB8, then the source
// is implicitly treated as being RGB8 itself.
Auto,
// 1-channel formats
R8,
A8,
R32F, // used for OES_texture_float extension
A32F, // used for OES_texture_float extension
// 2-channel formats
RA8,
RA32F,
// 3-channel formats
RGB8,
BGRX8, // used for DOM elements. Source format only.
RGB565,
RGB32F, // used for OES_texture_float extension
// 4-channel formats
RGBA8,
BGRA8, // used for DOM elements
RGBA5551,
RGBA4444,
RGBA32F // used for OES_texture_float extension
};
struct WebGLTexelPremultiplicationOp {
enum { Generic, None, Premultiply, Unmultiply };
};
} // end namespace WebGLTexelConversions
int GetWebGLTexelFormat(GLenum format, GLenum type);
using WebGLTexelConversions::WebGLTexelFormat;
WebGLTexelFormat GetWebGLTexelFormat(GLenum format, GLenum type);
// Zero is not an integer power of two.
inline bool is_pot_assuming_nonnegative(WebGLsizei x)
@ -536,6 +571,7 @@ class WebGLContext :
{
friend class WebGLMemoryMultiReporterWrapper;
friend class WebGLExtensionLoseContext;
friend class WebGLExtensionCompressedTextureS3TC;
friend class WebGLContextUserData;
friend class WebGLMemoryPressureObserver;
@ -1160,7 +1196,8 @@ protected:
WebGL_OES_texture_float,
WebGL_OES_standard_derivatives,
WebGL_EXT_texture_filter_anisotropic,
WebGL_MOZ_WEBGL_lose_context,
WebGL_WEBGL_lose_context,
WebGL_WEBGL_compressed_texture_s3tc,
WebGLExtensionID_Max
};
nsAutoTArray<nsRefPtr<WebGLExtension>, WebGLExtensionID_Max> mEnabledExtensions;
@ -1170,6 +1207,8 @@ protected:
}
bool IsExtensionSupported(WebGLExtensionID ei);
nsTArray<WebGLenum> mCompressedTextureFormats;
bool InitAndValidateGL();
bool ValidateBuffers(PRInt32* maxAllowedCount, const char *info);
bool ValidateCapabilityEnum(WebGLenum cap, const char *info);
@ -1192,7 +1231,11 @@ protected:
bool ValidateGLSLCharacter(PRUnichar c);
bool ValidateGLSLString(const nsAString& string, const char *info);
static PRUint32 GetTexelSize(WebGLenum format, WebGLenum type);
bool ValidateTexImage2DTarget(WebGLenum target, WebGLsizei width, WebGLsizei height, const char* info);
bool ValidateCompressedTextureSize(WebGLint level, WebGLenum format, WebGLsizei width, WebGLsizei height, uint32_t byteLength, const char* info);
bool ValidateLevelWidthHeightForTarget(WebGLenum target, WebGLint level, WebGLsizei width, WebGLsizei height, const char* info);
static PRUint32 GetBitsPerTexel(WebGLenum format, WebGLenum type);
void Invalidate();
void DestroyResourcesAndContext();
@ -1205,26 +1248,26 @@ protected:
WebGLenum format, WebGLenum type,
void *data, PRUint32 byteLength,
int jsArrayType,
int srcFormat, bool srcPremultiplied);
WebGLTexelFormat srcFormat, bool srcPremultiplied);
void TexSubImage2D_base(WebGLenum target, WebGLint level,
WebGLint xoffset, WebGLint yoffset,
WebGLsizei width, WebGLsizei height, WebGLsizei srcStrideOrZero,
WebGLenum format, WebGLenum type,
void *pixels, PRUint32 byteLength,
int jsArrayType,
int srcFormat, bool srcPremultiplied);
WebGLTexelFormat srcFormat, bool srcPremultiplied);
void TexParameter_base(WebGLenum target, WebGLenum pname,
WebGLint *intParamPtr, WebGLfloat *floatParamPtr);
void ConvertImage(size_t width, size_t height, size_t srcStride, size_t dstStride,
const PRUint8*src, PRUint8 *dst,
int srcFormat, bool srcPremultiplied,
int dstFormat, bool dstPremultiplied,
WebGLTexelFormat srcFormat, bool srcPremultiplied,
WebGLTexelFormat dstFormat, bool dstPremultiplied,
size_t dstTexelSize);
nsresult DOMElementToImageSurface(dom::Element* imageOrCanvas,
gfxImageSurface **imageOut,
int *format);
WebGLTexelFormat *format);
void CopyTexSubImage2D_base(WebGLenum target,
WebGLint level,
@ -1678,8 +1721,8 @@ public:
PRInt64 MemoryUsage() const {
if (!mIsDefined)
return 0;
PRInt64 texelSize = WebGLContext::GetTexelSize(mFormat, mType);
return PRInt64(mWidth) * PRInt64(mHeight) * texelSize;
PRInt64 texelSizeInBits = WebGLContext::GetBitsPerTexel(mFormat, mType);
return PRInt64(mWidth) * PRInt64(mHeight) * texelSizeInBits / 8;
}
WebGLenum Format() const { return mFormat; }
WebGLenum Type() const { return mType; }

Просмотреть файл

@ -46,7 +46,6 @@
#include "gfxImageSurface.h"
#include "gfxContext.h"
#include "gfxPlatform.h"
//#include "nsIDOMHTMLCanvasElement.h"
#include "nsContentUtils.h"
#include "nsDOMError.h"
@ -2483,7 +2482,8 @@ WebGLContext::GetParameter(JSContext* cx, WebGLenum pname, ErrorResult& rv)
return JS::Int32Value(0);
case LOCAL_GL_COMPRESSED_TEXTURE_FORMATS:
{
JSObject* obj = Uint32Array::Create(cx, 0);
PRUint32 length = mCompressedTextureFormats.Length();
JSObject* obj = Uint32Array::Create(cx, length, mCompressedTextureFormats.Elements());
if (!obj) {
rv = NS_ERROR_OUT_OF_MEMORY;
}
@ -4296,198 +4296,9 @@ WebGLContext::StencilOpSeparate(WebGLenum face, WebGLenum sfail, WebGLenum dpfai
gl->fStencilOpSeparate(face, sfail, dpfail, dppass);
}
struct WebGLImageConverter
{
bool flip;
size_t width, height, srcStride, dstStride, srcTexelSize, dstTexelSize;
const PRUint8 *src;
PRUint8 *dst;
WebGLImageConverter()
{
memset(this, 0, sizeof(WebGLImageConverter));
}
template<typename SrcType, typename DstType, typename UnpackType,
void unpackingFunc(const SrcType*, UnpackType*),
void packingFunc(const UnpackType*, DstType*)>
void run()
{
// Note -- even though the functions take UnpackType, the
// pointers below are all in terms of PRUint8; otherwise
// pointer math starts getting tricky.
for (size_t src_row = 0; src_row < height; ++src_row) {
size_t dst_row = flip ? (height - 1 - src_row) : src_row;
PRUint8 *dst_row_ptr = dst + dst_row * dstStride;
const PRUint8 *src_row_ptr = src + src_row * srcStride;
const PRUint8 *src_row_end = src_row_ptr + width * srcTexelSize; // != src_row_ptr + byteStride
while (src_row_ptr != src_row_end) {
UnpackType tmp[4];
unpackingFunc(reinterpret_cast<const SrcType*>(src_row_ptr), tmp);
packingFunc(tmp, reinterpret_cast<DstType*>(dst_row_ptr));
src_row_ptr += srcTexelSize;
dst_row_ptr += dstTexelSize;
}
}
}
};
void
WebGLContext::ConvertImage(size_t width, size_t height, size_t srcStride, size_t dstStride,
const PRUint8*src, PRUint8 *dst,
int srcFormat, bool srcPremultiplied,
int dstFormat, bool dstPremultiplied,
size_t dstTexelSize)
{
if (width <= 0 || height <= 0)
return;
if (srcFormat == dstFormat &&
srcPremultiplied == dstPremultiplied)
{
// fast exit path: we just have to memcpy all the rows.
//
// The case where absolutely nothing needs to be done is supposed to have
// been handled earlier (in TexImage2D_base, etc).
//
// So the case we're handling here is when even though no format conversion is needed,
// we still might have to flip vertically and/or to adjust to a different stride.
NS_ASSERTION(mPixelStoreFlipY || srcStride != dstStride, "Performance trap -- should handle this case earlier, to avoid memcpy");
size_t row_size = width * dstTexelSize; // doesn't matter, src and dst formats agree
const PRUint8* src_row = src;
const PRUint8* src_end = src + height * srcStride;
PRUint8* dst_row = mPixelStoreFlipY ? dst + (height-1) * dstStride : dst;
ptrdiff_t dstStrideSigned(dstStride);
ptrdiff_t dst_delta = mPixelStoreFlipY ? -dstStrideSigned : dstStrideSigned;
while(src_row != src_end) {
memcpy(dst_row, src_row, row_size);
src_row += srcStride;
dst_row += dst_delta;
}
return;
}
WebGLImageConverter converter;
converter.flip = mPixelStoreFlipY;
converter.width = width;
converter.height = height;
converter.srcStride = srcStride;
converter.dstStride = dstStride;
converter.dstTexelSize = dstTexelSize;
converter.src = src;
converter.dst = dst;
int premultiplicationOp = (!srcPremultiplied && dstPremultiplied) ? WebGLTexelPremultiplicationOp::Premultiply
: (srcPremultiplied && !dstPremultiplied) ? WebGLTexelPremultiplicationOp::Unmultiply
: WebGLTexelPremultiplicationOp::None;
#define HANDLE_DSTFORMAT(format, SrcType, DstType, unpackFunc, packFunc) \
case WebGLTexelFormat::format: \
switch (premultiplicationOp) { \
case WebGLTexelPremultiplicationOp::Premultiply: \
converter.run<SrcType, DstType, PRUint8, \
WebGLTexelConversions::unpackFunc, \
WebGLTexelConversions::packFunc##Premultiply>(); \
break; \
case WebGLTexelPremultiplicationOp::Unmultiply: \
converter.run<SrcType, DstType, PRUint8, \
WebGLTexelConversions::unpackFunc, \
WebGLTexelConversions::packFunc##Unmultiply>(); \
break; \
default: \
converter.run<SrcType, DstType, PRUint8, \
WebGLTexelConversions::unpackFunc, \
WebGLTexelConversions::packFunc>(); \
break; \
} \
break;
#define HANDLE_SRCFORMAT(format, size, SrcType, unpackFunc) \
case WebGLTexelFormat::format: \
converter.srcTexelSize = size; \
switch (dstFormat) { \
HANDLE_DSTFORMAT(RGBA8, SrcType, PRUint8, unpackFunc, packRGBA8ToRGBA8) \
HANDLE_DSTFORMAT(RGB8, SrcType, PRUint8, unpackFunc, packRGBA8ToRGB8) \
HANDLE_DSTFORMAT(R8, SrcType, PRUint8, unpackFunc, packRGBA8ToR8) \
HANDLE_DSTFORMAT(RA8, SrcType, PRUint8, unpackFunc, packRGBA8ToRA8) \
HANDLE_DSTFORMAT(RGBA5551, SrcType, PRUint16, unpackFunc, packRGBA8ToUnsignedShort5551) \
HANDLE_DSTFORMAT(RGBA4444, SrcType, PRUint16, unpackFunc, packRGBA8ToUnsignedShort4444) \
HANDLE_DSTFORMAT(RGB565, SrcType, PRUint16, unpackFunc, packRGBA8ToUnsignedShort565) \
/* A8 needs to be special-cased as it doesn't have color channels to premultiply */ \
case WebGLTexelFormat::A8: \
converter.run<SrcType, PRUint8, PRUint8, \
WebGLTexelConversions::unpackFunc, \
WebGLTexelConversions::packRGBA8ToA8>(); \
break; \
default: \
NS_ASSERTION(false, "Coding error?! Should never reach this point."); \
return; \
} \
break;
#define HANDLE_FLOAT_DSTFORMAT(format, unpackFunc, packFunc) \
case WebGLTexelFormat::format: \
switch (premultiplicationOp) { \
case WebGLTexelPremultiplicationOp::Premultiply: \
converter.run<float, float, float, \
WebGLTexelConversions::unpackFunc, \
WebGLTexelConversions::packFunc##Premultiply>(); \
break; \
case WebGLTexelPremultiplicationOp::Unmultiply: \
NS_ASSERTION(false, "Floating point can't be un-premultiplied -- we have no premultiplied source data!"); \
break; \
default: \
converter.run<float, float, float, \
WebGLTexelConversions::unpackFunc, \
WebGLTexelConversions::packFunc>(); \
break; \
} \
break;
#define HANDLE_FLOAT_SRCFORMAT(format, size, unpackFunc) \
case WebGLTexelFormat::format: \
converter.srcTexelSize = size; \
switch (dstFormat) { \
HANDLE_FLOAT_DSTFORMAT(RGB32F, unpackFunc, packRGBA32FToRGB32F) \
HANDLE_FLOAT_DSTFORMAT(A32F, unpackFunc, packRGBA32FToA32F) \
HANDLE_FLOAT_DSTFORMAT(R32F, unpackFunc, packRGBA32FToR32F) \
HANDLE_FLOAT_DSTFORMAT(RA32F, unpackFunc, packRGBA32FToRA32F) \
default: \
NS_ASSERTION(false, "Coding error?! Should never reach this point."); \
return; \
} \
break;
switch (srcFormat) {
HANDLE_SRCFORMAT(RGBA8, 4, PRUint8, unpackRGBA8ToRGBA8)
HANDLE_SRCFORMAT(RGBX8, 4, PRUint8, unpackRGB8ToRGBA8)
HANDLE_SRCFORMAT(RGB8, 3, PRUint8, unpackRGB8ToRGBA8)
HANDLE_SRCFORMAT(BGRA8, 4, PRUint8, unpackBGRA8ToRGBA8)
HANDLE_SRCFORMAT(BGRX8, 4, PRUint8, unpackBGR8ToRGBA8)
HANDLE_SRCFORMAT(BGR8, 3, PRUint8, unpackBGR8ToRGBA8)
HANDLE_SRCFORMAT(R8, 1, PRUint8, unpackR8ToRGBA8)
HANDLE_SRCFORMAT(A8, 1, PRUint8, unpackA8ToRGBA8)
HANDLE_SRCFORMAT(RA8, 2, PRUint8, unpackRA8ToRGBA8)
HANDLE_SRCFORMAT(RGBA5551, 2, PRUint16, unpackRGBA5551ToRGBA8)
HANDLE_SRCFORMAT(RGBA4444, 2, PRUint16, unpackRGBA4444ToRGBA8)
HANDLE_SRCFORMAT(RGB565, 2, PRUint16, unpackRGB565ToRGBA8)
HANDLE_FLOAT_SRCFORMAT(RGB32F, 12, unpackRGB32FToRGBA32F)
HANDLE_FLOAT_SRCFORMAT(RA32F, 8, unpackRA32FToRGBA32F)
HANDLE_FLOAT_SRCFORMAT(R32F, 4, unpackR32FToRGBA32F)
HANDLE_FLOAT_SRCFORMAT(A32F, 4, unpackA32FToRGBA32F)
default:
NS_ASSERTION(false, "Coding error?! Should never reach this point.");
return;
}
}
nsresult
WebGLContext::DOMElementToImageSurface(Element* imageOrCanvas,
gfxImageSurface **imageOut, int *format)
gfxImageSurface **imageOut, WebGLTexelFormat *format)
{
if (!imageOrCanvas) {
return NS_ERROR_FAILURE;
@ -4556,16 +4367,16 @@ WebGLContext::DOMElementToImageSurface(Element* imageOrCanvas,
switch (surf->Format()) {
case gfxASurface::ImageFormatARGB32:
*format = WebGLTexelFormat::BGRA8; // careful, our ARGB means BGRA
*format = WebGLTexelConversions::BGRA8; // careful, our ARGB means BGRA
break;
case gfxASurface::ImageFormatRGB24:
*format = WebGLTexelFormat::BGRX8; // careful, our RGB24 is not tightly packed. Whence BGRX8.
*format = WebGLTexelConversions::BGRX8; // careful, our RGB24 is not tightly packed. Whence BGRX8.
break;
case gfxASurface::ImageFormatA8:
*format = WebGLTexelFormat::A8;
*format = WebGLTexelConversions::A8;
break;
case gfxASurface::ImageFormatRGB16_565:
*format = WebGLTexelFormat::RGB565;
*format = WebGLTexelConversions::RGB565;
break;
default:
NS_ASSERTION(false, "Unsupported image format. Unimplemented.");
@ -5271,11 +5082,37 @@ WebGLContext::CompressedTexImage2D(WebGLenum target, WebGLint level, WebGLenum i
return;
}
WebGLTexture *tex = activeBoundTextureForTarget(target);
if (!tex)
return ErrorInvalidOperation("compressedTexImage2D: no texture is bound to this target");
if (!ValidateTexImage2DTarget(target, width, height, "compressedTexImage2D")) {
return;
}
return ErrorInvalidEnum("compressedTexImage2D: compressed textures are not supported");
WebGLTexture *tex = activeBoundTextureForTarget(target);
if (!tex) {
ErrorInvalidOperation("compressedTexImage2D: no texture is bound to this target");
return;
}
if (!mCompressedTextureFormats.Contains(internalformat)) {
ErrorInvalidEnum("compressedTexImage2D: compressed texture format 0x%x is not supported", internalformat);
return;
}
if (!ValidateLevelWidthHeightForTarget(target, level, width, height, "compressedTexImage2D")) {
return;
}
if (border) {
ErrorInvalidValue("compressedTexImage2D: border is not 0");
return;
}
uint32_t byteLength = view.mLength;
if (!ValidateCompressedTextureSize(level, internalformat, width, height, byteLength, "compressedTexImage2D")) {
return;
}
gl->fCompressedTexImage2D(target, level, internalformat, width, height, border, byteLength, view.mData);
tex->SetImageInfo(target, level, width, height, internalformat, LOCAL_GL_UNSIGNED_BYTE);
}
NS_IMETHODIMP
@ -5302,12 +5139,82 @@ WebGLContext::CompressedTexSubImage2D(WebGLenum target, WebGLint level, WebGLint
return;
}
WebGLTexture *tex = activeBoundTextureForTarget(target);
if (!tex) {
return ErrorInvalidOperation("compressedTexSubImage2D: no texture is bound to this target");
switch (target) {
case LOCAL_GL_TEXTURE_2D:
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X:
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
break;
default:
return ErrorInvalidEnumInfo("texSubImage2D: target", target);
}
return ErrorInvalidEnum("compressedTexSubImage2D: compressed textures are not supported");
WebGLTexture *tex = activeBoundTextureForTarget(target);
if (!tex) {
ErrorInvalidOperation("compressedTexSubImage2D: no texture is bound to this target");
return;
}
if (!mCompressedTextureFormats.Contains(format)) {
ErrorInvalidEnum("compressedTexSubImage2D: compressed texture format 0x%x is not supported", format);
return;
}
if (!ValidateLevelWidthHeightForTarget(target, level, width, height, "compressedTexSubImage2D")) {
return;
}
uint32_t byteLength = view.mLength;
if (!ValidateCompressedTextureSize(level, format, width, height, byteLength, "compressedTexSubImage2D")) {
return;
}
size_t face = WebGLTexture::FaceForTarget(target);
if (!tex->HasImageInfoAt(level, face)) {
ErrorInvalidOperation("compressedTexSubImage2D: no texture image previously defined for this level and face");
return;
}
const WebGLTexture::ImageInfo &imageInfo = tex->ImageInfoAt(level, face);
if (!CanvasUtils::CheckSaneSubrectSize(xoffset, yoffset, width, height, imageInfo.Width(), imageInfo.Height())) {
ErrorInvalidValue("compressedTexSubImage2D: subtexture rectangle out of bounds");
return;
}
switch (format) {
case LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
{
if (xoffset < 0 || xoffset % 4 != 0) {
ErrorInvalidOperation("compressedTexSubImage2D: xoffset is not a multiple of 4");
return;
}
if (yoffset < 0 || yoffset % 4 != 0) {
ErrorInvalidOperation("compressedTexSubImage2D: yoffset is not a multiple of 4");
return;
}
if (width % 4 != 0 && width != imageInfo.Width()) {
ErrorInvalidOperation("compressedTexSubImage2D: width is not a multiple of 4 or equal to texture width");
return;
}
if (height % 4 != 0 && height != imageInfo.Height()) {
ErrorInvalidOperation("compressedTexSubImage2D: height is not a multiple of 4 or equal to texture height");
return;
}
break;
}
}
gl->fCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, byteLength, view.mData);
return;
}
NS_IMETHODIMP
@ -5644,22 +5551,10 @@ WebGLContext::TexImage2D_base(WebGLenum target, WebGLint level, WebGLenum intern
WebGLenum format, WebGLenum type,
void *data, PRUint32 byteLength,
int jsArrayType, // a TypedArray format enum, or -1 if not relevant
int srcFormat, bool srcPremultiplied)
WebGLTexelFormat srcFormat, bool srcPremultiplied)
{
switch (target) {
case LOCAL_GL_TEXTURE_2D:
break;
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X:
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
if (width != height)
return ErrorInvalidValue("texImage2D: with cube map targets, width and height must be equal");
break;
default:
return ErrorInvalidEnumInfo("texImage2D: target", target);
if (!ValidateTexImage2DTarget(target, width, height, "texImage2D")) {
return;
}
switch (format) {
@ -5676,19 +5571,9 @@ WebGLContext::TexImage2D_base(WebGLenum target, WebGLint level, WebGLenum intern
if (format != internalformat)
return ErrorInvalidOperation("texImage2D: format does not match internalformat");
WebGLsizei maxTextureSize = MaxTextureSizeForTarget(target);
if (level < 0)
return ErrorInvalidValue("texImage2D: level must be >= 0");
if (!(maxTextureSize >> level))
return ErrorInvalidValue("texImage2D: 2^level exceeds maximum texture size");
if (width < 0 || height < 0)
return ErrorInvalidValue("texImage2D: width and height must be >= 0");
if (width > maxTextureSize || height > maxTextureSize)
return ErrorInvalidValue("texImage2D: width or height exceeds maximum texture size");
if (!ValidateLevelWidthHeightForTarget(target, level, width, height, "texImage2D")) {
return;
}
if (level >= 1) {
if (!(is_pot_assuming_nonnegative(width) &&
@ -5699,14 +5584,19 @@ WebGLContext::TexImage2D_base(WebGLenum target, WebGLint level, WebGLenum intern
if (border != 0)
return ErrorInvalidValue("TexImage2D: border must be 0");
PRUint32 texelSize = 0;
if (!ValidateTexFormatAndType(format, type, jsArrayType, &texelSize, "texImage2D"))
PRUint32 dstTexelSize = 0;
if (!ValidateTexFormatAndType(format, type, jsArrayType, &dstTexelSize, "texImage2D"))
return;
CheckedUint32 checked_neededByteLength =
GetImageSize(height, width, texelSize, mPixelStoreUnpackAlignment);
WebGLTexelFormat dstFormat = GetWebGLTexelFormat(format, type);
WebGLTexelFormat actualSrcFormat = srcFormat == WebGLTexelConversions::Auto ? dstFormat : srcFormat;
CheckedUint32 checked_plainRowSize = CheckedUint32(width) * texelSize;
PRUint32 srcTexelSize = WebGLTexelConversions::TexelBytesForFormat(actualSrcFormat);
CheckedUint32 checked_neededByteLength =
GetImageSize(height, width, srcTexelSize, mPixelStoreUnpackAlignment);
CheckedUint32 checked_plainRowSize = CheckedUint32(width) * srcTexelSize;
CheckedUint32 checked_alignedRowSize =
RoundedToNextMultipleOf(checked_plainRowSize.value(), mPixelStoreUnpackAlignment);
@ -5734,11 +5624,9 @@ WebGLContext::TexImage2D_base(WebGLenum target, WebGLint level, WebGLenum intern
GLenum error = LOCAL_GL_NO_ERROR;
if (byteLength) {
int dstFormat = GetWebGLTexelFormat(format, type);
int actualSrcFormat = srcFormat == WebGLTexelFormat::Auto ? dstFormat : srcFormat;
size_t srcStride = srcStrideOrZero ? srcStrideOrZero : checked_alignedRowSize.value();
size_t dstPlainRowSize = texelSize * width;
size_t dstPlainRowSize = dstTexelSize * width;
size_t unpackAlignment = mPixelStoreUnpackAlignment;
size_t dstStride = ((dstPlainRowSize + unpackAlignment-1) / unpackAlignment) * unpackAlignment;
@ -5753,11 +5641,12 @@ WebGLContext::TexImage2D_base(WebGLenum target, WebGLint level, WebGLenum intern
}
else
{
nsAutoArrayPtr<PRUint8> convertedData(new PRUint8[bytesNeeded]);
size_t convertedDataSize = height * dstStride;
nsAutoArrayPtr<PRUint8> convertedData(new PRUint8[convertedDataSize]);
ConvertImage(width, height, srcStride, dstStride,
(PRUint8*)data, convertedData,
actualSrcFormat, srcPremultiplied,
dstFormat, mPixelStorePremultiplyAlpha, texelSize);
dstFormat, mPixelStorePremultiplyAlpha, dstTexelSize);
error = CheckedTexImage2D(target, level, internalformat,
width, height, border, format, type, convertedData);
}
@ -5814,7 +5703,7 @@ WebGLContext::TexImage2D(JSContext* cx, WebGLenum target, WebGLint level,
pixels ? pixels->mData : 0,
pixels ? pixels->mLength : 0,
pixels ? (int)JS_GetTypedArrayType(pixels->mObj, cx) : -1,
WebGLTexelFormat::Auto, false);
WebGLTexelConversions::Auto, false);
}
NS_IMETHODIMP
@ -5832,7 +5721,7 @@ WebGLContext::TexImage2D_imageData(WebGLenum target, WebGLint level, WebGLenum i
pixels ? JS_GetArrayBufferViewData(pixels, cx) : 0,
pixels ? JS_GetArrayBufferViewByteLength(pixels, cx) : 0,
-1,
WebGLTexelFormat::RGBA8, false);
WebGLTexelConversions::RGBA8, false);
return NS_OK;
}
@ -5853,7 +5742,7 @@ WebGLContext::TexImage2D(JSContext* cx, WebGLenum target, WebGLint level,
return TexImage2D_base(target, level, internalformat, pixels->GetWidth(),
pixels->GetHeight(), 4*pixels->GetWidth(), 0,
format, type, arr.mData, arr.mLength, -1,
WebGLTexelFormat::RGBA8, false);
WebGLTexelConversions::RGBA8, false);
}
@ -5877,7 +5766,7 @@ WebGLContext::TexImage2D(JSContext* /* unused */, WebGLenum target,
nsRefPtr<gfxImageSurface> isurf;
int srcFormat;
WebGLTexelFormat srcFormat;
rv = DOMElementToImageSurface(elt, getter_AddRefs(isurf), &srcFormat);
if (rv.Failed())
return;
@ -5908,7 +5797,7 @@ WebGLContext::TexSubImage2D_base(WebGLenum target, WebGLint level,
WebGLenum format, WebGLenum type,
void *pixels, PRUint32 byteLength,
int jsArrayType,
int srcFormat, bool srcPremultiplied)
WebGLTexelFormat srcFormat, bool srcPremultiplied)
{
switch (target) {
case LOCAL_GL_TEXTURE_2D:
@ -5923,19 +5812,9 @@ WebGLContext::TexSubImage2D_base(WebGLenum target, WebGLint level,
return ErrorInvalidEnumInfo("texSubImage2D: target", target);
}
WebGLsizei maxTextureSize = MaxTextureSizeForTarget(target);
if (level < 0)
return ErrorInvalidValue("texSubImage2D: level must be >= 0");
if (!(maxTextureSize >> level))
return ErrorInvalidValue("texSubImage2D: 2^level exceeds maximum texture size");
if (width < 0 || height < 0)
return ErrorInvalidValue("texSubImage2D: width and height must be >= 0");
if (width > maxTextureSize || height > maxTextureSize)
return ErrorInvalidValue("texSubImage2D: width or height exceeds maximum texture size");
if (!ValidateLevelWidthHeightForTarget(target, level, width, height, "texSubImage2D")) {
return;
}
if (level >= 1) {
if (!(is_pot_assuming_nonnegative(width) &&
@ -5943,17 +5822,22 @@ WebGLContext::TexSubImage2D_base(WebGLenum target, WebGLint level,
return ErrorInvalidValue("texSubImage2D: with level > 0, width and height must be powers of two");
}
PRUint32 texelSize = 0;
if (!ValidateTexFormatAndType(format, type, jsArrayType, &texelSize, "texSubImage2D"))
PRUint32 dstTexelSize = 0;
if (!ValidateTexFormatAndType(format, type, jsArrayType, &dstTexelSize, "texSubImage2D"))
return;
WebGLTexelFormat dstFormat = GetWebGLTexelFormat(format, type);
WebGLTexelFormat actualSrcFormat = srcFormat == WebGLTexelConversions::Auto ? dstFormat : srcFormat;
PRUint32 srcTexelSize = WebGLTexelConversions::TexelBytesForFormat(actualSrcFormat);
if (width == 0 || height == 0)
return; // ES 2.0 says it has no effect, we better return right now
CheckedUint32 checked_neededByteLength =
GetImageSize(height, width, texelSize, mPixelStoreUnpackAlignment);
GetImageSize(height, width, srcTexelSize, mPixelStoreUnpackAlignment);
CheckedUint32 checked_plainRowSize = CheckedUint32(width) * texelSize;
CheckedUint32 checked_plainRowSize = CheckedUint32(width) * srcTexelSize;
CheckedUint32 checked_alignedRowSize =
RoundedToNextMultipleOf(checked_plainRowSize.value(), mPixelStoreUnpackAlignment);
@ -5986,11 +5870,9 @@ WebGLContext::TexSubImage2D_base(WebGLenum target, WebGLint level,
MakeContextCurrent();
int dstFormat = GetWebGLTexelFormat(format, type);
int actualSrcFormat = srcFormat == WebGLTexelFormat::Auto ? dstFormat : srcFormat;
size_t srcStride = srcStrideOrZero ? srcStrideOrZero : checked_alignedRowSize.value();
size_t dstPlainRowSize = texelSize * width;
size_t dstPlainRowSize = dstTexelSize * width;
// There are checks above to ensure that this won't overflow.
size_t dstStride = RoundedToNextMultipleOf(dstPlainRowSize, mPixelStoreUnpackAlignment).value();
@ -6004,11 +5886,12 @@ WebGLContext::TexSubImage2D_base(WebGLenum target, WebGLint level,
}
else
{
nsAutoArrayPtr<PRUint8> convertedData(new PRUint8[bytesNeeded]);
size_t convertedDataSize = height * dstStride;
nsAutoArrayPtr<PRUint8> convertedData(new PRUint8[convertedDataSize]);
ConvertImage(width, height, srcStride, dstStride,
(const PRUint8*)pixels, convertedData,
actualSrcFormat, srcPremultiplied,
dstFormat, mPixelStorePremultiplyAlpha, texelSize);
dstFormat, mPixelStorePremultiplyAlpha, dstTexelSize);
gl->fTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, convertedData);
}
@ -6051,7 +5934,7 @@ WebGLContext::TexSubImage2D(JSContext* cx, WebGLenum target, WebGLint level,
width, height, 0, format, type,
pixels->mData, pixels->mLength,
JS_GetTypedArrayType(pixels->mObj, cx),
WebGLTexelFormat::Auto, false);
WebGLTexelConversions::Auto, false);
}
NS_IMETHODIMP
@ -6075,7 +5958,7 @@ WebGLContext::TexSubImage2D_imageData(WebGLenum target, WebGLint level,
width, height, 4*width, format, type,
JS_GetArrayBufferViewData(pixels, cx), JS_GetArrayBufferViewByteLength(pixels, cx),
-1,
WebGLTexelFormat::RGBA8, false);
WebGLTexelConversions::RGBA8, false);
return NS_OK;
}
@ -6097,7 +5980,7 @@ WebGLContext::TexSubImage2D(JSContext* cx, WebGLenum target, WebGLint level,
4*pixels->GetWidth(), format, type,
arr.mData, arr.mLength,
-1,
WebGLTexelFormat::RGBA8, false);
WebGLTexelConversions::RGBA8, false);
}
NS_IMETHODIMP
@ -6122,7 +6005,7 @@ WebGLContext::TexSubImage2D(JSContext* /* unused */, WebGLenum target,
nsRefPtr<gfxImageSurface> isurf;
int srcFormat;
WebGLTexelFormat srcFormat;
rv = DOMElementToImageSurface(elt, getter_AddRefs(isurf), &srcFormat);
if (rv.Failed())
return;
@ -6232,52 +6115,52 @@ BaseTypeAndSizeFromUniformType(WebGLenum uType, WebGLenum *baseType, WebGLint *u
}
int mozilla::GetWebGLTexelFormat(GLenum format, GLenum type)
WebGLTexelFormat mozilla::GetWebGLTexelFormat(GLenum format, GLenum type)
{
if (type == LOCAL_GL_UNSIGNED_BYTE) {
switch (format) {
case LOCAL_GL_RGBA:
return WebGLTexelFormat::RGBA8;
return WebGLTexelConversions::RGBA8;
case LOCAL_GL_RGB:
return WebGLTexelFormat::RGB8;
return WebGLTexelConversions::RGB8;
case LOCAL_GL_ALPHA:
return WebGLTexelFormat::A8;
return WebGLTexelConversions::A8;
case LOCAL_GL_LUMINANCE:
return WebGLTexelFormat::R8;
return WebGLTexelConversions::R8;
case LOCAL_GL_LUMINANCE_ALPHA:
return WebGLTexelFormat::RA8;
return WebGLTexelConversions::RA8;
default:
NS_ASSERTION(false, "Coding mistake?! Should never reach this point.");
return WebGLTexelFormat::Generic;
NS_ABORT_IF_FALSE(false, "Coding mistake?! Should never reach this point.");
return WebGLTexelConversions::BadFormat;
}
} else if (type == LOCAL_GL_FLOAT) {
// OES_texture_float
switch (format) {
case LOCAL_GL_RGBA:
return WebGLTexelFormat::RGBA32F;
return WebGLTexelConversions::RGBA32F;
case LOCAL_GL_RGB:
return WebGLTexelFormat::RGB32F;
return WebGLTexelConversions::RGB32F;
case LOCAL_GL_ALPHA:
return WebGLTexelFormat::A32F;
return WebGLTexelConversions::A32F;
case LOCAL_GL_LUMINANCE:
return WebGLTexelFormat::R32F;
return WebGLTexelConversions::R32F;
case LOCAL_GL_LUMINANCE_ALPHA:
return WebGLTexelFormat::RA32F;
return WebGLTexelConversions::RA32F;
default:
NS_ASSERTION(false, "Coding mistake?! Should never reach this point.");
return WebGLTexelFormat::Generic;
NS_ABORT_IF_FALSE(false, "Coding mistake?! Should never reach this point.");
return WebGLTexelConversions::BadFormat;
}
} else {
switch (type) {
case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
return WebGLTexelFormat::RGBA4444;
return WebGLTexelConversions::RGBA4444;
case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1:
return WebGLTexelFormat::RGBA5551;
return WebGLTexelConversions::RGBA5551;
case LOCAL_GL_UNSIGNED_SHORT_5_6_5:
return WebGLTexelFormat::RGB565;
return WebGLTexelConversions::RGB565;
default:
NS_ASSERTION(false, "Coding mistake?! Should never reach this point.");
return WebGLTexelFormat::Generic;
NS_ABORT_IF_FALSE(false, "Coding mistake?! Should never reach this point.");
return WebGLTexelConversions::BadFormat;
}
}
}

Просмотреть файл

@ -57,3 +57,4 @@ DOMCI_DATA(WebGLExtension, void)
DOMCI_DATA(WebGLExtensionStandardDerivatives, void)
DOMCI_DATA(WebGLExtensionTextureFilterAnisotropic, void)
DOMCI_DATA(WebGLExtensionLoseContext, void)
DOMCI_DATA(WebGLExtensionCompressedTextureS3TC, void)

Просмотреть файл

@ -371,10 +371,118 @@ bool WebGLContext::ValidateGLSLString(const nsAString& string, const char *info)
return true;
}
PRUint32 WebGLContext::GetTexelSize(WebGLenum format, WebGLenum type)
bool WebGLContext::ValidateTexImage2DTarget(WebGLenum target, WebGLsizei width, WebGLsizei height,
const char* info)
{
switch (target) {
case LOCAL_GL_TEXTURE_2D:
break;
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X:
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
if (width != height) {
ErrorInvalidValue("%s: with cube map targets, width and height must be equal", info);
return false;
}
break;
default:
ErrorInvalidEnum("%s: invalid target enum 0x%x", info, target);
return false;
}
return true;
}
bool WebGLContext::ValidateCompressedTextureSize(WebGLint level, WebGLenum format, WebGLsizei width,
WebGLsizei height, uint32_t byteLength, const char* info)
{
CheckedUint32 calculated_byteLength = 0;
CheckedUint32 checked_byteLength = byteLength;
if (!checked_byteLength.valid()) {
ErrorInvalidValue("%s: data length out of bounds", info);
return false;
}
switch (format) {
case LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
{
calculated_byteLength = ((CheckedUint32(width) + 3) / 4) * ((CheckedUint32(height) + 3) / 4) * 8;
if (!calculated_byteLength.valid() || !(checked_byteLength == calculated_byteLength)) {
ErrorInvalidValue("%s: data size does not match dimensions", info);
return false;
}
break;
}
case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
{
calculated_byteLength = ((CheckedUint32(width) + 3) / 4) * ((CheckedUint32(height) + 3) / 4) * 16;
if (!calculated_byteLength.valid() || !(checked_byteLength == calculated_byteLength)) {
ErrorInvalidValue("%s: data size does not match dimensions", info);
return false;
}
break;
}
}
switch (format) {
case LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
{
if (level == 0 && width % 4 == 0 && height % 4 == 0) {
return true;
}
if (level > 0
&& (width == 0 || width == 1 || width == 2 || width % 4 == 0)
&& (height == 0 || height == 1 || height == 2 || height % 4 == 0))
{
return true;
}
}
}
ErrorInvalidOperation("%s: level parameter does not match width and height", info);
return false;
}
bool WebGLContext::ValidateLevelWidthHeightForTarget(WebGLenum target, WebGLint level, WebGLsizei width,
WebGLsizei height, const char* info)
{
WebGLsizei maxTextureSize = MaxTextureSizeForTarget(target);
if (level < 0) {
ErrorInvalidValue("%s: level must be >= 0", info);
return false;
}
if (!(maxTextureSize >> level)) {
ErrorInvalidValue("%s: 2^level exceeds maximum texture size");
return false;
}
if (width < 0 || height < 0) {
ErrorInvalidValue("%s: width and height must be >= 0");
return false;
}
if (width > maxTextureSize || height > maxTextureSize) {
ErrorInvalidValue("%s: width or height exceeds maximum texture size");
return false;
}
return true;
}
PRUint32 WebGLContext::GetBitsPerTexel(WebGLenum format, WebGLenum type)
{
if (type == LOCAL_GL_UNSIGNED_BYTE || type == LOCAL_GL_FLOAT) {
int multiplier = type == LOCAL_GL_FLOAT ? 4 : 1;
int multiplier = type == LOCAL_GL_FLOAT ? 32 : 8;
switch (format) {
case LOCAL_GL_ALPHA:
case LOCAL_GL_LUMINANCE:
@ -385,6 +493,12 @@ PRUint32 WebGLContext::GetTexelSize(WebGLenum format, WebGLenum type)
return 3 * multiplier;
case LOCAL_GL_RGBA:
return 4 * multiplier;
case LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
return 4;
case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
return 8;
default:
break;
}
@ -392,7 +506,7 @@ PRUint32 WebGLContext::GetTexelSize(WebGLenum format, WebGLenum type)
type == LOCAL_GL_UNSIGNED_SHORT_5_5_5_1 ||
type == LOCAL_GL_UNSIGNED_SHORT_5_6_5)
{
return 2;
return 16;
}
NS_ABORT();
@ -518,20 +632,6 @@ WebGLContext::InitAndValidateGL()
return false;
}
#ifdef ANDROID
// bug 736123, blacklist WebGL on Adreno because they do not implement
// glTexSubImage2D in a way that is safe to expose to WebGL </euphemism>
// We don't rely on GfxInfo for this blacklisting, because GfxInfo on Android doesn't know
// about GL strings and GL strings are the only way I know to detect Adreno (EGL Vendor only
// says 'Android'), and it is not convenient to have to create a GL context before GfxInfo::Init()
// is first called.
if (gl->Renderer() == gl::GLContext::RendererAdreno200 ||
gl->Renderer() == gl::GLContext::RendererAdreno205)
{
return false;
}
#endif
mMinCapability = Preferences::GetBool("webgl.min_capability_mode", false);
mDisableExtensions = Preferences::GetBool("webgl.disable-extensions", false);

Просмотреть файл

@ -0,0 +1,33 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "WebGLContext.h"
#include "WebGLExtensions.h"
using namespace mozilla;
WebGLExtensionCompressedTextureS3TC::WebGLExtensionCompressedTextureS3TC(WebGLContext* context)
: WebGLExtension(context)
{
context->mCompressedTextureFormats.AppendElement(LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT);
context->mCompressedTextureFormats.AppendElement(LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT);
context->mCompressedTextureFormats.AppendElement(LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT);
context->mCompressedTextureFormats.AppendElement(LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT);
}
WebGLExtensionCompressedTextureS3TC::~WebGLExtensionCompressedTextureS3TC()
{
}
NS_IMPL_ADDREF_INHERITED(WebGLExtensionCompressedTextureS3TC, WebGLExtension)
NS_IMPL_RELEASE_INHERITED(WebGLExtensionCompressedTextureS3TC, WebGLExtension)
DOMCI_DATA(WebGLExtensionCompressedTextureS3TC, WebGLExtensionCompressedTextureS3TC)
NS_INTERFACE_MAP_BEGIN(WebGLExtensionCompressedTextureS3TC)
NS_INTERFACE_MAP_ENTRY(nsIWebGLExtensionCompressedTextureS3TC)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, WebGLExtension)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebGLExtensionCompressedTextureS3TC)
NS_INTERFACE_MAP_END_INHERITING(WebGLExtension)

Просмотреть файл

@ -36,14 +36,9 @@
*
* ***** END LICENSE BLOCK ***** */
#include <stdarg.h>
#include "WebGLContext.h"
#include "WebGLExtensions.h"
#include "nsContentUtils.h"
#include "mozilla/Preferences.h"
using namespace mozilla;
WebGLExtensionLoseContext::WebGLExtensionLoseContext(WebGLContext* context) :

Просмотреть файл

@ -36,14 +36,9 @@
*
* ***** END LICENSE BLOCK ***** */
#include <stdarg.h>
#include "WebGLContext.h"
#include "WebGLExtensions.h"
#include "nsContentUtils.h"
#include "mozilla/Preferences.h"
using namespace mozilla;
WebGLExtensionStandardDerivatives::WebGLExtensionStandardDerivatives(WebGLContext* context) :

Просмотреть файл

@ -36,14 +36,9 @@
*
* ***** END LICENSE BLOCK ***** */
#include <stdarg.h>
#include "WebGLContext.h"
#include "WebGLExtensions.h"
#include "nsContentUtils.h"
#include "mozilla/Preferences.h"
using namespace mozilla;
WebGLExtensionTextureFilterAnisotropic::WebGLExtensionTextureFilterAnisotropic(WebGLContext* context) :

Просмотреть файл

@ -77,6 +77,18 @@ public:
NS_DECL_NSIWEBGLEXTENSION
};
class WebGLExtensionCompressedTextureS3TC :
public nsIWebGLExtensionCompressedTextureS3TC,
public WebGLExtension
{
public:
WebGLExtensionCompressedTextureS3TC(WebGLContext* context);
virtual ~WebGLExtensionCompressedTextureS3TC();
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIWEBGLEXTENSION
};
}
#endif // WEBGLEXTENSIONS_H_

Просмотреть файл

@ -0,0 +1,382 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "WebGLTexelConversions.h"
namespace mozilla {
using namespace WebGLTexelConversions;
namespace {
/** @class WebGLImageConverter
*
* This class is just a helper to implement WebGLContext::ConvertImage below.
*
* Design comments:
*
* WebGLContext::ConvertImage has to handle hundreds of format conversion paths.
* It is important to minimize executable code size here. Instead of passing around
* a large number of function parameters hundreds of times, we create a
* WebGLImageConverter object once, storing these parameters, and then we call
* the run() method on it.
*/
class WebGLImageConverter
{
const size_t mWidth, mHeight;
const void* const mSrcStart;
void* const mDstStart;
const ptrdiff_t mSrcStride, mDstStride;
bool mAlreadyRun;
bool mSuccess;
/*
* Returns sizeof(texel)/sizeof(type). The point is that we will iterate over
* texels with typed pointers and this value will tell us by how much we need
* to increment these pointers to advance to the next texel.
*/
template<int Format>
static size_t NumElementsPerTexelForFormat() {
switch (Format) {
case R8:
case A8:
case R32F:
case A32F:
case RGBA5551:
case RGBA4444:
case RGB565:
return 1;
case RA8:
case RA32F:
return 2;
case RGB8:
case RGB32F:
return 3;
case RGBA8:
case BGRA8:
case BGRX8:
case RGBA32F:
return 4;
default:
NS_ABORT_IF_FALSE(false, "Unknown texel format. Coding mistake?");
return 0;
}
}
/*
* This is the completely format-specific templatized conversion function,
* that will be instantiated hundreds of times for all different combinations.
* It is important to avoid generating useless code here. In particular, many
* instantiations of this function template will never be called, so we try
* to return immediately in these cases to allow the compiler to avoid generating
* useless code.
*/
template<WebGLTexelFormat SrcFormat,
WebGLTexelFormat DstFormat,
WebGLTexelPremultiplicationOp PremultiplicationOp>
void run()
{
// check for never-called cases. We early-return to allow the compiler
// to avoid generating this code. It would be tempting to abort() instead,
// as returning early does leave the destination surface with uninitialized
// data, but that would not allow the compiler to avoid generating this code.
// So instead, we return early, so Success() will return false, and the caller
// must check that and abort in that case. See WebGLContext::ConvertImage.
if (SrcFormat == DstFormat &&
PremultiplicationOp == NoPremultiplicationOp)
{
// Should have used a fast exit path earlier, rather than entering this function.
// we explicitly return here to allow the compiler to avoid generating this code
return;
}
// Only textures uploaded from DOM elements or ImageData can allow DstFormat != SrcFormat.
// DOM elements can only give BGRA8, BGRX8, A8, RGB565 formats. See DOMElementToImageSurface.
// ImageData is always RGBA8. So all other SrcFormat will always satisfy DstFormat==SrcFormat,
// so we can avoid compiling the code for all the unreachable paths.
const bool CanSrcFormatComeFromDOMElementOrImageData
= SrcFormat == BGRA8 ||
SrcFormat == BGRX8 ||
SrcFormat == A8 ||
SrcFormat == RGB565 ||
SrcFormat == RGBA8;
if (!CanSrcFormatComeFromDOMElementOrImageData &&
SrcFormat != DstFormat)
{
return;
}
// Likewise, only textures uploaded from DOM elements or ImageData can possibly have to be unpremultiplied.
if (!CanSrcFormatComeFromDOMElementOrImageData &&
PremultiplicationOp == Unpremultiply)
{
return;
}
// there is no point in premultiplication/unpremultiplication
// in the following cases:
// - the source format has no alpha
// - the source format has no color
// - the destination format has no color
if (!HasAlpha(SrcFormat) ||
!HasColor(SrcFormat) ||
!HasColor(DstFormat))
{
if (PremultiplicationOp != NoPremultiplicationOp)
{
return;
}
}
// end of early return cases.
NS_ABORT_IF_FALSE(!mAlreadyRun, "converter should be run only once!");
mAlreadyRun = true;
// gather some compile-time meta-data about the formats at hand.
typedef
typename DataTypeForFormat<SrcFormat>::Type
SrcType;
typedef
typename DataTypeForFormat<DstFormat>::Type
DstType;
const int IntermediateSrcFormat
= IntermediateFormat<SrcFormat>::Value;
const int IntermediateDstFormat
= IntermediateFormat<DstFormat>::Value;
typedef
typename DataTypeForFormat<IntermediateSrcFormat>::Type
IntermediateSrcType;
typedef
typename DataTypeForFormat<IntermediateDstFormat>::Type
IntermediateDstType;
const size_t NumElementsPerSrcTexel = NumElementsPerTexelForFormat<SrcFormat>();
const size_t NumElementsPerDstTexel = NumElementsPerTexelForFormat<DstFormat>();
const size_t MaxElementsPerTexel = 4;
NS_ABORT_IF_FALSE(NumElementsPerSrcTexel <= MaxElementsPerTexel, "unhandled format");
NS_ABORT_IF_FALSE(NumElementsPerDstTexel <= MaxElementsPerTexel, "unhandled format");
// we assume that the strides are multiples of the sizeof of respective types.
// this assumption will allow us to iterate over src and dst images using typed
// pointers, e.g. uint8_t* or uint16_t* or float*, instead of untyped pointers.
// So this assumption allows us to write cleaner and safer code, but it might
// not be true forever and if it eventually becomes wrong, we'll have to revert
// to always iterating using uint8_t* pointers regardless of the types at hand.
NS_ABORT_IF_FALSE(mSrcStride % sizeof(SrcType) == 0 &&
mDstStride % sizeof(DstType) == 0,
"Unsupported: texture stride is not a multiple of sizeof(type)");
const ptrdiff_t srcStrideInElements = mSrcStride / sizeof(SrcType);
const ptrdiff_t dstStrideInElements = mDstStride / sizeof(DstType);
const SrcType *srcRowStart = static_cast<const SrcType*>(mSrcStart);
DstType *dstRowStart = static_cast<DstType*>(mDstStart);
// the loop performing the texture format conversion
for (size_t i = 0; i < mHeight; ++i) {
const SrcType *srcRowEnd = srcRowStart + mWidth * NumElementsPerSrcTexel;
const SrcType *srcPtr = srcRowStart;
DstType *dstPtr = dstRowStart;
while (srcPtr != srcRowEnd) {
// convert a single texel. We proceed in 3 steps: unpack the source texel
// so the corresponding interchange format (e.g. unpack RGB565 to RGBA8),
// convert the resulting data type to the destination type (e.g. convert
// from RGBA8 to RGBA32F), and finally pack the destination texel
// (e.g. pack RGBA32F to RGB32F).
IntermediateSrcType unpackedSrc[MaxElementsPerTexel];
IntermediateDstType unpackedDst[MaxElementsPerTexel];
// unpack a src texel to corresponding intermediate src format.
// for example, unpack RGB565 to RGBA8
unpack<SrcFormat>(srcPtr, unpackedSrc);
// convert the data type to the destination type, if needed.
// for example, convert RGBA8 to RGBA32F
convertType(unpackedSrc, unpackedDst);
// pack the destination texel.
// for example, pack RGBA32F to RGB32F
pack<DstFormat, PremultiplicationOp>(unpackedDst, dstPtr);
srcPtr += NumElementsPerSrcTexel;
dstPtr += NumElementsPerDstTexel;
}
srcRowStart += srcStrideInElements;
dstRowStart += dstStrideInElements;
}
mSuccess = true;
return;
}
template<WebGLTexelFormat SrcFormat, WebGLTexelFormat DstFormat>
void run(WebGLTexelPremultiplicationOp premultiplicationOp)
{
#define WEBGLIMAGECONVERTER_CASE_PREMULTIPLICATIONOP(PremultiplicationOp) \
case PremultiplicationOp: \
return run<SrcFormat, DstFormat, PremultiplicationOp>();
switch (premultiplicationOp) {
WEBGLIMAGECONVERTER_CASE_PREMULTIPLICATIONOP(NoPremultiplicationOp)
WEBGLIMAGECONVERTER_CASE_PREMULTIPLICATIONOP(Premultiply)
WEBGLIMAGECONVERTER_CASE_PREMULTIPLICATIONOP(Unpremultiply)
default:
NS_ABORT_IF_FALSE(false, "unhandled case. Coding mistake?");
}
#undef WEBGLIMAGECONVERTER_CASE_PREMULTIPLICATIONOP
}
template<WebGLTexelFormat SrcFormat>
void run(WebGLTexelFormat dstFormat,
WebGLTexelPremultiplicationOp premultiplicationOp)
{
#define WEBGLIMAGECONVERTER_CASE_DSTFORMAT(DstFormat) \
case DstFormat: \
return run<SrcFormat, DstFormat>(premultiplicationOp);
switch (dstFormat) {
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(R8)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(A8)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(R32F)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(A32F)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(RA8)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(RA32F)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(RGB8)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(RGB565)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(RGB32F)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(RGBA8)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(RGBA5551)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(RGBA4444)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(RGBA32F)
default:
NS_ABORT_IF_FALSE(false, "unhandled case. Coding mistake?");
}
#undef WEBGLIMAGECONVERTER_CASE_DSTFORMAT
}
public:
void run(WebGLTexelFormat srcFormat,
WebGLTexelFormat dstFormat,
WebGLTexelPremultiplicationOp premultiplicationOp)
{
#define WEBGLIMAGECONVERTER_CASE_SRCFORMAT(SrcFormat) \
case SrcFormat: \
return run<SrcFormat>(dstFormat, premultiplicationOp);
switch (srcFormat) {
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(R8)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(A8)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(R32F)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(A32F)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(RA8)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(RA32F)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(RGB8)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(BGRX8) // source format only
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(RGB565)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(RGB32F)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(RGBA8)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(BGRA8)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(RGBA5551)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(RGBA4444)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(RGBA32F)
default:
NS_ABORT_IF_FALSE(false, "unhandled case. Coding mistake?");
}
#undef WEBGLIMAGECONVERTER_CASE_SRCFORMAT
}
WebGLImageConverter(size_t width, size_t height,
const void* srcStart, void* dstStart,
ptrdiff_t srcStride, ptrdiff_t dstStride)
: mWidth(width), mHeight(height),
mSrcStart(srcStart), mDstStart(dstStart),
mSrcStride(srcStride), mDstStride(dstStride),
mAlreadyRun(false), mSuccess(false)
{}
bool Success() const {
return mSuccess;
}
};
} // end anonymous namespace
void
WebGLContext::ConvertImage(size_t width, size_t height, size_t srcStride, size_t dstStride,
const uint8_t* src, uint8_t *dst,
WebGLTexelFormat srcFormat, bool srcPremultiplied,
WebGLTexelFormat dstFormat, bool dstPremultiplied,
size_t dstTexelSize)
{
if (width <= 0 || height <= 0)
return;
const bool FormatsRequireNoPremultiplicationOp =
!HasAlpha(srcFormat) ||
!HasColor(srcFormat) ||
!HasColor(dstFormat);
if (srcFormat == dstFormat &&
(FormatsRequireNoPremultiplicationOp || srcPremultiplied == dstPremultiplied))
{
// fast exit path: we just have to memcpy all the rows.
//
// The case where absolutely nothing needs to be done is supposed to have
// been handled earlier (in TexImage2D_base, etc).
//
// So the case we're handling here is when even though no format conversion is needed,
// we still might have to flip vertically and/or to adjust to a different stride.
NS_ABORT_IF_FALSE(mPixelStoreFlipY || srcStride != dstStride, "Performance trap -- should handle this case earlier, to avoid memcpy");
size_t row_size = width * dstTexelSize; // doesn't matter, src and dst formats agree
const uint8_t* ptr = src;
const uint8_t* src_end = src + height * srcStride;
uint8_t* dst_row = mPixelStoreFlipY
? dst + (height-1) * dstStride
: dst;
ptrdiff_t dstStrideSigned(dstStride);
ptrdiff_t dst_delta = mPixelStoreFlipY ? -dstStrideSigned : dstStrideSigned;
while(ptr != src_end) {
memcpy(dst_row, ptr, row_size);
ptr += srcStride;
dst_row += dst_delta;
}
return;
}
uint8_t* dstStart = dst;
ptrdiff_t signedDstStride = dstStride;
if (mPixelStoreFlipY) {
dstStart = dst + (height - 1) * dstStride;
signedDstStride = -dstStride;
}
WebGLImageConverter converter(width, height, src, dstStart, srcStride, signedDstStride);
const WebGLTexelPremultiplicationOp premultiplicationOp
= FormatsRequireNoPremultiplicationOp ? NoPremultiplicationOp
: (!srcPremultiplied && dstPremultiplied) ? Premultiply
: (srcPremultiplied && !dstPremultiplied) ? Unpremultiply
: NoPremultiplicationOp;
converter.run(srcFormat, dstFormat, premultiplicationOp);
if (!converter.Success()) {
// the dst image may be left uninitialized, so we better not try to
// continue even in release builds. This should never happen anyway,
// and would be a bug in our code.
NS_RUNTIMEABORT("programming mistake in WebGL texture conversions");
}
}
} // end namespace mozilla

Просмотреть файл

@ -25,17 +25,6 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// the pixel conversions code here is originally from this file:
// http://trac.webkit.org/browser/trunk/WebCore/platform/graphics/GraphicsContext3D.cpp
// Keep as much as possible unchanged to ease sharing code with the WebKit guys.
// Changes:
// * added BGR8 path, we need it in Mozilla to load textures from DOMElements
// * enclosing in a namespace WebGLTexelConversions to make it clear it is, in profilers and in symbol table dumps
// * added __restrict keywords. Although non-standard, this is very well supported across all compilers
// that I know of (GCC/LLVM/MSC/ICC/XLC...)
// * optimized scaleFactor computation in Unmultiply functions (1 div instead of 2)
#ifndef WEBGLTEXELCONVERSIONS_H_
#define WEBGLTEXELCONVERSIONS_H_
@ -44,6 +33,7 @@
#endif
#include "WebGLContext.h"
#include "mozilla/StandardInteger.h"
#if defined _MSC_VER
#define FORCE_INLINE __forceinline
@ -57,410 +47,647 @@ namespace mozilla {
namespace WebGLTexelConversions {
enum WebGLTexelPremultiplicationOp
{
NoPremultiplicationOp,
Premultiply,
Unpremultiply
};
template<int Format>
struct IsFloatFormat
{
static const bool Value =
Format == RGBA32F ||
Format == RGB32F ||
Format == RA32F ||
Format == R32F ||
Format == A32F;
};
template<int Format>
struct Is16bppFormat
{
static const bool Value =
Format == RGBA4444 ||
Format == RGBA5551 ||
Format == RGB565;
};
template<int Format,
bool IsFloat = IsFloatFormat<Format>::Value,
bool Is16bpp = Is16bppFormat<Format>::Value>
struct DataTypeForFormat
{
typedef uint8_t Type;
};
template<int Format>
struct DataTypeForFormat<Format, true, false>
{
typedef float Type;
};
template<int Format>
struct DataTypeForFormat<Format, false, true>
{
typedef uint16_t Type;
};
template<int Format>
struct IntermediateFormat
{
static const int Value = IsFloatFormat<Format>::Value ? RGBA32F : RGBA8;
};
inline size_t TexelBytesForFormat(int format) {
switch (format) {
case WebGLTexelConversions::R8:
case WebGLTexelConversions::A8:
return 1;
case WebGLTexelConversions::RA8:
case WebGLTexelConversions::RGBA5551:
case WebGLTexelConversions::RGBA4444:
case WebGLTexelConversions::RGB565:
return 2;
case WebGLTexelConversions::RGB8:
return 3;
case WebGLTexelConversions::RGBA8:
case WebGLTexelConversions::BGRA8:
case WebGLTexelConversions::BGRX8:
case WebGLTexelConversions::R32F:
case WebGLTexelConversions::A32F:
return 4;
case WebGLTexelConversions::RA32F:
return 8;
case WebGLTexelConversions::RGB32F:
return 12;
case WebGLTexelConversions::RGBA32F:
return 16;
default:
NS_ABORT_IF_FALSE(false, "Unknown texel format. Coding mistake?");
return 0;
}
}
FORCE_INLINE bool HasAlpha(int format) {
return format == A8 ||
format == A32F ||
format == RA8 ||
format == RA32F ||
format == RGBA8 ||
format == BGRA8 ||
format == RGBA32F ||
format == RGBA4444 ||
format == RGBA5551;
}
FORCE_INLINE bool HasColor(int format) {
return format == R8 ||
format == R32F ||
format == RA8 ||
format == RA32F ||
format == RGB8 ||
format == BGRX8 ||
format == RGB565 ||
format == RGB32F ||
format == RGBA8 ||
format == BGRA8 ||
format == RGBA32F ||
format == RGBA4444 ||
format == RGBA5551;
}
/****** BEGIN CODE SHARED WITH WEBKIT ******/
// the pack/unpack functions here are originally from this file:
// http://trac.webkit.org/browser/trunk/WebCore/platform/graphics/GraphicsContext3D.cpp
//----------------------------------------------------------------------
// Pixel unpacking routines.
FORCE_INLINE void unpackRGBA8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
template<int Format, typename SrcType, typename DstType>
FORCE_INLINE void
unpack(const SrcType* __restrict src,
DstType* __restrict dst)
{
destination[0] = source[0];
destination[1] = source[1];
destination[2] = source[2];
destination[3] = source[3];
NS_ABORT_IF_FALSE(false, "Unimplemented texture format conversion");
}
FORCE_INLINE void unpackRGB8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
template<> FORCE_INLINE void
unpack<RGBA8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
{
destination[0] = source[0];
destination[1] = source[1];
destination[2] = source[2];
destination[3] = 0xFF;
dst[0] = src[0];
dst[1] = src[1];
dst[2] = src[2];
dst[3] = src[3];
}
FORCE_INLINE void unpackBGRA8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
template<> FORCE_INLINE void
unpack<RGB8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
{
destination[0] = source[2];
destination[1] = source[1];
destination[2] = source[0];
destination[3] = source[3];
dst[0] = src[0];
dst[1] = src[1];
dst[2] = src[2];
dst[3] = 0xFF;
}
FORCE_INLINE void unpackBGR8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
template<> FORCE_INLINE void
unpack<BGRA8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
{
destination[0] = source[2];
destination[1] = source[1];
destination[2] = source[0];
destination[3] = 0xFF;
dst[0] = src[2];
dst[1] = src[1];
dst[2] = src[0];
dst[3] = src[3];
}
FORCE_INLINE void unpackRGBA5551ToRGBA8(const uint16_t* __restrict source, uint8_t* __restrict destination)
template<> FORCE_INLINE void
unpack<BGRX8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
{
uint16_t packedValue = source[0];
uint8_t r = packedValue >> 11;
dst[0] = src[2];
dst[1] = src[1];
dst[2] = src[0];
dst[3] = 0xFF;
}
template<> FORCE_INLINE void
unpack<RGBA5551, uint16_t, uint8_t>(const uint16_t* __restrict src, uint8_t* __restrict dst)
{
uint16_t packedValue = src[0];
uint8_t r = (packedValue >> 11) & 0x1F;
uint8_t g = (packedValue >> 6) & 0x1F;
uint8_t b = (packedValue >> 1) & 0x1F;
destination[0] = (r << 3) | (r & 0x7);
destination[1] = (g << 3) | (g & 0x7);
destination[2] = (b << 3) | (b & 0x7);
destination[3] = (packedValue & 0x1) ? 0xFF : 0x0;
dst[0] = (r << 3) | (r & 0x7);
dst[1] = (g << 3) | (g & 0x7);
dst[2] = (b << 3) | (b & 0x7);
dst[3] = (packedValue & 0x1) ? 0xFF : 0;
}
FORCE_INLINE void unpackRGBA4444ToRGBA8(const uint16_t* __restrict source, uint8_t* __restrict destination)
template<> FORCE_INLINE void
unpack<RGBA4444, uint16_t, uint8_t>(const uint16_t* __restrict src, uint8_t* __restrict dst)
{
uint16_t packedValue = source[0];
uint8_t r = packedValue >> 12;
uint16_t packedValue = src[0];
uint8_t r = (packedValue >> 12) & 0x0F;
uint8_t g = (packedValue >> 8) & 0x0F;
uint8_t b = (packedValue >> 4) & 0x0F;
uint8_t a = packedValue & 0x0F;
destination[0] = r << 4 | r;
destination[1] = g << 4 | g;
destination[2] = b << 4 | b;
destination[3] = a << 4 | a;
dst[0] = (r << 4) | r;
dst[1] = (g << 4) | g;
dst[2] = (b << 4) | b;
dst[3] = (a << 4) | a;
}
FORCE_INLINE void unpackRGB565ToRGBA8(const uint16_t* __restrict source, uint8_t* __restrict destination)
template<> FORCE_INLINE void
unpack<RGB565, uint16_t, uint8_t>(const uint16_t* __restrict src, uint8_t* __restrict dst)
{
uint16_t packedValue = source[0];
uint8_t r = packedValue >> 11;
uint16_t packedValue = src[0];
uint8_t r = (packedValue >> 11) & 0x1F;
uint8_t g = (packedValue >> 5) & 0x3F;
uint8_t b = packedValue & 0x1F;
destination[0] = (r << 3) | (r & 0x7);
destination[1] = (g << 2) | (g & 0x3);
destination[2] = (b << 3) | (b & 0x7);
destination[3] = 0xFF;
dst[0] = (r << 3) | (r & 0x7);
dst[1] = (g << 2) | (g & 0x3);
dst[2] = (b << 3) | (b & 0x7);
dst[3] = 0xFF;
}
FORCE_INLINE void unpackR8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
template<> FORCE_INLINE void
unpack<R8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
{
destination[0] = source[0];
destination[1] = source[0];
destination[2] = source[0];
destination[3] = 0xFF;
dst[0] = src[0];
dst[1] = src[0];
dst[2] = src[0];
dst[3] = 0xFF;
}
FORCE_INLINE void unpackRA8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
template<> FORCE_INLINE void
unpack<RA8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
{
destination[0] = source[0];
destination[1] = source[0];
destination[2] = source[0];
destination[3] = source[1];
dst[0] = src[0];
dst[1] = src[0];
dst[2] = src[0];
dst[3] = src[1];
}
FORCE_INLINE void unpackA8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
template<> FORCE_INLINE void
unpack<A8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
{
destination[0] = 0x0;
destination[1] = 0x0;
destination[2] = 0x0;
destination[3] = source[0];
dst[0] = 0;
dst[1] = 0;
dst[2] = 0;
dst[3] = src[0];
}
FORCE_INLINE void unpackRGB32FToRGBA32F(const float* __restrict source, float* __restrict destination)
template<> FORCE_INLINE void
unpack<RGBA32F, float, float>(const float* __restrict src, float* __restrict dst)
{
destination[0] = source[0];
destination[1] = source[1];
destination[2] = source[2];
destination[3] = 1;
dst[0] = src[0];
dst[1] = src[1];
dst[2] = src[2];
dst[3] = src[3];
}
FORCE_INLINE void unpackR32FToRGBA32F(const float* __restrict source, float* __restrict destination)
template<> FORCE_INLINE void
unpack<RGB32F, float, float>(const float* __restrict src, float* __restrict dst)
{
destination[0] = source[0];
destination[1] = source[0];
destination[2] = source[0];
destination[3] = 1;
dst[0] = src[0];
dst[1] = src[1];
dst[2] = src[2];
dst[3] = 1.0f;
}
FORCE_INLINE void unpackRA32FToRGBA32F(const float* __restrict source, float* __restrict destination)
template<> FORCE_INLINE void
unpack<R32F, float, float>(const float* __restrict src, float* __restrict dst)
{
destination[0] = source[0];
destination[1] = source[0];
destination[2] = source[0];
destination[3] = source[1];
dst[0] = src[0];
dst[1] = src[0];
dst[2] = src[0];
dst[3] = 1.0f;
}
FORCE_INLINE void unpackA32FToRGBA32F(const float* __restrict source, float* __restrict destination)
template<> FORCE_INLINE void
unpack<RA32F, float, float>(const float* __restrict src, float* __restrict dst)
{
destination[0] = 0;
destination[1] = 0;
destination[2] = 0;
destination[3] = source[0];
dst[0] = src[0];
dst[1] = src[0];
dst[2] = src[0];
dst[3] = src[1];
}
template<> FORCE_INLINE void
unpack<A32F, float, float>(const float* __restrict src, float* __restrict dst)
{
dst[0] = 0;
dst[1] = 0;
dst[2] = 0;
dst[3] = src[0];
}
//----------------------------------------------------------------------
// Pixel packing routines.
//
FORCE_INLINE void packRGBA8ToA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
template<int Format, int PremultiplicationOp, typename SrcType, typename DstType>
FORCE_INLINE void
pack(const SrcType* __restrict src,
DstType* __restrict dst)
{
destination[0] = source[3];
NS_ABORT_IF_FALSE(false, "Unimplemented texture format conversion");
}
FORCE_INLINE void packRGBA8ToR8(const uint8_t* __restrict source, uint8_t* __restrict destination)
template<> FORCE_INLINE void
pack<A8, NoPremultiplicationOp, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
{
destination[0] = source[0];
dst[0] = src[3];
}
FORCE_INLINE void packRGBA8ToR8Premultiply(const uint8_t* __restrict source, uint8_t* __restrict destination)
template<> FORCE_INLINE void
pack<A8, Premultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
{
float scaleFactor = source[3] / 255.0f;
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
destination[0] = sourceR;
dst[0] = src[3];
}
template<> FORCE_INLINE void
pack<A8, Unpremultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
{
dst[0] = src[3];
}
template<> FORCE_INLINE void
pack<R8, NoPremultiplicationOp, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
{
dst[0] = src[0];
}
template<> FORCE_INLINE void
pack<R8, Premultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
{
float scaleFactor = src[3] / 255.0f;
uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
dst[0] = srcR;
}
template<> FORCE_INLINE void
pack<R8, Unpremultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
{
float scaleFactor = src[3] ? 255.0f / src[3] : 1.0f;
uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
dst[0] = srcR;
}
template<> FORCE_INLINE void
pack<RA8, NoPremultiplicationOp, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
{
dst[0] = src[0];
dst[1] = src[3];
}
template<> FORCE_INLINE void
pack<RA8, Premultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
{
float scaleFactor = src[3] / 255.0f;
uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
dst[0] = srcR;
dst[1] = src[3];
}
// FIXME: this routine is lossy and must be removed.
FORCE_INLINE void packRGBA8ToR8Unmultiply(const uint8_t* __restrict source, uint8_t* __restrict destination)
template<> FORCE_INLINE void
pack<RA8, Unpremultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
{
float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
destination[0] = sourceR;
float scaleFactor = src[3] ? 255.0f / src[3] : 1.0f;
uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
dst[0] = srcR;
dst[1] = src[3];
}
FORCE_INLINE void packRGBA8ToRA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
template<> FORCE_INLINE void
pack<RGB8, NoPremultiplicationOp, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
{
destination[0] = source[0];
destination[1] = source[3];
dst[0] = src[0];
dst[1] = src[1];
dst[2] = src[2];
}
FORCE_INLINE void packRGBA8ToRA8Premultiply(const uint8_t* __restrict source, uint8_t* __restrict destination)
template<> FORCE_INLINE void
pack<RGB8, Premultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
{
float scaleFactor = source[3] / 255.0f;
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
destination[0] = sourceR;
destination[1] = source[3];
float scaleFactor = src[3] / 255.0f;
uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
uint8_t srcG = static_cast<uint8_t>(src[1] * scaleFactor);
uint8_t srcB = static_cast<uint8_t>(src[2] * scaleFactor);
dst[0] = srcR;
dst[1] = srcG;
dst[2] = srcB;
}
template<> FORCE_INLINE void
pack<RGB8, Unpremultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
{
float scaleFactor = src[3] ? 255.0f / src[3] : 1.0f;
uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
uint8_t srcG = static_cast<uint8_t>(src[1] * scaleFactor);
uint8_t srcB = static_cast<uint8_t>(src[2] * scaleFactor);
dst[0] = srcR;
dst[1] = srcG;
dst[2] = srcB;
}
template<> FORCE_INLINE void
pack<RGBA8, NoPremultiplicationOp, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
{
dst[0] = src[0];
dst[1] = src[1];
dst[2] = src[2];
dst[3] = src[3];
}
template<> FORCE_INLINE void
pack<RGBA8, Premultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
{
float scaleFactor = src[3] / 255.0f;
uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
uint8_t srcG = static_cast<uint8_t>(src[1] * scaleFactor);
uint8_t srcB = static_cast<uint8_t>(src[2] * scaleFactor);
dst[0] = srcR;
dst[1] = srcG;
dst[2] = srcB;
dst[3] = src[3];
}
// FIXME: this routine is lossy and must be removed.
FORCE_INLINE void packRGBA8ToRA8Unmultiply(const uint8_t* __restrict source, uint8_t* __restrict destination)
template<> FORCE_INLINE void
pack<RGBA8, Unpremultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
{
float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
destination[0] = sourceR;
destination[1] = source[3];
float scaleFactor = src[3] ? 255.0f / src[3] : 1.0f;
uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
uint8_t srcG = static_cast<uint8_t>(src[1] * scaleFactor);
uint8_t srcB = static_cast<uint8_t>(src[2] * scaleFactor);
dst[0] = srcR;
dst[1] = srcG;
dst[2] = srcB;
dst[3] = src[3];
}
FORCE_INLINE void packRGBA8ToRGB8(const uint8_t* __restrict source, uint8_t* __restrict destination)
template<> FORCE_INLINE void
pack<RGBA4444, NoPremultiplicationOp, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
{
destination[0] = source[0];
destination[1] = source[1];
destination[2] = source[2];
*dst = ( ((src[0] & 0xF0) << 8)
| ((src[1] & 0xF0) << 4)
| (src[2] & 0xF0)
| (src[3] >> 4) );
}
FORCE_INLINE void packRGBA8ToRGB8Premultiply(const uint8_t* __restrict source, uint8_t* __restrict destination)
template<> FORCE_INLINE void
pack<RGBA4444, Premultiply, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
{
float scaleFactor = source[3] / 255.0f;
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
destination[0] = sourceR;
destination[1] = sourceG;
destination[2] = sourceB;
float scaleFactor = src[3] / 255.0f;
uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
uint8_t srcG = static_cast<uint8_t>(src[1] * scaleFactor);
uint8_t srcB = static_cast<uint8_t>(src[2] * scaleFactor);
*dst = ( ((srcR & 0xF0) << 8)
| ((srcG & 0xF0) << 4)
| (srcB & 0xF0)
| (src[3] >> 4));
}
// FIXME: this routine is lossy and must be removed.
FORCE_INLINE void packRGBA8ToRGB8Unmultiply(const uint8_t* __restrict source, uint8_t* __restrict destination)
template<> FORCE_INLINE void
pack<RGBA4444, Unpremultiply, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
{
float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
destination[0] = sourceR;
destination[1] = sourceG;
destination[2] = sourceB;
float scaleFactor = src[3] ? 255.0f / src[3] : 1.0f;
uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
uint8_t srcG = static_cast<uint8_t>(src[1] * scaleFactor);
uint8_t srcB = static_cast<uint8_t>(src[2] * scaleFactor);
*dst = ( ((srcR & 0xF0) << 8)
| ((srcG & 0xF0) << 4)
| (srcB & 0xF0)
| (src[3] >> 4));
}
// This is only used when the source format is different than kSourceFormatRGBA8.
FORCE_INLINE void packRGBA8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
template<> FORCE_INLINE void
pack<RGBA5551, NoPremultiplicationOp, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
{
destination[0] = source[0];
destination[1] = source[1];
destination[2] = source[2];
destination[3] = source[3];
*dst = ( ((src[0] & 0xF8) << 8)
| ((src[1] & 0xF8) << 3)
| ((src[2] & 0xF8) >> 2)
| (src[3] >> 7));
}
FORCE_INLINE void packRGBA8ToRGBA8Premultiply(const uint8_t* __restrict source, uint8_t* __restrict destination)
template<> FORCE_INLINE void
pack<RGBA5551, Premultiply, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
{
float scaleFactor = source[3] / 255.0f;
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
destination[0] = sourceR;
destination[1] = sourceG;
destination[2] = sourceB;
destination[3] = source[3];
float scaleFactor = src[3] / 255.0f;
uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
uint8_t srcG = static_cast<uint8_t>(src[1] * scaleFactor);
uint8_t srcB = static_cast<uint8_t>(src[2] * scaleFactor);
*dst = ( ((srcR & 0xF8) << 8)
| ((srcG & 0xF8) << 3)
| ((srcB & 0xF8) >> 2)
| (src[3] >> 7));
}
// FIXME: this routine is lossy and must be removed.
FORCE_INLINE void packRGBA8ToRGBA8Unmultiply(const uint8_t* __restrict source, uint8_t* __restrict destination)
template<> FORCE_INLINE void
pack<RGBA5551, Unpremultiply, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
{
float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
destination[0] = sourceR;
destination[1] = sourceG;
destination[2] = sourceB;
destination[3] = source[3];
float scaleFactor = src[3] ? 255.0f / src[3] : 1.0f;
uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
uint8_t srcG = static_cast<uint8_t>(src[1] * scaleFactor);
uint8_t srcB = static_cast<uint8_t>(src[2] * scaleFactor);
*dst = ( ((srcR & 0xF8) << 8)
| ((srcG & 0xF8) << 3)
| ((srcB & 0xF8) >> 2)
| (src[3] >> 7));
}
FORCE_INLINE void packRGBA8ToUnsignedShort4444(const uint8_t* __restrict source, uint16_t* __restrict destination)
template<> FORCE_INLINE void
pack<RGB565, NoPremultiplicationOp, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
{
*destination = (((source[0] & 0xF0) << 8)
| ((source[1] & 0xF0) << 4)
| (source[2] & 0xF0)
| (source[3] >> 4));
*dst = ( ((src[0] & 0xF8) << 8)
| ((src[1] & 0xFC) << 3)
| ((src[2] & 0xF8) >> 3));
}
FORCE_INLINE void packRGBA8ToUnsignedShort4444Premultiply(const uint8_t* __restrict source, uint16_t* __restrict destination)
template<> FORCE_INLINE void
pack<RGB565, Premultiply, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
{
float scaleFactor = source[3] / 255.0f;
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
*destination = (((sourceR & 0xF0) << 8)
| ((sourceG & 0xF0) << 4)
| (sourceB & 0xF0)
| (source[3] >> 4));
float scaleFactor = src[3] / 255.0f;
uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
uint8_t srcG = static_cast<uint8_t>(src[1] * scaleFactor);
uint8_t srcB = static_cast<uint8_t>(src[2] * scaleFactor);
*dst = ( ((srcR & 0xF8) << 8)
| ((srcG & 0xFC) << 3)
| ((srcB & 0xF8) >> 3));
}
// FIXME: this routine is lossy and must be removed.
FORCE_INLINE void packRGBA8ToUnsignedShort4444Unmultiply(const uint8_t* __restrict source, uint16_t* __restrict destination)
template<> FORCE_INLINE void
pack<RGB565, Unpremultiply, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
{
float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
*destination = (((sourceR & 0xF0) << 8)
| ((sourceG & 0xF0) << 4)
| (sourceB & 0xF0)
| (source[3] >> 4));
float scaleFactor = src[3] ? 255.0f / src[3] : 1.0f;
uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
uint8_t srcG = static_cast<uint8_t>(src[1] * scaleFactor);
uint8_t srcB = static_cast<uint8_t>(src[2] * scaleFactor);
*dst = ( ((srcR & 0xF8) << 8)
| ((srcG & 0xFC) << 3)
| ((srcB & 0xF8) >> 3));
}
FORCE_INLINE void packRGBA8ToUnsignedShort5551(const uint8_t* __restrict source, uint16_t* __restrict destination)
template<> FORCE_INLINE void
pack<RGB32F, NoPremultiplicationOp, float, float>(const float* __restrict src, float* __restrict dst)
{
*destination = (((source[0] & 0xF8) << 8)
| ((source[1] & 0xF8) << 3)
| ((source[2] & 0xF8) >> 2)
| (source[3] >> 7));
dst[0] = src[0];
dst[1] = src[1];
dst[2] = src[2];
}
FORCE_INLINE void packRGBA8ToUnsignedShort5551Premultiply(const uint8_t* __restrict source, uint16_t* __restrict destination)
template<> FORCE_INLINE void
pack<RGB32F, Premultiply, float, float>(const float* __restrict src, float* __restrict dst)
{
float scaleFactor = source[3] / 255.0f;
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
*destination = (((sourceR & 0xF8) << 8)
| ((sourceG & 0xF8) << 3)
| ((sourceB & 0xF8) >> 2)
| (source[3] >> 7));
float scaleFactor = src[3];
dst[0] = src[0] * scaleFactor;
dst[1] = src[1] * scaleFactor;
dst[2] = src[2] * scaleFactor;
}
// FIXME: this routine is lossy and must be removed.
FORCE_INLINE void packRGBA8ToUnsignedShort5551Unmultiply(const uint8_t* __restrict source, uint16_t* __restrict destination)
template<> FORCE_INLINE void
pack<RGBA32F, NoPremultiplicationOp, float, float>(const float* __restrict src, float* __restrict dst)
{
float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
*destination = (((sourceR & 0xF8) << 8)
| ((sourceG & 0xF8) << 3)
| ((sourceB & 0xF8) >> 2)
| (source[3] >> 7));
dst[0] = src[0];
dst[1] = src[1];
dst[2] = src[2];
dst[3] = src[3];
}
FORCE_INLINE void packRGBA8ToUnsignedShort565(const uint8_t* __restrict source, uint16_t* __restrict destination)
template<> FORCE_INLINE void
pack<RGBA32F, Premultiply, float, float>(const float* __restrict src, float* __restrict dst)
{
*destination = (((source[0] & 0xF8) << 8)
| ((source[1] & 0xFC) << 3)
| ((source[2] & 0xF8) >> 3));
float scaleFactor = src[3];
dst[0] = src[0] * scaleFactor;
dst[1] = src[1] * scaleFactor;
dst[2] = src[2] * scaleFactor;
dst[3] = src[3];
}
FORCE_INLINE void packRGBA8ToUnsignedShort565Premultiply(const uint8_t* __restrict source, uint16_t* __restrict destination)
template<> FORCE_INLINE void
pack<A32F, NoPremultiplicationOp, float, float>(const float* __restrict src, float* __restrict dst)
{
float scaleFactor = source[3] / 255.0f;
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
*destination = (((sourceR & 0xF8) << 8)
| ((sourceG & 0xFC) << 3)
| ((sourceB & 0xF8) >> 3));
dst[0] = src[3];
}
// FIXME: this routine is lossy and must be removed.
FORCE_INLINE void packRGBA8ToUnsignedShort565Unmultiply(const uint8_t* __restrict source, uint16_t* __restrict destination)
template<> FORCE_INLINE void
pack<A32F, Premultiply, float, float>(const float* __restrict src, float* __restrict dst)
{
float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f;
uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor);
uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor);
uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor);
*destination = (((sourceR & 0xF8) << 8)
| ((sourceG & 0xFC) << 3)
| ((sourceB & 0xF8) >> 3));
dst[0] = src[3];
}
FORCE_INLINE void packRGBA32FToRGB32F(const float* __restrict source, float* __restrict destination)
template<> FORCE_INLINE void
pack<R32F, NoPremultiplicationOp, float, float>(const float* __restrict src, float* __restrict dst)
{
destination[0] = source[0];
destination[1] = source[1];
destination[2] = source[2];
dst[0] = src[0];
}
FORCE_INLINE void packRGBA32FToRGB32FPremultiply(const float* __restrict source, float* __restrict destination)
template<> FORCE_INLINE void
pack<R32F, Premultiply, float, float>(const float* __restrict src, float* __restrict dst)
{
float scaleFactor = source[3];
destination[0] = source[0] * scaleFactor;
destination[1] = source[1] * scaleFactor;
destination[2] = source[2] * scaleFactor;
float scaleFactor = src[3];
dst[0] = src[0] * scaleFactor;
}
FORCE_INLINE void packRGBA32FToRGBA32FPremultiply(const float* __restrict source, float* __restrict destination)
template<> FORCE_INLINE void
pack<RA32F, NoPremultiplicationOp, float, float>(const float* __restrict src, float* __restrict dst)
{
float scaleFactor = source[3];
destination[0] = source[0] * scaleFactor;
destination[1] = source[1] * scaleFactor;
destination[2] = source[2] * scaleFactor;
destination[3] = source[3];
dst[0] = src[0];
dst[1] = src[3];
}
FORCE_INLINE void packRGBA32FToA32F(const float* __restrict source, float* __restrict destination)
template<> FORCE_INLINE void
pack<RA32F, Premultiply, float, float>(const float* __restrict src, float* __restrict dst)
{
destination[0] = source[3];
}
// identical to above, to avoid special-casing
FORCE_INLINE void packRGBA32FToA32FPremultiply(const float* __restrict source, float* __restrict destination)
{
destination[0] = source[3];
}
FORCE_INLINE void packRGBA32FToR32F(const float* __restrict source, float* __restrict destination)
{
destination[0] = source[0];
}
FORCE_INLINE void packRGBA32FToR32FPremultiply(const float* __restrict source, float* __restrict destination)
{
float scaleFactor = source[3];
destination[0] = source[0] * scaleFactor;
}
FORCE_INLINE void packRGBA32FToRA32F(const float* __restrict source, float* __restrict destination)
{
destination[0] = source[0];
destination[1] = source[3];
}
FORCE_INLINE void packRGBA32FToRA32FPremultiply(const float* __restrict source, float* __restrict destination)
{
float scaleFactor = source[3];
destination[0] = source[0] * scaleFactor;
destination[1] = scaleFactor;
float scaleFactor = src[3];
dst[0] = src[0] * scaleFactor;
dst[1] = scaleFactor;
}
/****** END CODE SHARED WITH WEBKIT ******/
template<typename SrcType, typename DstType> FORCE_INLINE void
convertType(const SrcType* __restrict src, DstType* __restrict dst)
{
NS_ABORT_IF_FALSE(false, "Unimplemented texture format conversion");
}
template<> FORCE_INLINE void
convertType<uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
{
dst[0] = src[0];
dst[1] = src[1];
dst[2] = src[2];
dst[3] = src[3];
}
template<> FORCE_INLINE void
convertType<float, float>(const float* __restrict src, float* __restrict dst)
{
dst[0] = src[0];
dst[1] = src[1];
dst[2] = src[2];
dst[3] = src[3];
}
template<> FORCE_INLINE void
convertType<uint8_t, float>(const uint8_t* __restrict src, float* __restrict dst)
{
const float scaleFactor = 1.f / 255.0f;
dst[0] = src[0] * scaleFactor;
dst[1] = src[1] * scaleFactor;
dst[2] = src[2] * scaleFactor;
dst[3] = src[3] * scaleFactor;
}
#undef FORCE_INLINE
} // end namespace WebGLTexelConversions
} // end namespace mozilla

Просмотреть файл

@ -530,17 +530,8 @@ nsEventDispatcher::Dispatch(nsISupports* aTarget,
if (!nsContentUtils::IsChromeDoc(doc)) {
nsPIDOMWindow* win = doc ? doc->GetInnerWindow() : nsnull;
// If we can't dispatch the event to chrome, do nothing.
nsIDOMEventTarget* piTarget = win ? win->GetChromeEventHandler() : nsnull;
nsIDOMEventTarget* piTarget = win ? win->GetParentTarget() : nsnull;
NS_ENSURE_TRUE(piTarget, NS_OK);
nsCOMPtr<nsIFrameLoaderOwner> flo = do_QueryInterface(piTarget);
if (flo) {
nsRefPtr<nsFrameLoader> fl = flo->GetFrameLoader();
if (fl) {
nsIDOMEventTarget* t = fl->GetTabChildGlobalAsEventTarget();
piTarget = t ? t : piTarget;
}
}
// Set the target to be the original dispatch target,
aEvent->target = target;

Просмотреть файл

@ -47,10 +47,10 @@ MODULE = dom
DIRS = \
interfaces/base \
interfaces/canvas \
interfaces/contacts \
interfaces/core \
interfaces/html \
interfaces/events \
interfaces/contacts \
interfaces/settings \
interfaces/stylesheets \
interfaces/sidebar \

Просмотреть файл

@ -1,296 +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/. */
"use strict";
let Cu = Components.utils;
let Ci = Components.interfaces;
let Cc = Components.classes;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
const NS_PREFBRANCH_PREFCHANGE_TOPIC_ID = "nsPref:changed";
const BROWSER_FRAMES_ENABLED_PREF = "dom.mozBrowserFramesEnabled";
/**
* The BrowserElementAPI implements <iframe mozbrowser>.
*
* We detect windows and docshells contained inside <iframe mozbrowser>s and
* alter their behavior so that the page inside the iframe can't tell that it's
* framed and the page outside the iframe can observe changes within the iframe
* (e.g. loadstart/loadstart, locationchange).
*/
function BrowserElementAPI() {}
BrowserElementAPI.prototype = {
classID: Components.ID("{5d6fcab3-6c12-4db6-80fb-352df7a41602}"),
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
Ci.nsISupportsWeakReference]),
/**
* The keys of this map are the set of chrome event handlers we've observed
* which contain a mozbrowser window.
*
* The values in this map are ignored.
*/
_chromeEventHandlersWatching: new WeakMap(),
/**
* The keys of this map are the set of windows we've observed that are
* directly contained in <iframe mozbrowser>s.
*
* The values in this map are ignored.
*/
_topLevelBrowserWindows: new WeakMap(),
_browserFramesPrefEnabled: function BA_browserFramesPrefEnabled() {
var prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
try {
return prefs.getBoolPref(BROWSER_FRAMES_ENABLED_PREF);
}
catch(e) {
return false;
}
},
/**
* Called on browser start, and also when we observe a change in
* the browser-frames-enabled pref.
*/
_init: function BA_init() {
if (this._initialized) {
return;
}
// If browser frames are disabled, watch the pref so we can enable
// ourselves if the pref is flipped. This is important for tests, if
// nothing else.
if (!this._browserFramesPrefEnabled()) {
var prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
prefs.addObserver(BROWSER_FRAMES_ENABLED_PREF, this, /* ownsWeak = */ true);
return;
}
this._initialized = true;
this._progressListener._browserElementAPI = this;
var os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
os.addObserver(this, 'content-document-global-created', /* ownsWeak = */ true);
os.addObserver(this, 'docshell-marked-as-browser-frame', /* ownsWeak = */ true);
},
/**
* Called when we observe a docshell-marked-as-browser-frame event, which
* happens when a docshell is created inside an <iframe mozbrowser>.
*
* A docshell may not be un-marked as a browser frame -- this ensures that
* this event will never fire twice for the same docshell, which guarantees
* that we'll never register duplicate listeners.
*/
_observeDocshellMarkedAsBrowserFrame: function BA_observeDocshellMarkedAsBrowserFrame(docshell) {
docshell.QueryInterface(Ci.nsIWebProgress)
.addProgressListener(this._progressListener,
Ci.nsIWebProgress.NOTIFY_LOCATION |
Ci.nsIWebProgress.NOTIFY_STATE_WINDOW);
},
/**
* Called when a content window is created. If the window is directly or
* indirectly contained in an <iframe mozbrowser>, we'll modify it.
*/
_observeContentGlobalCreated: function BA_observeContentGlobalCreated(win) {
var docshell = win.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShell);
// If this window is not directly or indirectly inside an
// <iframe mozbrowser>, BrowserElementAPI does nothing to it.
if (!docshell.containedInBrowserFrame) {
return;
}
this._initBrowserWindow(win, docshell.isBrowserFrame);
// If this window is directly contained in an <iframe mozbrowser>, do some
// extra work.
if (docshell.isBrowserFrame) {
this._topLevelBrowserWindows.set(win, true);
this._initTopLevelBrowserWindow(win);
}
},
/**
* Initialize a content window which is indirectly or directly contained by
* an <iframe mozbrowser>.
*
* |isTopLevel| is true iff |win| is directly contained by an
* <iframe mozbrowser>.
*/
_initBrowserWindow: function BA_initBrowserWindow(win, isTopLevel) {
// XPCNativeWrapper.unwrap gets us the object that content sees; this is
// the object object that we must define properties on. Otherwise, the
// properties will be visible only to chrome!
var unwrappedWin = XPCNativeWrapper.unwrap(win);
// This property should exist only on the x-ray wrapped object, not on the
// unwrapped object, so we define it on |win|, not |unwrappedWin|.
Object.defineProperty(win, 'browserFrameTop', {
get: function() {
if (isTopLevel) {
return win;
}
if ('browserFrameTop' in win.parent) {
return win.parent.browserFrameTop;
}
// This shouldn't happen, but let's at least throw a semi-meaningful
// error message if it does.
throw new Error('Internal error in window.browserFrameTop.');
}
});
Object.defineProperty(unwrappedWin, 'top', {
get: function() {
return win.browserFrameTop;
}
});
Object.defineProperty(unwrappedWin, 'parent', {
get: function() {
if (isTopLevel) {
return win;
}
return win.parent;
}
});
Object.defineProperty(unwrappedWin, 'frameElement', {
get: function() {
if (isTopLevel) {
return null;
}
return win.frameElement;
}
});
},
/**
* Initialize a content window directly contained by an <iframe mozbrowser>.
*/
_initTopLevelBrowserWindow: function BA_initTopLevelBrowserWindow(win) {
// If we haven't seen this window's chrome event handler before, register
// listeners on it.
var chromeHandler = win.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShell)
.chromeEventHandler;
if (chromeHandler && !this._chromeEventHandlersWatching.has(chromeHandler)) {
this._chromeEventHandlersWatching.set(chromeHandler, true);
this._addChromeEventHandlerListeners(chromeHandler);
}
},
/**
* Add some listeners to a chrome event handler. Don't call this twice for
* the same chrome event handler or we'll get duplicate listeners!
*/
_addChromeEventHandlerListeners: function BA_addChromeEventHandlerListeners(chromeHandler) {
var browserElementAPI = this;
// Listen for DOMTitleChanged events on top-level <iframe mozbrowser>
// windows. (The chrome event handler handles
chromeHandler.addEventListener(
'DOMTitleChanged',
function(e) {
var win = e.target.defaultView;
if (browserElementAPI._topLevelBrowserWindows.has(win)) {
browserElementAPI._fireCustomEvent('titlechange', e.target.title,
win, win.frameElement);
}
},
/* useCapture = */ false,
/* wantsUntrusted = */ false);
},
/**
* Asynchronously fire a vanilla event at the given window's frame element.
* (Presumably, the window's frame element is an <iframe mozbrowser>.)
*
* We'll prepend 'mozbrowser' to the event's name.
*/
_fireEvent: function BA_fireEvent(name, win) {
// Because we're chrome, win.frameElement ignores <iframe mozbrowser>
// boundaries, as desired.
var evt = new win.Event('mozbrowser' + name);
win.setTimeout(function() { win.frameElement.dispatchEvent(evt) }, 0);
},
/**
* Like _fireEvent, but fire a customevent with the given data, instead of a
* vanilla event.
*/
_fireCustomEvent: function BA_fireCustomEvent(name, data, win) {
var evt = new win.CustomEvent('mozbrowser' + name, {detail: data});
win.setTimeout(function() { win.frameElement.dispatchEvent(evt) }, 0);
},
/**
* An nsIWebProgressListener registered on docshells directly contained in an
* <iframe mozbrowser>.
*/
_progressListener: {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener,
Ci.nsISupportsWeakReference,
Ci.nsISupports]),
_getWindow: function(webProgress) {
return webProgress.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindow);
},
onLocationChange: function(webProgress, request, location, flags) {
this._browserElementAPI._fireCustomEvent('locationchange', location.spec,
this._getWindow(webProgress));
},
onStateChange: function(webProgress, request, stateFlags, status) {
if (stateFlags & Ci.nsIWebProgressListener.STATE_START) {
this._browserElementAPI._fireEvent('loadstart', this._getWindow(webProgress));
}
if (stateFlags & Ci.nsIWebProgressListener.STATE_STOP) {
this._browserElementAPI._fireEvent('loadend', this._getWindow(webProgress));
}
},
onStatusChange: function(webProgress, request, status, message) {},
onProgressChange: function(webProgress, request, curSelfProgress,
maxSelfProgress, curTotalProgress, maxTotalProgress) {},
onSecurityChange: function(webProgress, request, aState) {}
},
/**
* nsIObserver::Observe
*/
observe: function BA_observe(subject, topic, data) {
switch(topic) {
case 'app-startup':
this._init();
break;
case 'content-document-global-created':
this._observeContentGlobalCreated(subject);
break;
case 'docshell-marked-as-browser-frame':
this._observeDocshellMarkedAsBrowserFrame(subject);
break;
case NS_PREFBRANCH_PREFCHANGE_TOPIC_ID:
if (data == BROWSER_FRAMES_ENABLED_PREF) {
this._init();
}
break;
}
},
};
var NSGetFactory = XPCOMUtils.generateNSGetFactory([BrowserElementAPI]);

Просмотреть файл

@ -1,3 +0,0 @@
component {5d6fcab3-6c12-4db6-80fb-352df7a41602} BrowserElementAPI.js
contract @mozilla.org/browser-element-api;1 {5d6fcab3-6c12-4db6-80fb-352df7a41602}
category app-startup BrowserElementAPI service,@mozilla.org/browser-element-api;1

Просмотреть файл

@ -0,0 +1,109 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
let Cu = Components.utils;
let Ci = Components.interfaces;
let Cc = Components.classes;
function debug(msg) {
dump("BrowserElementChild - " + msg + "\n");
}
function sendAsyncMsg(msg, data) {
sendAsyncMessage('browser-element-api:' + msg, data);
}
/**
* The BrowserElementChild implements one half of <iframe mozbrowser>.
* (The other half is, unsurprisingly, BrowserElementParent.)
*
* This script is injected into an <iframe mozbrowser> via
* nsIMessageManager::LoadFrameScript().
*
* Our job here is to listen for events within this frame and bubble them up to
* the parent process.
*/
function BrowserElementChild() {
this._init();
};
BrowserElementChild.prototype = {
_init: function() {
debug("Starting up.");
sendAsyncMsg("hello");
docShell.QueryInterface(Ci.nsIWebProgress)
.addProgressListener(this._progressListener,
Ci.nsIWebProgress.NOTIFY_LOCATION |
Ci.nsIWebProgress.NOTIFY_STATE_WINDOW);
addEventListener('DOMTitleChanged',
this._titleChangedHandler.bind(this),
/* useCapture = */ true,
/* wantsUntrusted = */ false);
},
_titleChangedHandler: function(e) {
debug("Got titlechanged: (" + e.target.title + ")");
var win = e.target.defaultView;
// Ignore titlechanges which don't come from the top-level
// <iframe mozbrowser> window.
if (win == content) {
sendAsyncMsg('titlechange', e.target.title);
}
else {
debug("Not top level!");
}
},
// The docShell keeps a weak reference to the progress listener, so we need
// to keep a strong ref to it ourselves.
_progressListener: {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener,
Ci.nsISupportsWeakReference,
Ci.nsISupports]),
_seenLoadStart: false,
onLocationChange: function(webProgress, request, location, flags) {
// We get progress events from subshells here, which is kind of weird.
if (webProgress != docShell) {
return;
}
// Ignore locationchange events which occur before the first loadstart.
// These are usually about:blank loads we don't care about.
if (!this._seenLoadStart) {
return;
}
sendAsyncMsg('locationchange', location.spec);
},
onStateChange: function(webProgress, request, stateFlags, status) {
if (webProgress != docShell) {
return;
}
if (stateFlags & Ci.nsIWebProgressListener.STATE_START) {
this._seenLoadStart = true;
sendAsyncMsg('loadstart');
}
if (stateFlags & Ci.nsIWebProgressListener.STATE_STOP) {
sendAsyncMsg('loadend');
}
},
onStatusChange: function(webProgress, request, status, message) {},
onProgressChange: function(webProgress, request, curSelfProgress,
maxSelfProgress, curTotalProgress, maxTotalProgress) {},
onSecurityChange: function(webProgress, request, aState) {}
},
};
var api = new BrowserElementChild();

Просмотреть файл

@ -0,0 +1,158 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
let Cu = Components.utils;
let Ci = Components.interfaces;
let Cc = Components.classes;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
const NS_PREFBRANCH_PREFCHANGE_TOPIC_ID = "nsPref:changed";
const BROWSER_FRAMES_ENABLED_PREF = "dom.mozBrowserFramesEnabled";
function debug(msg) {
dump("BrowserElementParent - " + msg + "\n");
}
/**
* The BrowserElementParent implements one half of <iframe mozbrowser>.
* (The other half is, unsurprisingly, BrowserElementChild.)
*
* We detect windows and docshells contained inside <iframe mozbrowser>s and
* inject script to listen for certain events in the child. We then listen to
* messages from the child script and take appropriate action here.
*/
function BrowserElementParent() {}
BrowserElementParent.prototype = {
classID: Components.ID("{ddeafdac-cb39-47c4-9cb8-c9027ee36d26}"),
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
Ci.nsISupportsWeakReference]),
/**
* Called on app startup, and also when the browser frames enabled pref is
* changed.
*/
_init: function() {
debug("_init");
if (this._initialized) {
return;
}
// If the pref is disabled, do nothing except wait for the pref to change.
// (This is important for tests, if nothing else.)
if (!this._browserFramesPrefEnabled()) {
var prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
prefs.addObserver(BROWSER_FRAMES_ENABLED_PREF, this, /* ownsWeak = */ true);
return;
}
this._initialized = true;
var os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
os.addObserver(this, 'remote-browser-frame-shown', /* ownsWeak = */ true);
os.addObserver(this, 'in-process-browser-frame-shown', /* ownsWeak = */ true);
},
_browserFramesPrefEnabled: function() {
var prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
try {
return prefs.getBoolPref(BROWSER_FRAMES_ENABLED_PREF);
}
catch(e) {
return false;
}
},
_observeInProcessBrowserFrameShown: function(frameLoader) {
debug("In-process browser frame shown " + frameLoader);
this._setUpMessageManagerListeners(frameLoader);
},
_observeRemoteBrowserFrameShown: function(frameLoader) {
debug("Remote browser frame shown " + frameLoader);
this._setUpMessageManagerListeners(frameLoader);
},
_setUpMessageManagerListeners: function(frameLoader) {
let frameElement = frameLoader.QueryInterface(Ci.nsIFrameLoader).ownerElement;
if (!frameElement) {
debug("No frame element?");
return;
}
let mm = frameLoader.messageManager;
// Messages we receive are handled by functions with parameters
// (frameElement, data), where |data| is the message manager's data object.
function addMessageListener(msg, handler) {
mm.addMessageListener('browser-element-api:' + msg, handler.bind(this, frameElement));
}
addMessageListener("hello", this._recvHello);
addMessageListener("locationchange", this._fireEventFromMsg);
addMessageListener("loadstart", this._fireEventFromMsg);
addMessageListener("loadend", this._fireEventFromMsg);
addMessageListener("titlechange", this._fireEventFromMsg);
mm.loadFrameScript("chrome://global/content/BrowserElementChild.js",
/* allowDelayedLoad = */ true);
},
_recvHello: function(frameElement, data) {
debug("recvHello " + frameElement);
},
/**
* Fire either a vanilla or a custom event, depending on the contents of
* |data|.
*/
_fireEventFromMsg: function(frameElement, data) {
let name = data.name;
let detail = data.json;
debug('fireEventFromMsg: ' + name + ' ' + detail);
let evtName = name.substring('browser-element-api:'.length);
let win = frameElement.ownerDocument.defaultView;
let evt;
// This will have to change if we ever want to send a CustomEvent with null
// detail. For now, it's OK.
if (detail !== undefined && detail !== null) {
evt = new win.CustomEvent('mozbrowser' + evtName, {detail: detail});
}
else {
evt = new win.Event('mozbrowser' + evtName);
}
frameElement.dispatchEvent(evt);
},
observe: function(subject, topic, data) {
switch(topic) {
case 'app-startup':
this._init();
break;
case NS_PREFBRANCH_PREFCHANGE_TOPIC_ID:
if (data == BROWSER_FRAMES_ENABLED_PREF) {
this._init();
}
break;
case 'remote-browser-frame-shown':
this._observeRemoteBrowserFrameShown(subject);
break;
case 'in-process-browser-frame-shown':
this._observeInProcessBrowserFrameShown(subject);
break;
case 'content-document-global-created':
this._observeContentGlobalCreated(subject);
break;
}
},
};
var NSGetFactory = XPCOMUtils.generateNSGetFactory([BrowserElementParent]);

Просмотреть файл

@ -0,0 +1,3 @@
component {ddeafdac-cb39-47c4-9cb8-c9027ee36d26} BrowserElementParent.js
contract @mozilla.org/browser-element-parent;1 {ddeafdac-cb39-47c4-9cb8-c9027ee36d26}
category app-startup BrowserElementParent service,@mozilla.org/browser-element-parent;1

Просмотреть файл

@ -54,8 +54,8 @@ DIRS = \
EXTRA_PP_COMPONENTS = \
ConsoleAPI.js \
ConsoleAPI.manifest \
BrowserElementAPI.js \
BrowserElementAPI.manifest \
BrowserElementParent.js \
BrowserElementParent.manifest \
$(NULL)
EXTRA_JS_MODULES = ConsoleAPIStorage.jsm \

Просмотреть файл

@ -5,6 +5,8 @@
#ifndef mozilla_dom_ScreenOrientation_h
#define mozilla_dom_ScreenOrientation_h
#include "IPC/IPCMessageUtils.h"
namespace mozilla {
namespace dom {
@ -22,24 +24,6 @@ enum ScreenOrientation {
eScreenOrientation_EndGuard
};
/**
* ScreenOrientationWrapper is a class wrapping ScreenOrientation so it can be
* used with Observer<T> which is taking a class, not an enum.
* C++11 should make this useless.
*/
class ScreenOrientationWrapper {
public:
ScreenOrientationWrapper()
: orientation(eScreenOrientation_None)
{}
ScreenOrientationWrapper(ScreenOrientation aOrientation)
: orientation(aOrientation)
{}
ScreenOrientation orientation;
};
} // namespace dom
} // namespace mozilla

Просмотреть файл

@ -478,8 +478,9 @@ DOMApplicationManifest.prototype = {
},
fullLaunchPath: function(aStartPoint) {
let startPoint = aStartPoint || "";
let launchPath = this._localeProp("launch_path") || "";
return this._origin.resolve(launchPath + aStartPoint);
return this._origin.resolve(launchPath + startPoint);
}
};

Просмотреть файл

@ -1546,6 +1546,9 @@ static nsDOMClassInfoData sClassInfoData[] = {
NS_DEFINE_CLASSINFO_DATA(WebGLExtensionLoseContext, WebGLExtensionSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS |
nsIXPCScriptable::WANT_ADDPROPERTY)
NS_DEFINE_CLASSINFO_DATA(WebGLExtensionCompressedTextureS3TC, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS |
nsIXPCScriptable::WANT_ADDPROPERTY)
NS_DEFINE_CLASSINFO_DATA(PaintRequest, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
@ -4250,6 +4253,10 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_ENTRY(nsIWebGLExtensionLoseContext)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(WebGLExtensionCompressedTextureS3TC, nsIWebGLExtensionCompressedTextureS3TC)
DOM_CLASSINFO_MAP_ENTRY(nsIWebGLExtensionCompressedTextureS3TC)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(PaintRequest, nsIDOMPaintRequest)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMPaintRequest)
DOM_CLASSINFO_MAP_END

Просмотреть файл

@ -489,6 +489,7 @@ DOMCI_CLASS(WebGLExtension)
DOMCI_CLASS(WebGLExtensionStandardDerivatives)
DOMCI_CLASS(WebGLExtensionTextureFilterAnisotropic)
DOMCI_CLASS(WebGLExtensionLoseContext)
DOMCI_CLASS(WebGLExtensionCompressedTextureS3TC)
DOMCI_CLASS(PaintRequest)
DOMCI_CLASS(PaintRequestList)

Просмотреть файл

@ -2341,19 +2341,46 @@ nsGlobalWindow::SetOpenerWindow(nsIDOMWindow* aOpener,
#endif
}
static
already_AddRefed<nsIDOMEventTarget>
TryGetTabChildGlobalAsEventTarget(nsISupports *aFrom)
{
nsCOMPtr<nsIFrameLoaderOwner> frameLoaderOwner = do_QueryInterface(aFrom);
if (!frameLoaderOwner) {
return NULL;
}
nsRefPtr<nsFrameLoader> frameLoader = frameLoaderOwner->GetFrameLoader();
if (!frameLoader) {
return NULL;
}
nsCOMPtr<nsIDOMEventTarget> eventTarget =
frameLoader->GetTabChildGlobalAsEventTarget();
return eventTarget.forget();
}
void
nsGlobalWindow::UpdateParentTarget()
{
nsCOMPtr<nsIFrameLoaderOwner> flo = do_QueryInterface(mChromeEventHandler);
if (flo) {
nsRefPtr<nsFrameLoader> fl = flo->GetFrameLoader();
if (fl) {
mParentTarget = fl->GetTabChildGlobalAsEventTarget();
}
// Try to get our frame element's tab child global (its in-process message
// manager). If that fails, fall back to the chrome event handler's tab
// child global, and if it doesn't have one, just use the chrome event
// handler itself.
nsCOMPtr<nsIDOMElement> frameElement = GetFrameElementInternal();
nsCOMPtr<nsIDOMEventTarget> eventTarget =
TryGetTabChildGlobalAsEventTarget(frameElement);
if (!eventTarget) {
eventTarget = TryGetTabChildGlobalAsEventTarget(mChromeEventHandler);
}
if (!mParentTarget) {
mParentTarget = mChromeEventHandler;
if (!eventTarget) {
eventTarget = mChromeEventHandler;
}
mParentTarget = eventTarget;
}
bool

Просмотреть файл

@ -82,8 +82,10 @@ nsScreen::Create(nsPIDOMWindow* aWindow)
nsRefPtr<nsScreen> screen = new nsScreen();
screen->BindToOwner(aWindow);
hal::RegisterScreenOrientationObserver(screen);
hal::GetCurrentScreenOrientation(&(screen->mOrientation));
hal::RegisterScreenConfigurationObserver(screen);
hal::ScreenConfiguration config;
hal::GetCurrentScreenConfiguration(&config);
screen->mOrientation = config.orientation();
return screen.forget();
}
@ -95,7 +97,7 @@ nsScreen::nsScreen()
nsScreen::~nsScreen()
{
hal::UnregisterScreenOrientationObserver(this);
hal::UnregisterScreenConfigurationObserver(this);
}
@ -285,10 +287,10 @@ nsScreen::GetAvailRect(nsRect& aRect)
}
void
nsScreen::Notify(const ScreenOrientationWrapper& aOrientation)
nsScreen::Notify(const hal::ScreenConfiguration& aConfiguration)
{
ScreenOrientation previousOrientation = mOrientation;
mOrientation = aOrientation.orientation;
mOrientation = aConfiguration.orientation();
NS_ASSERTION(mOrientation != eScreenOrientation_None &&
mOrientation != eScreenOrientation_EndGuard &&

Просмотреть файл

@ -37,14 +37,13 @@
#ifndef nsScreen_h___
#define nsScreen_h___
#include "mozilla/dom/ScreenOrientation.h"
#include "mozilla/Hal.h"
#include "nsIDOMScreen.h"
#include "nsISupports.h"
#include "nsIScriptContext.h"
#include "nsCOMPtr.h"
#include "mozilla/dom/ScreenOrientation.h"
#include "nsDOMEventTargetHelper.h"
#include "mozilla/Observer.h"
class nsIDocShell;
class nsDeviceContext;
@ -53,7 +52,7 @@ struct nsRect;
// Script "screen" object
class nsScreen : public nsDOMEventTargetHelper
, public nsIDOMScreen
, public mozilla::hal::ScreenOrientationObserver
, public mozilla::hal::ScreenConfigurationObserver
{
public:
static already_AddRefed<nsScreen> Create(nsPIDOMWindow* aWindow);
@ -67,7 +66,7 @@ public:
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsScreen,
nsDOMEventTargetHelper)
void Notify(const mozilla::dom::ScreenOrientationWrapper& aOrientation);
void Notify(const mozilla::hal::ScreenConfiguration& aConfiguration);
protected:
nsDeviceContext* GetDeviceContext();

Просмотреть файл

@ -175,7 +175,7 @@ Contact.prototype = {
// ContactManager
const CONTACTMANAGER_CONTRACTID = "@mozilla.org/contactManager;1";
const CONTACTMANAGER_CID = Components.ID("{50a820b0-ced0-11e0-9572-0800200c9a66}");
const CONTACTMANAGER_CID = Components.ID("{d9ca0950-93d1-11e1-b0c4-0800200c9a66}");
const nsIDOMContactManager = Components.interfaces.nsIDOMContactManager;
function ContactManager()
@ -185,6 +185,18 @@ function ContactManager()
ContactManager.prototype = {
__proto__: DOMRequestIpcHelper.prototype,
_oncontactchange: null,
set oncontactchange(aCallback) {
if (this.hasPrivileges)
this._oncontactchange = aCallback;
else
throw Components.results.NS_ERROR_FAILURE;
},
get oncontactchange() {
return this._oncontactchange;
},
save: function save(aContact) {
let request;
@ -216,17 +228,21 @@ ContactManager.prototype = {
for (let field in newContact.properties)
newContact.properties[field] = aContact[field];
let reason;
if (aContact.id == "undefined") {
// for example {25c00f01-90e5-c545-b4d4-21E2ddbab9e0} becomes
// 25c00f0190e5c545b4d421E2ddbab9e0
aContact.id = this._getRandomId().replace('-', '').replace('{', '').replace('}', '');
aContact.id = this._getRandomId().replace('-', '', 'g').replace('{', '').replace('}', '');
reason = "create";
} else {
reason = "update";
}
this._setMetaData(newContact, aContact);
debug("send: " + JSON.stringify(newContact));
request = this.createRequest();
cpmm.sendAsyncMessage("Contact:Save", {contact: newContact,
requestID: this.getRequestId(request)});
requestID: this.getRequestId({request: request, reason: reason })});
return request;
} else {
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
@ -238,7 +254,7 @@ ContactManager.prototype = {
if (this.hasPrivileges) {
request = this.createRequest();
cpmm.sendAsyncMessage("Contact:Remove", {id: aRecord.id,
requestID: this.getRequestId(request)});
requestID: this.getRequestId({request: request, reason: "remove"})});
return request;
} else {
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
@ -273,7 +289,7 @@ ContactManager.prototype = {
if (req) {
let result = this._convertContactsArray(contacts);
debug("result: " + JSON.stringify(result));
Services.DOMRequest.fireSuccess(req, result);
Services.DOMRequest.fireSuccess(req.request, result);
} else {
debug("no request stored!" + msg.requestID);
}
@ -283,7 +299,13 @@ ContactManager.prototype = {
case "Contact:Remove:Return:OK":
req = this.getRequest(msg.requestID);
if (req)
Services.DOMRequest.fireSuccess(req, null);
Services.DOMRequest.fireSuccess(req.request, null);
// Fire oncontactchange event
if (this._oncontactchange) {
let event = new MozContactEvent(msg.contactID, req.reason);
this._oncontactchange.handleEvent(event);
}
break;
case "Contacts:Find:Return:KO":
case "Contact:Save:Return:KO":
@ -291,7 +313,7 @@ ContactManager.prototype = {
case "Contacts:Clear:Return:KO":
req = this.getRequest(msg.requestID);
if (req)
Services.DOMRequest.fireError(req, msg.errorMsg);
Services.DOMRequest.fireError(req.request, msg.errorMsg);
break;
default:
debug("Wrong message: " + aMessage.name);
@ -304,7 +326,7 @@ ContactManager.prototype = {
if (this.hasPrivileges) {
request = this.createRequest();
cpmm.sendAsyncMessage("Contacts:Find", {findOptions: aOptions,
requestID: this.getRequestId(request)});
requestID: this.getRequestId({request: request, reason: "find"})});
return request;
} else {
debug("find not allowed");
@ -316,7 +338,7 @@ ContactManager.prototype = {
let request;
if (this.hasPrivileges) {
request = this.createRequest();
cpmm.sendAsyncMessage("Contacts:Clear", {requestID: this.getRequestId(request)});
cpmm.sendAsyncMessage("Contacts:Clear", {requestID: this.getRequestId({request: request, reason: "remove"})});
return request;
} else {
debug("clear not allowed");
@ -346,6 +368,13 @@ ContactManager.prototype = {
debug("has privileges :" + this.hasPrivileges);
},
// Called from DOMRequestIpcHelper
uninit: function uninit() {
debug("uninit call");
if (this._oncontactchange)
this._oncontactchange = null;
},
classID : CONTACTMANAGER_CID,
QueryInterface : XPCOMUtils.generateQI([nsIDOMContactManager, Ci.nsIDOMGlobalPropertyInitializer]),
@ -356,4 +385,31 @@ ContactManager.prototype = {
flags: nsIClassInfo.DOM_OBJECT})
}
// MozContactEvent object
function MozContactEvent(aContactID, aReason) {
debug("ContactEventConstr: " + aContactID + ", " + aReason);
this._contactID = aContactID;
this._reason = aReason;
}
MozContactEvent.prototype = {
get contactID() {
return this._contactID;
},
get reason() {
return this._reason;
},
classID: Components.ID("{a8cd4ba0-93d1-11e1-b0c4-0800200c9a66}"),
QueryInterface: XPCOMUtils.generateQI([Ci.mozIDOMContactEvent]),
classInfo: XPCOMUtils.generateCI({classID: Components.ID("{a8cd4ba0-93d1-11e1-b0c4-0800200c9a66}"),
contractID: "@mozilla.org/contact-event;1",
interfaces: [Ci.mozIDOMContactEvent],
flags: Ci.nsIClassInfo.DOM_OBJECT,
classDescription: "Contact Change Event"})
}
const NSGetFactory = XPCOMUtils.generateNSGetFactory([Contact, ContactManager, ContactProperties, ContactAddress, ContactFindOptions])

Просмотреть файл

@ -11,6 +11,6 @@ component {da0f7040-388b-11e1-b86c-0800200c9a66} ContactManager.js
contract @mozilla.org/contact;1 {da0f7040-388b-11e1-b86c-0800200c9a66}
category JavaScript-global-constructor mozContact @mozilla.org/contact;1
component {50a820b0-ced0-11e0-9572-0800200c9a66} ContactManager.js
contract @mozilla.org/contactManager;1 {50a820b0-ced0-11e0-9572-0800200c9a66}
component {d9ca0950-93d1-11e1-b0c4-0800200c9a66} ContactManager.js
contract @mozilla.org/contactManager;1 {d9ca0950-93d1-11e1-b0c4-0800200c9a66}
category JavaScript-navigator-property mozContacts @mozilla.org/contactManager;1

Просмотреть файл

@ -95,21 +95,28 @@ let DOMContactManager = {
debug("result:" + JSON.stringify(result));
ppmm.sendAsyncMessage("Contacts:Find:Return:OK", {requestID: msg.requestID, contacts: result});
}.bind(this),
function(aErrorMsg) { ppmm.sendAsyncMessage("Contacts:Find:Return:KO", { requestID: msg.requestID, errorMsg: aErrorMsg }) }.bind(this),
function(aErrorMsg) { ppmm.sendAsyncMessage("Contacts:Find:Return:KO", { requestID: msg.requestID, errorMsg: aErrorMsg }) }.bind(this),
msg.findOptions);
break;
case "Contact:Save":
this._db.saveContact(msg.contact, function() { ppmm.sendAsyncMessage("Contact:Save:Return:OK", { requestID: msg.requestID }); }.bind(this),
function(aErrorMsg) { ppmm.sendAsyncMessage("Contact:Save:Return:KO", { requestID: msg.requestID, errorMsg: aErrorMsg }); }.bind(this));
this._db.saveContact(
msg.contact,
function() { ppmm.sendAsyncMessage("Contact:Save:Return:OK", { requestID: msg.requestID, contactID: msg.contact.id }); }.bind(this),
function(aErrorMsg) { ppmm.sendAsyncMessage("Contact:Save:Return:KO", { requestID: msg.requestID, errorMsg: aErrorMsg }); }.bind(this)
);
break;
case "Contact:Remove":
this._db.removeContact(msg.id,
function() { ppmm.sendAsyncMessage("Contact:Remove:Return:OK", { requestID: msg.requestID }); }.bind(this),
function(aErrorMsg) { ppmm.sendAsyncMessage("Contact:Remove:Return:KO", { requestID: msg.requestID, errorMsg: aErrorMsg }); }.bind(this));
this._db.removeContact(
msg.id,
function() { ppmm.sendAsyncMessage("Contact:Remove:Return:OK", { requestID: msg.requestID, contactID: msg.id }); }.bind(this),
function(aErrorMsg) { ppmm.sendAsyncMessage("Contact:Remove:Return:KO", { requestID: msg.requestID, errorMsg: aErrorMsg }); }.bind(this)
);
break;
case "Contacts:Clear":
this._db.clear(function() { ppmm.sendAsyncMessage("Contacts:Clear:Return:OK", { requestID: msg.requestID }); }.bind(this),
function(aErrorMsg) { ppmm.sendAsyncMessage("Contacts:Clear:Return:KO", { requestID: msg.requestID, errorMsg: aErrorMsg }); }.bind(this));
this._db.clear(
function() { ppmm.sendAsyncMessage("Contacts:Clear:Return:OK", { requestID: msg.requestID }); }.bind(this),
function(aErrorMsg) { ppmm.sendAsyncMessage("Contacts:Clear:Return:KO", { requestID: msg.requestID, errorMsg: aErrorMsg }); }.bind(this)
);
}
}
}

Просмотреть файл

@ -231,6 +231,12 @@ var steps = [
ok(true, "Adding a new contact1");
createResult1 = new mozContact();
createResult1.init(properties1);
mozContacts.oncontactchange = function(event) {
is(event.contactID, createResult1.id, "Same contactID");
is(event.reason, "create", "Same reason");
}
req = navigator.mozContacts.save(createResult1);
req.onsuccess = function () {
ok(createResult1.id, "The contact now has an ID.");
@ -255,11 +261,135 @@ var steps = [
};
req.onerror = onFailure;
},
function () {
ok(true, "Retrieving by substring and update");
mozContacts.oncontactchange = function(event) {
is(event.contactID, findResult1.id, "Same contactID");
is(event.reason, "update", "Same reason");
}
var options = {filterBy: ["name"],
filterOp: "contains",
filterValue: properties1.name.substring(0,3)};
req = mozContacts.find(options);
req.onsuccess = function () {
ok(req.result.length == 1, "Found exactly 1 contact.");
findResult1 = req.result[0];
findResult1.jobTitle = ["new Job"];
ok(findResult1.id == sample_id1, "Same ID");
checkContacts(createResult1, properties1);
next();
};
req.onerror = onFailure;
},
function () {
ok(true, "Adding a new contact");
mozContacts.oncontactchange = function(event) {
is(event.contactID, createResult2.id, "Same contactID");
is(event.reason, "create", "Same reason");
}
createResult2 = new mozContact();
createResult2.init({name: "newName"});
req = navigator.mozContacts.save(createResult2);
req.onsuccess = function () {
ok(createResult2.id, "The contact now has an ID.");
next();
};
req.onerror = onFailure;
},
function () {
ok(true, "Retrieving by substring");
var options = {filterBy: ["name"],
filterOp: "contains",
filterValue: properties1.name.substring(0,3)};
req = mozContacts.find(options);
req.onsuccess = function () {
ok(req.result.length == 1, "Found exactly 1 contact.");
findResult1 = req.result[0];
checkContacts(createResult1, findResult1);
next();
};
req.onerror = onFailure;
},
function () {
ok(true, "Remove contact1");
mozContacts.oncontactchange = function(event) {
is(event.contactID, createResult1.id, "Same contactID");
is(event.reason, "remove", "Same reason");
}
req = navigator.mozContacts.remove(createResult1);
req.onsuccess = function () {
next();
};
req.onerror = onFailure;
},
function () {
ok(true, "Retrieving by substring");
var options = {filterBy: ["name"],
filterOp: "contains",
filterValue: properties1.name.substring(0,3)};
req = mozContacts.find(options);
req.onsuccess = function () {
ok(req.result.length == 0, "Found no contact.");
next();
};
req.onerror = onFailure;
},
function () {
ok(true, "Remove contact2");
mozContacts.oncontactchange = function(event) {
is(event.contactID, createResult2.id, "Same contactID");
is(event.reason, "remove", "Same reason");
}
req = navigator.mozContacts.remove(createResult2);
req.onsuccess = function () {
next();
};
req.onerror = onFailure;
},
function () {
ok(true, "Retrieving by substring");
var options = {filterBy: ["name"],
filterOp: "contains",
filterValue: properties1.name.substring(0,3)};
req = mozContacts.find(options);
req.onsuccess = function () {
ok(req.result.length == 0, "Found no contact.");
next();
};
req.onerror = onFailure;
},
function () {
ok(true, "Deleting database");
mozContacts.oncontactchange = function(event) {
is(event.contactID, "undefined", "Same contactID");
is(event.reason, "remove", "Same reason");
}
req = mozContacts.clear();
req.onsuccess = function () {
ok(true, "Deleted the database");
next();
};
req.onerror = onFailure;
},
function () {
ok(true, "Adding a new contact with properties1");
createResult1 = new mozContact();
createResult1.init(properties1);
req = navigator.mozContacts.save(createResult1);
req.onsuccess = function () {
ok(createResult1.id, "The contact now has an ID.");
sample_id1 = createResult1.id;
checkContacts(properties1, createResult1);
next();
};
req.onerror = onFailure;
},
function () {
ok(true, "Retrieving by substring tel1");
var options = {filterBy: ["tel"],
filterOp: "contains",
filterValue: properties1.tel[1].substring(1,5)};
mozContacts.oncontactchange = null;
req = mozContacts.find(options);
req.onsuccess = function () {
ok(req.result.length == 1, "Found exactly 1 contact.");

Просмотреть файл

@ -178,6 +178,16 @@ interface nsIWebGLExtensionTextureFilterAnisotropic : nsIWebGLExtension
const WebGLenum MAX_TEXTURE_MAX_ANISOTROPY_EXT = 0x84FF;
};
[scriptable, builtinclass, uuid(a1508b6f-f2ab-44cf-bbb4-3cfb339e1e8a)]
interface nsIWebGLExtensionCompressedTextureS3TC : nsIWebGLExtension
{
/* Compressed Texture Formats */
const WebGLenum COMPRESSED_RGB_S3TC_DXT1_EXT = 0x83F0;
const WebGLenum COMPRESSED_RGBA_S3TC_DXT1_EXT = 0x83F1;
const WebGLenum COMPRESSED_RGBA_S3TC_DXT3_EXT = 0x83F2;
const WebGLenum COMPRESSED_RGBA_S3TC_DXT5_EXT = 0x83F3;
};
[scriptable, builtinclass, uuid(a1fdfb76-6a08-4a1a-b0c9-d92ef3357cb9)]
interface nsIDOMWebGLRenderingContext : nsISupports
{

Просмотреть файл

@ -4,6 +4,7 @@
#include "domstubs.idl"
#include "nsIDOMContactProperties.idl"
#include "nsIDOMEvent.idl"
interface nsIArray;
interface nsIDOMContactFindOptions;
@ -20,7 +21,14 @@ interface nsIDOMContact : nsIDOMContactProperties
void init(in nsIDOMContactProperties properties); // Workaround BUG 723206
};
[scriptable, uuid(50a820b0-ced0-11e0-9572-0800200c9a66)]
[scriptable, uuid(a8cd4ba0-93d1-11e1-b0c4-0800200c9a66)]
interface mozIDOMContactEvent : nsIDOMEvent
{
readonly attribute DOMString contactID;
readonly attribute DOMString reason;
};
[scriptable, uuid(d9ca0950-93d1-11e1-b0c4-0800200c9a66)]
interface nsIDOMContactManager : nsISupports
{
nsIDOMDOMRequest find(in nsIDOMContactFindOptions options);
@ -30,4 +38,6 @@ interface nsIDOMContactManager : nsISupports
nsIDOMDOMRequest save(in nsIDOMContact contact);
nsIDOMDOMRequest remove(in nsIDOMContact contact);
};
attribute nsIDOMEventListener oncontactchange;
};

Просмотреть файл

@ -51,4 +51,4 @@ interface nsIDOMContactProperties : nsISupports
attribute jsval anniversary; // Date
attribute jsval sex; // DOMString
attribute jsval genderIdentity; // DOMString
};
};

Просмотреть файл

@ -629,7 +629,8 @@ bool
TabParent::RecvGetDPI(float* aValue)
{
TryCacheDPI();
NS_ABORT_IF_FALSE(mDPI > 0,
NS_ABORT_IF_FALSE(mDPI > 0,
"Must not ask for DPI before OwnerElement is received!");
*aValue = mDPI;
return true;
@ -864,6 +865,17 @@ TabParent::TryCacheDPI()
}
nsCOMPtr<nsIWidget> widget = GetWidget();
if (!widget && mFrameElement) {
// Even if we don't have a widget (e.g. because we're display:none), there's
// probably a widget somewhere in the hierarchy our frame element lives in.
nsCOMPtr<nsIDOMDocument> ownerDoc;
mFrameElement->GetOwnerDocument(getter_AddRefs(ownerDoc));
nsCOMPtr<nsIDocument> doc = do_QueryInterface(ownerDoc);
widget = nsContentUtils::WidgetForDocument(doc);
}
if (widget) {
mDPI = widget->GetDPI();
}

Просмотреть файл

@ -1,3 +1,4 @@
toolkit.jar:
content/global/test-ipc.xul (test.xul)
content/global/remote-test-ipc.js (remote-test.js)
content/global/BrowserElementChild.js (../base/BrowserElementChild.js)

Просмотреть файл

@ -116,6 +116,7 @@ nsIDOMWindowInternalWarning=Use of nsIDOMWindowInternal is deprecated. Use nsIDO
InputEncodingWarning=Use of inputEncoding is deprecated.
# LOCALIZATION NOTE: Do not translate "MozBeforePaint" and "mozRequestAnimationFrame"
MozBeforePaintWarning=MozBeforePaint events are no longer supported. mozRequestAnimationFrame must be passed a non-null callback argument.
FullScreenDeniedBlocked=Request for full-screen was denied because this domain has been blocked from full-screen by user.
FullScreenDeniedDisabled=Request for full-screen was denied because full-screen API is disabled by user preference.
FullScreenDeniedFocusedPlugin=Request for full-screen was denied because a windowed plugin is focused.
FullScreenDeniedHidden=Request for full-screen was denied because the document is no longer visible.

Просмотреть файл

@ -71,8 +71,10 @@
USING_WORKERS_NAMESPACE
using namespace mozilla::dom::gonk;
using namespace mozilla::dom::bluetooth;
using namespace mozilla::ipc;
#ifdef MOZ_B2G_BT
using namespace mozilla::dom::bluetooth;
#endif
namespace {
@ -394,10 +396,8 @@ SystemWorkerManager::InitBluetooth(JSContext *cx)
// see if we can load functions out of bluedroid. If not, assume
// it's an emulator and don't start the bluetooth thread.
if(EnsureBluetoothInit()) {
#endif
#endif
StartDBus();
#ifdef MOZ_B2G_BT
#ifdef MOZ_WIDGET_GONK
}
else {

Просмотреть файл

@ -59,6 +59,7 @@ DIRS += \
storageevent \
pointerlock \
browser-frame \
webapps \
$(NULL)
#needs IPC support, also tests do not run successfully in Firefox for now

Просмотреть файл

@ -54,7 +54,6 @@ _TEST_FILES = \
test_browserFrame5.html \
test_browserFrame6.html \
test_browserFrame7.html \
test_browserFrame8.html \
$(NULL)
libs:: $(_TEST_FILES)

Просмотреть файл

@ -3,75 +3,91 @@
// Helpers for managing the browser frame preferences.
const browserFrameHelpers = {
'getEnabledPref': function() {
_getBoolPref: function(pref) {
try {
return SpecialPowers.getBoolPref('dom.mozBrowserFramesEnabled');
return SpecialPowers.getBoolPref(pref);
}
catch(e) {
catch (e) {
return undefined;
}
},
'getWhitelistPref': function() {
try {
return SpecialPowers.getCharPref('dom.mozBrowserFramesWhitelist');
}
catch(e) {
return undefined;
}
},
'getOOPDisabledPref': function() {
try {
return SpecialPowers.getBoolPref('dom.ipc.tabs.disabled');
}
catch(e) {
return undefined;
}
},
'setEnabledPref': function(enabled) {
if (enabled !== undefined) {
SpecialPowers.setBoolPref('dom.mozBrowserFramesEnabled', enabled);
}
else {
SpecialPowers.clearUserPref('dom.mozBrowserFramesEnabled');
}
},
'setWhitelistPref': function(whitelist) {
if (whitelist !== undefined) {
SpecialPowers.setCharPref('dom.mozBrowserFramesWhitelist', whitelist);
}
else {
SpecialPowers.clearUserPref('dom.mozBrowserFramesWhitelist');
}
},
'setOOPDisabledPref': function(value) {
_setBoolPref: function(pref, value) {
if (value !== undefined) {
SpecialPowers.setBoolPref('dom.ipc.tabs.disabled', value);
SpecialPowers.setBoolPref(pref, value);
}
else {
SpecialPowers.clearUserPref('dom.ipc.tabs.disabled');
SpecialPowers.clearUserPref(pref);
}
},
'addToWhitelist': function() {
var whitelist = browserFrameHelpers.getWhitelistPref();
whitelist += ', http://' + window.location.host + ', ';
browserFrameHelpers.setWhitelistPref(whitelist);
_getCharPref: function(pref) {
try {
return SpecialPowers.getCharPref(pref);
}
catch (e) {
return undefined;
}
},
'restoreOriginalPrefs': function() {
browserFrameHelpers.setEnabledPref(browserFrameHelpers.origEnabledPref);
browserFrameHelpers.setWhitelistPref(browserFrameHelpers.origWhitelistPref);
browserFrameHelpers.setOOPDisabledPref(browserFrameHelpers.origOOPDisabledPref);
_setCharPref: function(pref, value) {
if (value !== undefined) {
SpecialPowers.setCharPref(pref, value);
}
else {
SpecialPowers.clearUserPref(pref);
}
},
getEnabledPref: function() {
return this._getBoolPref('dom.mozBrowserFramesEnabled');
},
setEnabledPref: function(value) {
this._setBoolPref('dom.mozBrowserFramesEnabled', value);
},
getWhitelistPref: function() {
return this._getCharPref('dom.mozBrowserFramesWhitelist');
},
setWhitelistPref: function(whitelist) {
this._setCharPref('dom.mozBrowserFramesWhitelist', whitelist);
},
getOOPDisabledPref: function() {
return this._getBoolPref('dom.ipc.tabs.disabled');
},
setOOPDisabledPref: function(value) {
this._setBoolPref('dom.ipc.tabs.disabled', value);
},
getPageThumbsEnabledPref: function() {
return this._getBoolPref('browser.pageThumbs.enabled');
},
setPageThumbsEnabledPref: function(value) {
this._setBoolPref('browser.pageThumbs.enabled', value);
},
addToWhitelist: function() {
var whitelist = this.getWhitelistPref();
whitelist += ', http://' + window.location.host + ', ';
this.setWhitelistPref(whitelist);
},
restoreOriginalPrefs: function() {
this.setEnabledPref(this.origEnabledPref);
this.setWhitelistPref(this.origWhitelistPref);
this.setOOPDisabledPref(this.origOOPDisabledPref);
this.setPageThumbsEnabledPref(this.origPageThumbsEnabledPref);
},
'origEnabledPref': null,
'origWhitelistPref': null,
'origOOPDisabledPref': null,
'origPageThumbsEnabledPref': null,
// Two basically-empty pages from two different domains you can load.
'emptyPage1': 'http://example.com' +
@ -85,10 +101,19 @@ const browserFrameHelpers = {
browserFrameHelpers.origEnabledPref = browserFrameHelpers.getEnabledPref();
browserFrameHelpers.origWhitelistPref = browserFrameHelpers.getWhitelistPref();
browserFrameHelpers.origOOPDisabledPref = browserFrameHelpers.getOOPDisabledPref();
browserFrameHelpers.origPageThumbsEnabledPref = browserFrameHelpers.getPageThumbsEnabledPref();
// Set OOPDisabledPref to true, because none of these tests pass with OOP
// browser frames, at the moment.
browserFrameHelpers.setOOPDisabledPref(true);
// Disable tab view; it seriously messes us up.
browserFrameHelpers.setPageThumbsEnabledPref(false);
// OOP must be disabled on Windows; it doesn't work there. Enable it
// everywhere else.
if (navigator.platform.indexOf('Win') != -1) {
browserFrameHelpers.setOOPDisabledPref(true);
}
else {
browserFrameHelpers.setOOPDisabledPref(false);
}
addEventListener('unload', function() {
browserFrameHelpers.restoreOriginalPrefs();

Просмотреть файл

@ -31,12 +31,11 @@ function runTest() {
// Load emptypage1 into the iframe, wait for that to finish loading, then
// call runTest2.
//
// This should trigger loadstart, load, and loadend events, but not a
// locationchange, because this is the initial load into the iframe.
// This should trigger loadstart, locationchange, and loadend events.
var seenLoad = false;
var seenLoadEnd = false;
var seenLoadStart = false;
var seenLocationChange = false;
var iframe = document.createElement('iframe');
iframe.mozbrowser = true;
@ -45,7 +44,6 @@ function runTest() {
function loadstart(e) {
ok(e.isTrusted, 'Event should be trusted.');
ok(!seenLoad, 'loadstart before load.');
ok(!seenLoadEnd, 'loadstart before loadend.');
ok(!seenLoadStart, 'Just one loadstart event.');
seenLoadStart = true;
@ -53,32 +51,26 @@ function runTest() {
function locationchange(e) {
ok(e.isTrusted, 'Event should be trusted.');
ok(false, 'Unexpected locationchange.');
ok(!seenLocationChange, 'Just one locationchange event.');
seenLocationChange = true;
ok(seenLoadStart, 'Location change after load start.');
ok(!seenLoadEnd, 'Location change before load end.');
ok(e.detail, browserFrameHelpers.emptyPage1, "event's reported location");
}
function loadend(e) {
ok(e.isTrusted, 'Event should be trusted.');
ok(seenLoadStart, 'loadend after loadstart.');
ok(seenLoad, 'loadend after load.');
ok(!seenLoadEnd, 'Just one loadend event.');
seenLoadEnd = true;
}
function load(e) {
ok(e.isTrusted, 'Event should be trusted.');
ok(seenLoadStart, 'load after loadstart.');
ok(!seenLoad, 'Just one load event.');
ok(!seenLoadEnd, 'load before loadend.');
seenLoad = true;
}
iframe.addEventListener('mozbrowserloadstart', loadstart);
iframe.addEventListener('mozbrowserlocationchange', locationchange);
iframe.addEventListener('mozbrowserloadend', loadend);
iframe.addEventListener('load', load);
function waitForAllCallbacks() {
if (!seenLoadStart || !seenLoad || !seenLoadEnd) {
if (!seenLoadStart || !seenLoadEnd) {
SimpleTest.executeSoon(waitForAllCallbacks);
return;
}
@ -86,7 +78,6 @@ function runTest() {
iframe.removeEventListener('mozbrowserloadstart', loadstart);
iframe.removeEventListener('mozbrowserlocationchange', locationchange);
iframe.removeEventListener('mozbrowserloadend', loadend);
iframe.removeEventListener('load', load);
runTest2();
}
@ -96,7 +87,6 @@ function runTest() {
function runTest2() {
var seenLoadStart = false;
var seenLoad = false;
var seenLoadEnd = false;
var seenLocationChange = false;
@ -105,7 +95,6 @@ function runTest2() {
ok(e.isTrusted, 'Event should be trusted.');
ok(!seenLoadStart, 'Just one loadstart event.');
seenLoadStart = true;
ok(!seenLoad, 'Got mozbrowserloadstart event before load.');
ok(!seenLoadEnd, 'Got mozbrowserloadstart before loadend.');
ok(!seenLocationChange, 'Got mozbrowserloadstart before locationchange.');
});
@ -115,20 +104,10 @@ function runTest2() {
ok(!seenLocationChange, 'Just one locationchange event.');
seenLocationChange = true;
ok(seenLoadStart, 'Location change after load start.');
ok(!seenLoad, 'Location change before load.');
ok(!seenLoadEnd, 'Location change before load end.');
ok(e.detail, browserFrameHelpers.emptyPage2, "event's reported location");
});
iframe.addEventListener('load', function(e) {
ok(e.isTrusted, 'Event should be trusted.');
ok(!seenLoad, 'Just one load event.');
seenLoad = true;
ok(seenLoadStart, 'Load after loadstart.');
ok(seenLocationChange, 'Load after locationchange.');
ok(!seenLoadEnd, 'Load before loadend.');
});
iframe.addEventListener('mozbrowserloadend', function(e) {
ok(e.isTrusted, 'Event should be trusted.');
ok(!seenLoadEnd, 'Just one load end event.');
@ -140,7 +119,7 @@ function runTest2() {
iframe.src = browserFrameHelpers.emptyPage2;
function waitForAllCallbacks() {
if (!seenLoadStart || !seenLoad || !seenLoadEnd || !seenLocationChange) {
if (!seenLoadStart || !seenLoadEnd || !seenLocationChange) {
SimpleTest.executeSoon(waitForAllCallbacks);
return;
}

Просмотреть файл

@ -27,8 +27,9 @@ function runTest() {
var iframe1 = document.createElement('iframe');
iframe1.mozbrowser = true;
iframe1.id = 'iframe1';
iframe1.addEventListener('load', function() {
iframe1.removeEventListener('load', arguments.callee);
iframe1.addEventListener('mozbrowserloadend', function() {
iframe1.removeEventListener('mozbrowserloadend', arguments.callee);
ok(true, 'Got first loadend event.');
SimpleTest.executeSoon(runTest2);
});
iframe1.src = browserFrameHelpers.emptyPage1;
@ -39,25 +40,25 @@ function runTest2() {
var iframe1 = document.getElementById('iframe1');
var iframe2 = document.getElementById('iframe2');
var sawLoad = false;
var sawLoadEnd = false;
var sawLocationChange = false;
iframe1.addEventListener('mozbrowserlocationchange', function(e) {
ok(e.isTrusted, 'Event should be trusted.');
ok(!sawLocationChange, 'Just one locationchange event.');
ok(!sawLoad, 'locationchange before load.');
ok(!sawLoadEnd, 'locationchange before load.');
is(e.detail, 'data:text/html,1', "event's reported location");
sawLocationChange = true;
});
iframe1.addEventListener('load', function() {
ok(sawLocationChange, 'Load after locationchange.');
ok(!sawLoad, 'Just one load event.');
sawLoad = true;
iframe1.addEventListener('mozbrowserloadend', function() {
ok(sawLocationChange, 'Loadend after locationchange.');
ok(!sawLoadEnd, 'Just one loadend event.');
sawLoadEnd = true;
});
function iframe2Load() {
if (!sawLoad || !sawLocationChange) {
if (!sawLoadEnd || !sawLocationChange) {
// Spin if iframe1 hasn't loaded yet.
SimpleTest.executeSoon(iframe2Load);
return;

Просмотреть файл

@ -44,12 +44,20 @@ function runTest() {
var numTitleChanges = 0;
iframe1.addEventListener('mozbrowsertitlechange', function(e) {
// Ignore empty titles; these come from about:blank.
if (e.detail == '')
return;
numTitleChanges++;
if (numTitleChanges == 1) {
is(e.detail, 'Title');
iframe1.contentDocument.title = 'New title';
iframe2.contentDocument.title = 'BAD TITLE 2';
SpecialPowers.getBrowserFrameMessageManager(iframe1)
.loadFrameScript("data:,content.document.title='New title';",
/* allowDelayedLoad = */ false);
SpecialPowers.getBrowserFrameMessageManager(iframe2)
.loadFrameScript("data:,content.document.title='BAD TITLE 2';",
/* allowDelayedLoad = */ false);
}
else if (numTitleChanges == 2) {
is(e.detail, 'New title');

Просмотреть файл

@ -14,9 +14,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=725796
<!--
Test that an <iframe mozbrowser> is a window.{top,parent,frameElement} barrier.
If <iframe mozbrowser> is changed to run in a separate process, this test
will not work.
-->
<script type="application/javascript;version=1.7">
@ -25,30 +22,79 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=725796
browserFrameHelpers.setEnabledPref(true);
browserFrameHelpers.addToWhitelist();
var iframe = document.createElement('iframe');
iframe.addEventListener('load', function() {
outerIframeLoaded();
});
iframe.mozbrowser = true;
iframe.src = 'data:text/html,Outer iframe';
document.body.appendChild(iframe);
// This test works only with OOP browser frames. If browserFramesHelpers
// didn't decide to enable OOP browser frames, just skip this test.
if (browserFrameHelpers.getOOPDisabledPref()) {
ok(true, "Skipping test because OOP browser frames are disabled.");
}
else {
runTest();
}
SimpleTest.waitForExplicitFinish();
var iframe;
function runTest() {
iframe = document.createElement('iframe');
iframe.addEventListener('mozbrowserloadend', function() {
try {
outerIframeLoaded();
} catch(e) {
dump("Got error: " + e + '\n');
}
});
iframe.mozbrowser = true;
iframe.src = 'data:text/html,Outer iframe <iframe id="inner-iframe"></iframe>';
// For kicks, this test uses a display:none iframe. This shouldn't make a
// difference in anything.
iframe.style.display = 'none';
document.body.appendChild(iframe);
SimpleTest.waitForExplicitFinish();
}
var numMsgReceived = 0;
function outerIframeLoaded() {
var innerIframe = iframe.contentDocument.createElement('iframe');
iframe.contentDocument.body.appendChild(innerIframe);
var injectedScript =
"data:,function is(a, b, desc) { \
if (a == b) { \
sendAsyncMessage('test:test-pass', desc); \
} else { \
sendAsyncMessage('test:test-fail', desc + ' ' + a + ' != ' + b); \
} \
} \
is(content.window.top, content.window, 'top'); \
is(content.window.parent, content.window, 'parent'); \
is(content.window.frameElement, null, 'frameElement'); \
var innerIframe = content.document.getElementById('inner-iframe'); \
var innerWindow = innerIframe.contentWindow; \
is(innerWindow.top, content.window, 'inner top'); \
is(innerWindow.parent, content.window, 'inner parent'); \
is(innerWindow.frameElement, innerIframe, 'inner frameElement');"
var iframeCw = iframe.contentWindow;
var innerCw = innerIframe.contentWindow;
var mm = SpecialPowers.getBrowserFrameMessageManager(iframe);
is(iframeCw.top, iframeCw, 'iframe top');
is(iframeCw.parent, iframeCw, 'iframe parent');
is(iframeCw.frameElement, null, 'iframe frameElement');
function onRecvTestPass(msg) {
numMsgReceived++;
ok(true, msg.json);
}
mm.addMessageListener('test:test-pass', onRecvTestPass);
is(innerCw.top, iframeCw, 'inner iframe top');
is(innerCw.parent, iframeCw, 'inner iframe parent');
is(innerCw.frameElement, innerIframe, 'inner iframe frameElement');
function onRecvTestFail(msg) {
numMsgReceived++;
ok(false, msg.json);
}
mm.addMessageListener('test:test-fail', onRecvTestFail);
mm.loadFrameScript(injectedScript, /* allowDelayedLoad = */ false);
waitForMessages(6);
}
function waitForMessages(num) {
if (numMsgReceived < num) {
SimpleTest.executeSoon(function() { waitForMessages(num); });
return;
}
SimpleTest.finish();
}

Просмотреть файл

@ -1,62 +0,0 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=742448
-->
<head>
<title>Test for Bug 742448</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="browserFrameHelpers.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=742448">Mozilla Bug 742448</a>
<!--
Test that <iframe mozbrowser>'s window.{top,parent,frameElement} methods are
not confused if we override window.top ourselves.
-->
<script type="application/javascript;version=1.7">
"use strict";
browserFrameHelpers.setEnabledPref(true);
browserFrameHelpers.addToWhitelist();
var iframe = document.createElement('iframe');
iframe.addEventListener('load', function() {
outerIframeLoaded();
});
iframe.mozbrowser = true;
iframe.src = 'data:text/html,Outer iframe';
document.body.appendChild(iframe);
SimpleTest.waitForExplicitFinish();
function outerIframeLoaded() {
var innerIframe = iframe.contentDocument.createElement('iframe');
iframe.contentDocument.body.appendChild(innerIframe);
var iframeCw = iframe.contentWindow;
var innerCw = innerIframe.contentWindow;
// Override window.top in the parent iframe. This shouldn't confuse the
// inner one.
Object.defineProperty(iframe.contentWindow, 'top', {
get: function() { return 42; }
});
is(iframeCw.top, 42, 'iframe top');
is(iframeCw.parent, iframeCw, 'iframe parent');
is(iframeCw.frameElement, null, 'iframe frameElement');
is(innerCw.top, iframeCw, 'inner iframe top');
is(innerCw.parent, iframeCw, 'inner iframe parent');
is(innerCw.frameElement, innerIframe, 'inner iframe frameElement');
SimpleTest.finish();
}
</script>
</body>
</html>

Просмотреть файл

@ -45,8 +45,8 @@ include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/rules.mk
_TEST_FILES = \
test_dom_fullscreen_warning.xul \
dom_fullscreen_warning.xul \
test_MozEnteredDomFullscreen_event.xul \
MozEnteredDomFullscreen_chrome.xul \
test_fullscreen.xul \
fullscreen.xul \
test_fullscreen_preventdefault.xul \

Просмотреть файл

@ -0,0 +1,83 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
<!--
Test that "MozEnteredFullscreen" is dispatched to chrome on documents that enter fullscreen.
Test Description:
This chrome window has a browser. The browser's contentDocument (the "outer document")
in turn has an iframe (the "inner document").
We request fullscreen in the outer document, and check that MozEnteredDomFullscreen is
dispatched to chrome, targeted at the outer document.
Then we request fullscreen in the inner document, and check that MozEnteredDomFullscreen
is dispatched to chrome, targeted at the inner document.
Then we cancel fullscreen in the inner document, and check that MozEnteredDomFullscreen is
dispatched again to chrome, targeted at the outer document. This still happens, since the
outer document's domain was never approved for fullscreen.
-->
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" onload="start();">
<script type="application/javascript" src="chrome://mochikit/content/chrome-harness.js"></script>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"><![CDATA[
function ok(condition, msg) {
window.opener.wrappedJSObject.ok(condition, msg);
}
function is(a, b, msg) {
window.opener.wrappedJSObject.is(a, b, msg);
}
var gBrowser = null;
var gOuterDoc = null;
var gInnerDoc = null;
function firstEntry(event) {
is(event.target, gOuterDoc, "First MozEnteredDomFullscreen should be targeted at outer doc");
window.removeEventListener("MozEnteredDomFullscreen", firstEntry, false);
ok(gOuterDoc.mozFullScreenElement != null, "Outer doc should be in fullscreen");
gInnerDoc = gOuterDoc.getElementById("innerFrame").contentDocument;
window.addEventListener("MozEnteredDomFullscreen", secondEntry, false);
gInnerDoc.defaultView.focus();
gInnerDoc.body.mozRequestFullScreen();
}
function secondEntry(event) {
is(event.target, gInnerDoc, "Second MozEnteredDomFullscreen should be targeted at inner doc");
ok(gInnerDoc.mozFullScreenElement != null, "Inner doc should be in fullscreen");
window.removeEventListener("MozEnteredDomFullscreen", secondEntry, false);
window.addEventListener("MozEnteredDomFullscreen", thirdEntry, false);
gInnerDoc.mozCancelFullScreen();
}
function thirdEntry(event) {
is(event.target, gOuterDoc, "Third MozEnteredDomFullscreen should be targeted at outer doc");
ok(gOuterDoc.mozFullScreenElement != null, "Outer doc return to fullscreen after cancel fullscreen in inner doc");
window.removeEventListener("MozEnteredDomFullscreen", thirdEntry, false);
gOuterDoc.mozCancelFullScreen();
window.opener.wrappedJSObject.done();
}
function start() {
SimpleTest.waitForFocus(
function() {
gBrowser = document.getElementById("browser");
gOuterDoc = gBrowser.contentDocument;
gBrowser.contentWindow.focus();
window.addEventListener("MozEnteredDomFullscreen", firstEntry, false);
gOuterDoc.body.mozRequestFullScreen();
});
}
]]>
</script>
<!-- chrome://mochitests/content/chrome/dom/tests/mochitest/chrome/test_MozEnteredDomFullscreen_event.xul -->
<browser type="content" id="browser" width="400" height="400" src="http://mochi.test:8888/tests/dom/tests/mochitest/general/file_MozEnteredDomFullscreen.html"/>
</window>

Просмотреть файл

@ -1,263 +0,0 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
<!--
Test that "MozShowFullScreenWarning" is dispatched to chrome on restricted keypress.
-->
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" onload="start();">
<script type="application/javascript" src="chrome://mochikit/content/chrome-harness.js"></script>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"><![CDATA[
// List of key codes, and whether they should cause a warning in full-screen mode.
var keyList = [
// Allowed: DOM_VK_CANCEL to DOM_VK_CAPS_LOCK, inclusive
{ code: "VK_CANCEL", warn: true},
{ code: "VK_HELP", warn: true},
{ code: "VK_BACK_SPACE", warn: true},
{ code: "VK_TAB", warn: false},
{ code: "VK_CLEAR", warn: true},
{ code: "VK_RETURN", warn: true},
{ code: "VK_ENTER", warn: true},
{ code: "VK_SHIFT", warn: false},
{ code: "VK_CONTROL", warn: false},
{ code: "VK_ALT", warn: false},
{ code: "VK_PAUSE", warn: true},
{ code: "VK_CAPS_LOCK", warn: true},
{ code: "VK_KANA", warn: true},
{ code: "VK_HANGUL", warn: true},
{ code: "VK_JUNJA", warn: true},
{ code: "VK_FINAL", warn: true},
{ code: "VK_HANJA", warn: true},
{ code: "VK_KANJI", warn: true},
{ code: "VK_ESCAPE", warn: false, exit: true},
{ code: "VK_CONVERT", warn: true},
{ code: "VK_NONCONVERT", warn: true},
{ code: "VK_ACCEPT", warn: true},
{ code: "VK_MODECHANGE", warn: true},
{ code: "VK_SPACE", warn: false},
{ code: "VK_PAGE_UP", warn: false},
{ code: "VK_PAGE_DOWN", warn: false},
{ code: "VK_END", warn: false},
{ code: "VK_HOME", warn: false},
{ code: "VK_LEFT", warn: false},
{ code: "VK_UP", warn: false},
{ code: "VK_RIGHT", warn: false},
{ code: "VK_DOWN", warn: false},
{ code: "VK_SELECT", warn: true},
{ code: "VK_PRINT", warn: true},
{ code: "VK_EXECUTE", warn: true},
{ code: "VK_PRINTSCREEN", warn: true},
{ code: "VK_INSERT", warn: true},
{ code: "VK_DELETE", warn: true},
{ code: "VK_0", warn: true},
{ code: "VK_1", warn: true},
{ code: "VK_2", warn: true},
{ code: "VK_3", warn: true},
{ code: "VK_4", warn: true},
{ code: "VK_5", warn: true},
{ code: "VK_6", warn: true},
{ code: "VK_7", warn: true},
{ code: "VK_8", warn: true},
{ code: "VK_9", warn: true},
{ code: "VK_SEMICOLON", warn: true},
{ code: "VK_EQUALS", warn: true},
{ code: "VK_A", warn: true},
{ code: "VK_B", warn: true},
{ code: "VK_C", warn: true},
{ code: "VK_D", warn: true},
{ code: "VK_E", warn: true},
{ code: "VK_F", warn: true},
{ code: "VK_G", warn: true},
{ code: "VK_H", warn: true},
{ code: "VK_I", warn: true},
{ code: "VK_J", warn: true},
{ code: "VK_K", warn: true},
{ code: "VK_L", warn: true},
{ code: "VK_M", warn: true},
{ code: "VK_N", warn: true},
{ code: "VK_O", warn: true},
{ code: "VK_P", warn: true},
{ code: "VK_Q", warn: true},
{ code: "VK_R", warn: true},
{ code: "VK_S", warn: true},
{ code: "VK_T", warn: true},
{ code: "VK_U", warn: true},
{ code: "VK_V", warn: true},
{ code: "VK_W", warn: true},
{ code: "VK_X", warn: true},
{ code: "VK_Y", warn: true},
{ code: "VK_Z", warn: true},
{ code: "VK_CONTEXT_MENU", warn: true},
{ code: "VK_SLEEP", warn: true},
{ code: "VK_NUMPAD0", warn: true},
{ code: "VK_NUMPAD1", warn: true},
{ code: "VK_NUMPAD2", warn: true},
{ code: "VK_NUMPAD3", warn: true},
{ code: "VK_NUMPAD4", warn: true},
{ code: "VK_NUMPAD5", warn: true},
{ code: "VK_NUMPAD6", warn: true},
{ code: "VK_NUMPAD7", warn: true},
{ code: "VK_NUMPAD8", warn: true},
{ code: "VK_NUMPAD9", warn: true},
{ code: "VK_MULTIPLY", warn: true},
{ code: "VK_ADD", warn: true},
{ code: "VK_SEPARATOR", warn: true},
{ code: "VK_SUBTRACT", warn: true},
{ code: "VK_DECIMAL", warn: true},
{ code: "VK_DIVIDE", warn: true},
{ code: "VK_F1", warn: true},
{ code: "VK_F2", warn: true},
{ code: "VK_F3", warn: true},
{ code: "VK_F4", warn: true},
{ code: "VK_F5", warn: true},
{ code: "VK_F6", warn: true},
{ code: "VK_F7", warn: true},
{ code: "VK_F8", warn: true},
{ code: "VK_F9", warn: true},
{ code: "VK_F10", warn: true},
{ code: "VK_F11", warn: true}, // F11 exit full-screen handler is in browser.js, so won't cause exit here.
{ code: "VK_F12", warn: true},
{ code: "VK_F13", warn: true},
{ code: "VK_F14", warn: true},
{ code: "VK_F15", warn: true},
{ code: "VK_F16", warn: true},
{ code: "VK_F17", warn: true},
{ code: "VK_F18", warn: true},
{ code: "VK_F19", warn: true},
{ code: "VK_F20", warn: true},
{ code: "VK_F21", warn: true},
{ code: "VK_F22", warn: true},
{ code: "VK_F23", warn: true},
{ code: "VK_F24", warn: true},
{ code: "VK_NUM_LOCK", warn: true},
{ code: "VK_SCROLL_LOCK", warn: true},
{ code: "VK_COMMA", warn: true},
{ code: "VK_PERIOD", warn: true},
{ code: "VK_SLASH", warn: true},
{ code: "VK_BACK_QUOTE", warn: true},
{ code: "VK_OPEN_BRACKET", warn: true},
{ code: "VK_BACK_SLASH", warn: true},
{ code: "VK_CLOSE_BRACKET", warn: true},
{ code: "VK_QUOTE", warn: true},
{ code: "VK_META", warn: false},
];
function ok(condition, msg) {
window.opener.wrappedJSObject.ok(condition, msg);
}
function is(a, b, msg) {
window.opener.wrappedJSObject.is(a, b, msg);
}
var gKeyTestIndex = 0;
var gKeyName;
var gKeyCode;
var gWarningEventReceived = false;
var gExpectWarning;
var gExpectExit;
var gBrowser;
function checkKeyEffect() {
is(gBrowser.contentDocument.mozFullScreen, !gExpectExit,
(gExpectExit ? ("Should exit full-screen for " + gKeyName + " press ")
: ("Should remain in full-screen for " + gKeyName + " press")));
is(gWarningEventReceived, gExpectWarning, "Should " + (gExpectWarning ? "" : "not ") +
"receive MozShowFullScreenWarning for " + gKeyName + " press");
if (gKeyTestIndex < keyList.length) {
setTimeout(startNextTest, 0);
} else {
gBrowser.contentDocument.mozCancelFullScreen();
window.opener.wrappedJSObject.done();
}
}
function testTrustedKeyEvents() {
gBrowser.contentWindow.focus();
gWarningEventReceived = false;
synthesizeKey(gKeyName, {});
setTimeout(checkKeyEffect, 0);
}
function testScriptInitiatedKeyEvents() {
// Script initiated untrusted key events should not cause the warning to show.
gBrowser.contentWindow.focus();
gWarningEventReceived = false;
var evt = gBrowser.contentDocument.createEvent("KeyEvents");
evt.initKeyEvent("keydown", true, true, window,
false, false, false, false,
gKeyCode, 0);
gBrowser.contentDocument.body.dispatchEvent(evt);
evt = gBrowser.contentDocument.createEvent("KeyEvents");
evt.initKeyEvent("keypress", true, true, window,
false, false, false, false,
gKeyCode, 0);
gBrowser.contentDocument.body.dispatchEvent(evt);
evt = gBrowser.contentDocument.createEvent("KeyEvents");
evt.initKeyEvent("keyup", true, true, window,
false, false, false, false,
gKeyCode, 0);
gBrowser.contentDocument.body.dispatchEvent(evt);
setTimeout(checkScriptInitiatedEvents, 0);
}
function checkScriptInitiatedEvents() {
is(gWarningEventReceived, false, "Should not receive MozShowFullScreenWarning on synthesized key events.");
ok(gBrowser.contentDocument.mozFullScreen,
"Should remain in full-screen mode for script initiated key events for " + gKeyName);
testTrustedKeyEvents();
}
function testNextKey() {
ok(gBrowser.contentDocument.mozFullScreen, "Must be in full-screen mode");
gKeyName = keyList[gKeyTestIndex].code;
gKeyCode = KeyEvent["DOM_" + gKeyName];
gExpectWarning = keyList[gKeyTestIndex].warn;
gExpectExit = (keyList[gKeyTestIndex].exit != undefined) ?
keyList[gKeyTestIndex].exit : false;
gKeyTestIndex++;
testScriptInitiatedKeyEvents();
}
function startNextTest() {
if (!gBrowser.contentDocument.mozFullScreen) {
gBrowser.contentDocument.body.mozRequestFullScreen();
}
// mozRequestFullScreen is async...
setTimeout(testNextKey, 0);
}
function keyHandler(event) {
event.preventDefault();
}
window.addEventListener("MozShowFullScreenWarning", function(){ gWarningEventReceived = true; }, true);
window.addEventListener("keydown", keyHandler, true);
window.addEventListener("keyup", keyHandler, true);
window.addEventListener("keypress", keyHandler, true);
function start() {
SimpleTest.waitForFocus(
function() {
gBrowser = document.getElementById("browser");
gBrowser.contentWindow.focus();
gBrowser.contentDocument.body.mozRequestFullScreen();
setTimeout(startNextTest, 0);
});
}
]]>
</script>
<browser type="content" id="browser" width="400" height="400"/>
</window>

Просмотреть файл

@ -18,8 +18,21 @@ SpecialPowers.setBoolPref("full-screen-api.enabled", true);
var gPrevTrusted = SpecialPowers.getBoolPref("full-screen-api.allow-trusted-requests-only");
SpecialPowers.setBoolPref("full-screen-api.allow-trusted-requests-only", false);
const Cc = Components.classes;
const Ci = Components.interfaces;
newwindow = window.open("dom_fullscreen_warning.xul", "_blank","chrome,resizable=yes,width=400,height=400");
function make_uri(url) {
var ios = Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService);
return ios.newURI(url, null, null);
}
// Ensure "fullscreen" permissions are not present on the test URI.
var pm = Cc["@mozilla.org/permissionmanager;1"].getService(Ci.nsIPermissionManager);
var uri = make_uri("http://mochi.test:8888");
pm.remove(uri.host, "fullscreen");
newwindow = window.open("MozEnteredDomFullscreen_chrome.xul", "_blank","chrome,resizable=yes,width=400,height=400");
function done()
{

Просмотреть файл

@ -45,6 +45,7 @@ include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/rules.mk
_TEST_FILES = \
file_MozEnteredDomFullscreen.html \
test_outerHTML.html \
test_outerHTML.xhtml \
497633.html \

Просмотреть файл

@ -0,0 +1,8 @@
<html>
<head>
</head>
<body style="background-color: blue;">
<p>Outer doc</p>
<iframe id="innerFrame" src="data:text/html,<html><body style='background-color: red;'><p>Inner doc</p></body></html>"></iframe>
</body>
</html>

Просмотреть файл

@ -15,6 +15,7 @@ include $(topsrcdir)/config/rules.mk
_TEST_FILES = \
test_pointerlock-api.html \
pointerlock_utils.js \
file_approval.html \
file_pointerlock-api.html \
file_pointerlockerror.html \
file_escapeKey.html \

Просмотреть файл

@ -0,0 +1,66 @@
<!DOCTYPE HTML>
<html>
<!--https://bugzilla.mozilla.org/show_bug.cgi?id=746885-->
<head>
<title>Bug 746885</title>
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="pointerlock_utils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=746885">
Mozilla Bug 746885
</a>
<div id="div"></div>
<pre id="test">
<script type="text/javascript">
/*
* Test for Bug 746885
* When requesting pointer lock on a domain that doesn't have fullscreen
* permission, the pointer lock request should be delayed until approval
* has been granted.
*/
SimpleTest.waitForExplicitFinish();
// Ensure fullscreen won't be automatically granted for this document's domain.
SpecialPowers.removeFullscreenAllowed(document);
var div = document.getElementById("div");
var isApproved = false;
document.addEventListener("mozpointerlockchange",
function (e) {
is(isApproved, true, "Should only receive mozpointerlockchange when we've been approved for fullscreen.");
document.mozCancelFullScreen();
}, false);
function approveFullscreen() {
isApproved = true;
SpecialPowers.setFullscreenAllowed(document);
}
document.addEventListener("mozfullscreenchange", function(e) {
if (document.mozFullScreenElement === div) {
// First entered fullscreen. Request pointer lock...
div.mozRequestPointerLock();
// ... But only approve fullscreen after a delay, giving the pointer
// lock request time to run if it were going to. Note we need two timeouts
// here to because if we were to fail and the pointer lock request were to
// succeed without approval, we'd need to give it time to run, and time for
// its asynchronously dispatched mozpointerlockchange to run.
setTimeout(function(){ setTimeout(approveFullscreen, 0); }, 0);
} else {
SimpleTest.finish();
}
}, false);
function start() {
div.mozRequestFullScreen();
}
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -19,10 +19,10 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=633602
<script type="application/javascript">
/**
* Pointer Lock tests for bug 633602. These depend on the fullscreen api
* which doesn't work well on all platforms when run in an iframe, even
* when allowing fullscreen on the iframe. To get around this, all tests
* are run in a child window, which can go fullscreen. This method is
* borrowed from content/html/content/test/test_fullscreen-api.html.
* which doesn't work when run in the mochitests' iframe, since the
* mochitests' iframe doesn't have a mozallowfullscreen attribute. To get
* around this, all tests are run in a child window, which can go fullscreen.
* This method is borrowed from content/html/content/test/test_fullscreen-api.html.
**/
SimpleTest.waitForExplicitFinish();
@ -33,10 +33,15 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=633602
// Disable the requirement for trusted contexts only, so the tests are easier to write.
SpecialPowers.setBoolPref("full-screen-api.allow-trusted-requests-only", false);
// Grant "fullscreen" permission on the test domain. This means fullscreen will be
// automatically approved, so pointer lock in the tests will be too.
SpecialPowers.setFullscreenAllowed(document);
// Run the tests which go full-screen in new window, as Mochitests
// normally run in an iframe, which by default will not have the
// mozallowfullscreen attribute set, so full-screen won't work.
var gTestFiles = [
"file_approval.html",
"file_screenClientXYConst.html",
"file_childIframe.html",
"file_doubleLock.html",
@ -63,15 +68,22 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=633602
const isWinXP = navigator.userAgent.indexOf("Windows NT 5.1") != -1;
const isOSXLion = navigator.userAgent.indexOf("Mac OS X 10.7") != -1;
function finish() {
SpecialPowers.clearUserPref("full-screen-api.enabled");
SpecialPowers.clearUserPref("full-screen-api.allow-trusted-requests-only");
SpecialPowers.removeFullscreenAllowed(document)
SimpleTest.finish();
}
function nextTest() {
if (isWinXP) {
todo(false, "Can't reliably run full-screen tests on Windows XP due to bug 704010");
SimpleTest.finish();
finish();
return;
}
if (isOSXLion) {
todo(false, "Can't reliably run full-screen tests on OS X Lion, see bug 744125");
SimpleTest.finish();
finish();
return;
}
if (gTestWindow) {
@ -85,9 +97,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=633602
gTestWindow = window.open(gTestFiles[gTestIndex], "", "width=500,height=500");
gTestIndex++;
} else {
SpecialPowers.clearUserPref("full-screen-api.enabled");
SpecialPowers.clearUserPref("full-screen-api.allow-trusted-requests-only");
SimpleTest.finish();
finish();
}
}

Просмотреть файл

@ -0,0 +1,32 @@
# 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/.
DEPTH = ../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
relativesrcdir = dom/tests/mochitest/webapps
include $(DEPTH)/config/autoconf.mk
DIRS = \
apps \
$(NULL)
include $(topsrcdir)/config/rules.mk
_TEST_FILES = \
test_install_app.xul \
test_list_api.xul \
test_install_errors.xul \
test_cross_domain.xul \
test_install_utf8.xul \
test_install_receipts.xul \
jshelper.js \
apphelper.js \
$(NULL)
libs:: $(_TEST_FILES)
$(INSTALL) $^ $(DEPTH)/_tests/testing/mochitest/chrome/$(relativesrcdir)

Просмотреть файл

@ -0,0 +1,110 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
const MODE_READONLY = 0x01;
const PERMS_FILE = 0644;
var popupNotifications = getPopupNotifications(window.top);
var event_listener_loaded = {};
Components.utils.import("resource://gre/modules/Services.jsm");
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
Components.classes["@mozilla.org/permissionmanager;1"]
.getService(Components.interfaces.nsIPermissionManager)
.add(SpecialPowers.getDocumentURIObject(window.document),
"webapps-manage",
Components.interfaces.nsIPermissionManager.ALLOW_ACTION);
SpecialPowers.setCharPref("dom.mozApps.whitelist", "http://mochi.test:8888");
SpecialPowers.setBoolPref('dom.mozBrowserFramesEnabled', true);
SpecialPowers.setBoolPref('browser.mozApps.installer.dry_run', true);
SpecialPowers.setBoolPref("dom.mozBrowserFramesWhitelist", "http://www.example.com");
var triggered = false;
function iterateMethods(label, root, suppress) {
var arr = [];
for (var f in root) {
if (suppress && suppress.indexOf(f) != -1)
continue;
if (typeof root[f] === 'function')
arr.push(label + f);
}
return arr;
}
function getPopupNotifications(aWindow) {
var Ci = Components.interfaces;
var chromeWin = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShell)
.chromeEventHandler.ownerDocument.defaultView;
return chromeWin.PopupNotifications;
}
function triggerMainCommand(popup) {
var notifications = popup.childNodes;
ok(notifications.length > 0, "at least one notification displayed");
var notification = notifications[0];
debug("triggering command: " + notification.getAttribute("buttonlabel"));
notification.button.doCommand();
}
function mainCommand() {
triggerMainCommand(this);
}
function popup_listener() {
debug("here in popup listener");
popupNotifications.panel.addEventListener("popupshown", mainCommand, false);
}
/**
* Reads text from a file and returns the string.
*
* @param aFile
* The file to read from.
* @return The string of text read from the file.
*/
function readFile(aFile) {
var file = Components.classes["@mozilla.org/file/directory_service;1"].
getService(Components.interfaces.nsIProperties).
get("CurWorkD", Components.interfaces.nsILocalFile);
var fis = Components.classes["@mozilla.org/network/file-input-stream;1"].
createInstance(Components.interfaces.nsIFileInputStream);
var paths = "chrome/dom/tests/mochitest/webapps" + aFile;
var split = paths.split("/");
var sis = Components.classes["@mozilla.org/scriptableinputstream;1"].
createInstance(Components.interfaces.nsIScriptableInputStream);
var utf8Converter = Components.classes["@mozilla.org/intl/utf8converterservice;1"].
getService(Components.interfaces.nsIUTF8ConverterService);
for(var i = 0; i < split.length; ++i) {
file.append(split[i]);
}
fis.init(file, MODE_READONLY, PERMS_FILE, 0);
sis.init(fis);
var text = sis.read(sis.available());
text = utf8Converter.convertURISpecToUTF8 (text, "UTF-8");
sis.close();
debug (text);
return text;
}
function getOrigin(url) {
return Services.io.newURI(url, null, null).prePath;
}
function tearDown() {
debug("in " + arguments.callee.name);
uninstallAll();
popupNotifications.panel.removeEventListener("popupshown", mainCommand, false);
SpecialPowers.clearUserPref('browser.mozApps.installer.dry_run');
}

Просмотреть файл

@ -0,0 +1,34 @@
# 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/.
DEPTH = ../../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
relativesrcdir = dom/tests/mochitest/webapps/apps
include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/rules.mk
_TEST_FILES = \
include.html \
wild_crazy.webapp \
wild_crazy.webapp^headers^ \
super_crazy.webapp \
super_crazy.webapp^headers^ \
missing_required_field.webapp \
missing_required_field.webapp^headers^ \
json_syntax_error.webapp \
json_syntax_error.webapp^headers^ \
no_delegated_install.webapp \
no_delegated_install.webapp^headers^ \
bad_content_type.webapp \
manifest_with_bom.webapp \
manifest_with_bom.webapp^headers^ \
$(NULL)
libs:: $(_TEST_FILES)
$(INSTALL) $^ $(DEPTH)/_tests/testing/mochitest/chrome/$(relativesrcdir)

Просмотреть файл

@ -0,0 +1,5 @@
{
"name": "An app served with a bad header. The .json ext doesn't trigger proper headers in the test harness webserver.",
"default_locale": "en",
"installs_allowed_from": [ "*" ]
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше