--HG--
rename : mobile/android/base/resources/drawable-mdpi/crash_reporter.png => mobile/android/base/crashreporter/res/drawable-mdpi/crash_reporter.png
rename : mobile/android/base/resources/layout/crash_reporter.xml => mobile/android/base/crashreporter/res/layout/crash_reporter.xml
rename : mobile/android/branding/aurora/content/fennec_72x72.png => mobile/android/branding/aurora/res/drawable-hdpi/icon.png
rename : mobile/android/branding/aurora/content/fennec_48x48.png => mobile/android/branding/aurora/res/drawable-mdpi/icon.png
rename : mobile/android/branding/aurora/content/fennec_96x96.png => mobile/android/branding/aurora/res/drawable-xhdpi/icon.png
rename : mobile/android/branding/aurora/content/fennec_144x144.png => mobile/android/branding/aurora/res/drawable-xxhdpi/icon.png
rename : mobile/android/branding/beta/content/fennec_72x72.png => mobile/android/branding/beta/res/drawable-hdpi/icon.png
rename : mobile/android/branding/beta/content/fennec_48x48.png => mobile/android/branding/beta/res/drawable-mdpi/icon.png
rename : mobile/android/branding/beta/content/fennec_96x96.png => mobile/android/branding/beta/res/drawable-xhdpi/icon.png
rename : mobile/android/branding/beta/content/fennec_144x144.png => mobile/android/branding/beta/res/drawable-xxhdpi/icon.png
rename : mobile/android/branding/nightly/content/fennec_72x72.png => mobile/android/branding/nightly/res/drawable-hdpi/icon.png
rename : mobile/android/branding/nightly/content/fennec_48x48.png => mobile/android/branding/nightly/res/drawable-mdpi/icon.png
rename : mobile/android/branding/nightly/content/fennec_96x96.png => mobile/android/branding/nightly/res/drawable-xhdpi/icon.png
rename : mobile/android/branding/nightly/content/fennec_144x144.png => mobile/android/branding/nightly/res/drawable-xxhdpi/icon.png
rename : mobile/android/branding/official/content/fennec_72x72.png => mobile/android/branding/official/res/drawable-hdpi/icon.png
rename : mobile/android/branding/official/content/fennec_48x48.png => mobile/android/branding/official/res/drawable-mdpi/icon.png
rename : mobile/android/branding/official/content/fennec_96x96.png => mobile/android/branding/official/res/drawable-xhdpi/icon.png
rename : mobile/android/branding/official/content/fennec_144x144.png => mobile/android/branding/official/res/drawable-xxhdpi/icon.png
rename : mobile/android/branding/unofficial/content/fennec_72x72.png => mobile/android/branding/unofficial/res/drawable-hdpi/icon.png
rename : mobile/android/branding/unofficial/content/fennec_48x48.png => mobile/android/branding/unofficial/res/drawable-mdpi/icon.png
rename : mobile/android/branding/unofficial/content/fennec_96x96.png => mobile/android/branding/unofficial/res/drawable-xhdpi/icon.png
rename : mobile/android/branding/unofficial/content/fennec_144x144.png => mobile/android/branding/unofficial/res/drawable-xxhdpi/icon.png
This commit is contained in:
Nick Alexander 2013-12-12 08:21:15 -08:00
Родитель 3520f2dfa1 577bf4bd2d
Коммит 03c9e15f08
696 изменённых файлов: 18818 добавлений и 8207 удалений

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

@ -18,4 +18,7 @@
# Modifying this file will now automatically clobber the buildbot machines \o/
#
Bug 946067 required a clobber on Windows because bug 928195
Bug 934646 needs a clobber -- the icon resources previously copied
into $OBJDIR/mobile/android/base/res will conflict with those in
$BRANDING_DIRECTORY/res.

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

@ -14,7 +14,6 @@
#include "States.h"
#include "nsContentList.h"
#include "nsCxPusher.h"
#include "mozilla/dom/HTMLInputElement.h"
#include "nsIAccessibleRelation.h"
#include "nsIDOMNSEditableElement.h"
@ -26,6 +25,7 @@
#include "nsISelectionController.h"
#include "nsIServiceManager.h"
#include "nsITextControlFrame.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/FloatingPoint.h"
#include "mozilla/Preferences.h"
@ -468,8 +468,7 @@ HTMLTextFieldAccessible::GetEditor() const
// nsGenericHTMLElement::GetEditor has a security check.
// Make sure we're not restricted by the permissions of
// whatever script is currently running.
nsCxPusher pusher;
pusher.PushNull();
mozilla::dom::AutoSystemCaller asc;
nsCOMPtr<nsIEditor> editor;
editableElt->GetEditor(getter_AddRefs(editor));

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

@ -87,8 +87,6 @@
"infojobs.net": "\\(Mobile#(Android; Mobile",
// bug 828399, antena3.com
"antena3.com": "\\(Mobile#(Android; Mobile",
// bug 828401, ingdirect.es
"ingdirect.es": "\\(Mobile#(Android; Mobile",
// bug 828403, fotocasa.es
"fotocasa.es": "\\(Mobile#(Android; Mobile",
// bug 828406, orange.es
@ -107,8 +105,6 @@
"movistar.com.ve": "\\(Mobile#(Android; Mobile",
// bug 828445, bumeran.com.ve
"bumeran.com.ve": "\\(Mobile#(Android; Mobile",
// bug 828448, petardas.com
"petardas.com": "\\(Mobile#(Android; Mobile",
// bug 843112, movil.bankinter.es
"movil.bankinter.es": "\\(Mobile#(Android; Mobile",
// bug 843114, einforma.com
@ -139,16 +135,12 @@
"citibank.com": "\\(Mobile#(Android; Mobile",
// bug 843153, games.com
"games.com": "\\(Mobile#(Android; Mobile",
// bug 843156, orbitz.com
"orbitz.com": "\\(Mobile#(Android; Mobile",
// bug 843160, ehow.com
"ehow.com": "\\(Mobile#(Android; Mobile",
// bug 843162, urbanspoon.com
"urbanspoon.com": "\\(Mobile#(Android; Mobile",
// bug 843165, virginatlantic.com
"virginatlantic.com": "\\(Mobile#(Android; Mobile",
// bug 843168, cheaptickets.com
"cheaptickets.com": "\\(Mobile#(Android; Mobile",
// bug 843172, zimbio.com
"zimbio.com": "\\(Mobile#(Android; Mobile",
// bug 843176, tylted.com
@ -171,8 +163,6 @@
"hazipatika.com": "\\(Mobile#(Android; Mobile",
// bug 878234, hvg.hu
"hvg.hu": "\\(Mobile#(Android; Mobile",
// bug 878236, jofogas.hu
"jofogas.hu": "\\(Mobile#(Android; Mobile",
// bug 878238, koponyeg.hu
"koponyeg.hu": "\\(Mobile#(Android; Mobile",
// bug 878240, kuruc.info
@ -205,16 +195,12 @@
"mondo.rs": "\\(Mobile#(Android; Mobile",
// bug 878277, naslovi.net
"naslovi.net": "\\(Mobile#(Android; Mobile",
// bug 878284, softonic.com
"softonic.com": "\\(Mobile#(Android; Mobile",
// bug 878630, ask.com
"ask.com": "\\(Mobile#(Android; Mobile",
// bug 878632, banorte.com
"banorte.com": "\\(Mobile#(Android; Mobile",
// bug 878637, eluniversal.com.mx
"eluniversal.com.mx": "\\(Mobile#(Android; Mobile",
// bug 878640, hootsuite.com
"hootsuite.com": "\\(Mobile#(Android; Mobile",
// bug 878642, mercadolibre.com.mx
"mercadolibre.com.mx": "\\(Mobile#(Android; Mobile",
// bug 878645, olx.com.mx

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

@ -1,4 +1,4 @@
{
"revision": "336e9464c144268a8902bbb2d9026be3ff2b327f",
"revision": "5bfef5faac50d14e055f642a44ed2df8483fb2fe",
"repo_path": "/integration/gaia-central"
}

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

@ -57,7 +57,7 @@ MOZ_PLACES=
MOZ_B2G=1
if test "$OS_TARGET" = "Android"; then
MOZ_NUWA_PROCESS=0
MOZ_NUWA_PROCESS=
fi
MOZ_FOLD_LIBS=1

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

@ -106,11 +106,6 @@ function appUpdater()
this.bundle = Services.strings.
createBundle("chrome://browser/locale/browser.properties");
this.updateBtn = document.getElementById("updateButton");
// The button label value must be set so its height is correct.
this.setupUpdateButton("update.checkInsideButton");
let manualURL = Services.urlFormatter.formatURLPref("app.update.url.manual");
let manualLink = document.getElementById("manualLink");
manualLink.value = manualURL;
@ -123,8 +118,7 @@ function appUpdater()
}
if (this.isPending || this.isApplied) {
this.setupUpdateButton("update.restart." +
(this.isMajor ? "upgradeButton" : "updateButton"));
this.selectPanel("apply");
return;
}
@ -135,15 +129,19 @@ function appUpdater()
if (this.isDownloading) {
this.startDownload();
// selectPanel("downloading") is called from setupDownloadingUI().
return;
}
if (this.updateEnabled && this.updateAuto) {
this.selectPanel("checkingForUpdates");
this.isChecking = true;
this.checker.checkForUpdates(this.updateCheckListener, true);
return;
}
// If app.update.enabled is false, we don't pop up an update dialog
// automatically, but opening the About dialog is considered manually
// checking for updates, so we always check.
// If app.update.auto is false, we ask before downloading though,
// in onCheckComplete.
this.selectPanel("checkingForUpdates");
this.isChecking = true;
this.checker.checkForUpdates(this.updateCheckListener, true);
// after checking, onCheckComplete() is called
}
appUpdater.prototype =
@ -180,13 +178,6 @@ appUpdater.prototype =
this.um.activeUpdate.state == "downloading";
},
// true when the update type is major.
get isMajor() {
if (this.update)
return this.update.type == "major";
return this.um.activeUpdate.type == "major";
},
// true when updating is disabled by an administrator.
get updateDisabledAndLocked() {
return !this.updateEnabled &&
@ -218,36 +209,54 @@ appUpdater.prototype =
},
/**
* Sets the deck's selected panel.
* Sets the panel of the updateDeck.
*
* @param aChildID
* The id of the deck's child to select.
* The id of the deck's child to select, e.g. "apply".
*/
selectPanel: function(aChildID) {
this.updateDeck.selectedPanel = document.getElementById(aChildID);
this.updateBtn.disabled = (aChildID != "updateButtonBox");
let panel = document.getElementById(aChildID);
let button = panel.querySelector("button");
if (button) {
if (aChildID == "downloadAndInstall") {
let updateVersion = gAppUpdater.update.displayVersion;
button.label = this.bundle.formatStringFromName("update.downloadAndInstallButton.label", [updateVersion], 1);
button.accessKey = this.bundle.GetStringFromName("update.downloadAndInstallButton.accesskey");
}
this.updateDeck.selectedPanel = panel;
if (!document.commandDispatcher.focusedElement || // don't steal the focus
document.commandDispatcher.focusedElement.localName == "button") // except from the other buttons
button.focus();
} else {
this.updateDeck.selectedPanel = panel;
}
},
/**
* Sets the update button's label and accesskey.
*
* @param aKeyPrefix
* The prefix for the properties file entry to use for setting the
* label and accesskey.
* Check for addon compat, or start the download right away
*/
setupUpdateButton: function(aKeyPrefix) {
this.updateBtn.label = this.bundle.GetStringFromName(aKeyPrefix + ".label");
this.updateBtn.accessKey = this.bundle.GetStringFromName(aKeyPrefix + ".accesskey");
if (!document.commandDispatcher.focusedElement ||
document.commandDispatcher.focusedElement == this.updateBtn)
this.updateBtn.focus();
doUpdate: function() {
// skip the compatibility check if the update doesn't provide appVersion,
// or the appVersion is unchanged, e.g. nightly update
if (!this.update.appVersion ||
Services.vc.compare(gAppUpdater.update.appVersion,
Services.appinfo.version) == 0) {
this.startDownload();
} else {
this.checkAddonCompatibility();
}
},
/**
* Handles oncommand for the update button.
* Handles oncommand for the "Restart to Update" button
* which is presented after the download has been downloaded.
*/
buttonOnCommand: function() {
if (this.isPending || this.isApplied) {
buttonRestartAfterDownload: function() {
if (!this.isPending && !this.isApplied)
return;
// Notify all windows that an application quit has been requested.
let cancelQuit = Components.classes["@mozilla.org/supports-PRBool;1"].
createInstance(Components.interfaces.nsISupportsPRBool);
@ -268,27 +277,21 @@ appUpdater.prototype =
appStartup.quit(Components.interfaces.nsIAppStartup.eAttemptQuit |
Components.interfaces.nsIAppStartup.eRestart);
return;
}
},
/**
* Handles oncommand for the "Apply Update…" button
* which is presented if we need to show the billboard or license.
*/
buttonApplyBillboard: function() {
const URI_UPDATE_PROMPT_DIALOG = "chrome://mozapps/content/update/updates.xul";
// Firefox no longer displays a license for updates and the licenseURL check
// is just in case a distibution does.
if (this.update && (this.update.billboardURL || this.update.licenseURL ||
this.addons.length != 0)) {
var ary = null;
ary = Components.classes["@mozilla.org/supports-array;1"].
createInstance(Components.interfaces.nsISupportsArray);
ary.AppendElement(this.update);
var openFeatures = "chrome,centerscreen,dialog=no,resizable=no,titlebar,toolbar=no";
Services.ww.openWindow(null, URI_UPDATE_PROMPT_DIALOG, "", openFeatures, ary);
window.close();
return;
}
this.selectPanel("checkingForUpdates");
this.isChecking = true;
this.checker.checkForUpdates(this.updateCheckListener, true);
var ary = null;
ary = Components.classes["@mozilla.org/supports-array;1"].
createInstance(Components.interfaces.nsISupportsArray);
ary.AppendElement(this.update);
var openFeatures = "chrome,centerscreen,dialog=no,resizable=no,titlebar,toolbar=no";
Services.ww.openWindow(null, URI_UPDATE_PROMPT_DIALOG, "", openFeatures, ary);
window.close(); // close the "About" window; updates.xul takes over.
},
/**
@ -326,21 +329,14 @@ appUpdater.prototype =
// Firefox no longer displays a license for updates and the licenseURL
// check is just in case a distibution does.
if (gAppUpdater.update.billboardURL || gAppUpdater.update.licenseURL) {
gAppUpdater.selectPanel("updateButtonBox");
gAppUpdater.setupUpdateButton("update.openUpdateUI." +
(this.isMajor ? "upgradeButton"
: "applyButton"));
gAppUpdater.selectPanel("applyBillboard");
return;
}
if (!gAppUpdater.update.appVersion ||
Services.vc.compare(gAppUpdater.update.appVersion,
Services.appinfo.version) == 0) {
gAppUpdater.startDownload();
return;
}
gAppUpdater.checkAddonCompatibility();
if (gAppUpdater.updateAuto) // automatically download and install
gAppUpdater.doUpdate();
else // ask
gAppUpdater.selectPanel("downloadAndInstall");
},
/**
@ -474,9 +470,7 @@ appUpdater.prototype =
return;
}
this.selectPanel("updateButtonBox");
this.setupUpdateButton("update.openUpdateUI." +
(this.isMajor ? "upgradeButton" : "applyButton"));
this.selectPanel("apply");
},
/**
@ -553,11 +547,9 @@ appUpdater.prototype =
if (status == "applied" || status == "applied-service" ||
status == "pending" || status == "pending-service") {
// If the update is successfully applied, or if the updater has
// fallen back to non-staged updates, show the Restart to Update
// fallen back to non-staged updates, show the "Restart to Update"
// button.
self.selectPanel("updateButtonBox");
self.setupUpdateButton("update.restart." +
(self.isMajor ? "upgradeButton" : "updateButton"));
self.selectPanel("apply");
} else if (status == "failed") {
// Background update has failed, let's show the UI responsible for
// prompting the user to update manually.
@ -572,9 +564,7 @@ appUpdater.prototype =
Services.obs.removeObserver(arguments.callee, "update-staged");
}, "update-staged", false);
} else {
this.selectPanel("updateButtonBox");
this.setupUpdateButton("update.restart." +
(this.isMajor ? "upgradeButton" : "updateButton"));
this.selectPanel("apply");
}
break;
default:
@ -582,7 +572,6 @@ appUpdater.prototype =
this.selectPanel("downloadFailed");
break;
}
},
/**

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

@ -50,17 +50,29 @@
<vbox id="updateBox">
#ifdef MOZ_UPDATER
<deck id="updateDeck" orient="vertical">
<hbox id="updateButtonBox" align="center">
<hbox id="downloadAndInstall" align="center">
<button id="downloadAndInstallButton" align="start"
oncommand="gAppUpdater.doUpdate();"/>
<!-- label and accesskey will be filled by JS -->
<spacer flex="1"/>
</hbox>
<hbox id="apply" align="center">
<button id="updateButton" align="start"
oncommand="gAppUpdater.buttonOnCommand();"/>
label="&update.updateButton.label;"
accesskey="&update.updateButton.accesskey;"
oncommand="gAppUpdater.buttonRestartAfterDownload();"/>
<spacer flex="1"/>
</hbox>
<hbox id="applyBillboard" align="center">
<button id="applyButtonBillboard" align="start"
label="&update.applyButtonBillboard.label;"
accesskey="&update.applyButtonBillboard.accesskey;"
oncommand="gAppUpdater.buttonApplyBillboard();"/>
<spacer flex="1"/>
</hbox>
<hbox id="checkingForUpdates" align="center">
<image class="update-throbber"/><label>&update.checkingForUpdates;</label>
</hbox>
<hbox id="checkingAddonCompat" align="center">
<image class="update-throbber"/><label>&update.checkingAddonCompat;</label>
</hbox>
<hbox id="downloading" align="center">
<image class="update-throbber"/><label>&update.downloading.start;</label><label id="downloadStatus"/><label>&update.downloading.end;</label>
</hbox>

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

@ -457,10 +457,17 @@ let CustomizableUIInternal = {
// If the placements have items in them which are (now) no longer removable,
// we shouldn't be moving them:
if (node.parentNode != container && !this.isWidgetRemovable(node)) {
if (provider == CustomizableUI.PROVIDER_API) {
let widgetInfo = gPalette.get(id);
if (!widgetInfo.removable && aArea != widgetInfo.defaultArea) {
placementsToRemove.add(id);
continue;
}
} else if (provider == CustomizableUI.PROVIDER_XUL &&
node.parentNode != container && !this.isWidgetRemovable(node)) {
placementsToRemove.add(id);
continue;
}
} // Special widgets are always removable, so no need to check them
if (inPrivateWindow && provider == CustomizableUI.PROVIDER_API) {
let widget = gPalette.get(id);
@ -1736,7 +1743,7 @@ let CustomizableUIInternal = {
source: aSource || "addon",
instances: new Map(),
currentArea: null,
removable: false,
removable: true,
overflows: true,
defaultArea: null,
shortcutId: null,
@ -1778,6 +1785,11 @@ let CustomizableUIInternal = {
if (aData.defaultArea && gAreas.has(aData.defaultArea)) {
widget.defaultArea = aData.defaultArea;
} else if (!widget.removable) {
ERROR("Widget '" + widget.id + "' is not removable but does not specify " +
"a valid defaultArea. That's not possible; it must specify a " +
"valid defaultArea as well.");
return null;
}
if ("type" in aData && gSupportedWidgetTypes.has(aData.type)) {
@ -2383,11 +2395,13 @@ this.CustomizableUI = {
* invoked when a user hides your view.
* - tooltiptext: string to use for the tooltip of the widget
* - label: string to use for the label of the widget
* - removable: whether the widget is removable (optional, default: false)
* - removable: whether the widget is removable (optional, default: true)
* NB: if you specify false here, you must provide a
* defaultArea, too.
* - overflows: whether widget can overflow when in an overflowable
* toolbar (optional, default: true)
* - defaultArea: default area to add the widget to
* (optional, default: none)
* (optional, default: none; required if non-removable)
* - shortcutId: id of an element that has a shortcut for this widget
* (optional, default: null). This is only used to display
* the shortcut as part of the tooltip for builtin widgets

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

@ -61,7 +61,6 @@ const CustomizableWidgets = [{
type: "view",
viewId: "PanelUI-history",
shortcutId: "key_gotoHistory",
removable: true,
defaultArea: CustomizableUI.AREA_PANEL,
onViewShowing: function(aEvent) {
// Populate our list of history
@ -148,7 +147,6 @@ const CustomizableWidgets = [{
}
}, {
id: "privatebrowsing-button",
removable: true,
shortcutId: "key_privatebrowsing",
defaultArea: CustomizableUI.AREA_PANEL,
onCommand: function(e) {
@ -161,7 +159,6 @@ const CustomizableWidgets = [{
}
}, {
id: "save-page-button",
removable: true,
shortcutId: "key_savePage",
defaultArea: CustomizableUI.AREA_PANEL,
onCommand: function(aEvent) {
@ -174,7 +171,6 @@ const CustomizableWidgets = [{
}
}, {
id: "find-button",
removable: true,
shortcutId: "key_find",
defaultArea: CustomizableUI.AREA_PANEL,
onCommand: function(aEvent) {
@ -187,7 +183,6 @@ const CustomizableWidgets = [{
}
}, {
id: "open-file-button",
removable: true,
shortcutId: "openFileKb",
defaultArea: CustomizableUI.AREA_PANEL,
onCommand: function(aEvent) {
@ -202,7 +197,6 @@ const CustomizableWidgets = [{
id: "developer-button",
type: "view",
viewId: "PanelUI-developer",
removable: true,
shortcutId: "key_devToolboxMenuItem",
defaultArea: CustomizableUI.AREA_PANEL,
onViewShowing: function(aEvent) {
@ -265,7 +259,6 @@ const CustomizableWidgets = [{
}
}, {
id: "add-ons-button",
removable: true,
shortcutId: "key_openAddons",
defaultArea: CustomizableUI.AREA_PANEL,
onCommand: function(aEvent) {
@ -278,7 +271,6 @@ const CustomizableWidgets = [{
}
}, {
id: "preferences-button",
removable: true,
defaultArea: CustomizableUI.AREA_PANEL,
#ifdef XP_WIN
label: "preferences-button.labelWin",
@ -295,7 +287,6 @@ const CustomizableWidgets = [{
}, {
id: "zoom-controls",
type: "custom",
removable: true,
defaultArea: CustomizableUI.AREA_PANEL,
onBuild: function(aDocument) {
const kPanelId = "PanelUI-popup";
@ -441,7 +432,6 @@ const CustomizableWidgets = [{
}, {
id: "edit-controls",
type: "custom",
removable: true,
defaultArea: CustomizableUI.AREA_PANEL,
onBuild: function(aDocument) {
let inPanel = (this.currentArea == CustomizableUI.AREA_PANEL);
@ -536,7 +526,6 @@ const CustomizableWidgets = [{
id: "feed-button",
type: "view",
viewId: "PanelUI-feeds",
removable: true,
defaultArea: CustomizableUI.AREA_PANEL,
onClick: function(aEvent) {
let win = aEvent.target.ownerDocument.defaultView;
@ -576,7 +565,6 @@ const CustomizableWidgets = [{
id: "characterencoding-button",
type: "view",
viewId: "PanelUI-characterEncodingView",
removable: true,
defaultArea: CustomizableUI.AREA_PANEL,
maybeDisableMenu: function(aDocument) {
let window = aDocument.defaultView;
@ -783,7 +771,6 @@ const CustomizableWidgets = [{
}
}, {
id: "email-link-button",
removable: true,
onCommand: function(aEvent) {
let win = aEvent.view;
win.MailIntegration.sendLinkForWindow(win.content);
@ -801,7 +788,6 @@ if (Services.sysinfo.getProperty("hasWindowsTouchInterface")) {
id: "switch-to-metro-button",
label: "switch-to-metro-button2.label",
tooltiptext: metroTooltip,
removable: true,
defaultArea: CustomizableUI.AREA_PANEL,
showInPrivateBrowsing: false, /* See bug 928068 */
onCommand: function(aEvent) {

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

@ -45,4 +45,5 @@ skip-if = os == "mac"
[browser_942581_unregisterArea_keeps_placements.js]
[browser_943683_migration_test.js]
[browser_944887_destroyWidget_should_destroy_in_palette.js]
[browser_947987_removable_default.js]
[browser_panel_toggle.js]

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

@ -10,16 +10,17 @@ let gTests = [
let navbar = document.getElementById("nav-bar");
ok(CustomizableUI.inDefaultState, "Should start in default state");
CustomizableUI.createWidget({id: kWidgetId, removable: false, label: "Test"});
let button = createDummyXULButton(kWidgetId, "Test non-removable inDefaultState handling");
CustomizableUI.addWidgetToArea(kWidgetId, CustomizableUI.AREA_NAVBAR);
button.setAttribute("removable", "false");
ok(CustomizableUI.inDefaultState, "Should still be in default state after navbar addition");
CustomizableUI.destroyWidget(kWidgetId);
button.remove();
CustomizableUI.createWidget({id: kWidgetId, removable: false, label: "Test"});
button = createDummyXULButton(kWidgetId, "Test non-removable inDefaultState handling");
CustomizableUI.addWidgetToArea(kWidgetId, CustomizableUI.AREA_PANEL);
button.setAttribute("removable", "false");
ok(CustomizableUI.inDefaultState, "Should still be in default state after panel addition");
CustomizableUI.destroyWidget(kWidgetId);
button.remove();
ok(CustomizableUI.inDefaultState, "Should be in default state after destroying both widgets");
},
teardown: null

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

@ -0,0 +1,79 @@
/* 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/. */
let kWidgetId = "test-removable-widget-default";
const kNavBar = CustomizableUI.AREA_NAVBAR;
let widgetCounter = 0;
let gTests = [
{
desc: "Sanity checks",
run: function() {
let brokenSpec = {id: kWidgetId + (widgetCounter++), removable: false};
SimpleTest.doesThrow(function() CustomizableUI.createWidget(brokenSpec),
"Creating non-removable widget without defaultArea should throw.");
// Widget without removable set should be removable:
let wrapper = CustomizableUI.createWidget({id: kWidgetId + (widgetCounter++)});
ok(CustomizableUI.isWidgetRemovable(wrapper.id), "Should be removable by default.");
CustomizableUI.destroyWidget(wrapper.id);
}
},
{
desc: "Test non-removable widget with defaultArea",
run: function() {
// Non-removable widget with defaultArea should work:
let spec = {id: kWidgetId + (widgetCounter++), removable: false,
defaultArea: kNavBar};
let widgetWrapper;
try {
widgetWrapper = CustomizableUI.createWidget(spec);
} catch (ex) {
ok(false, "Creating a non-removable widget with a default area should not throw.");
return;
}
let placement = CustomizableUI.getPlacementOfWidget(spec.id);
ok(placement, "Widget should be placed.");
is(placement.area, kNavBar, "Widget should be in navbar");
let singleWrapper = widgetWrapper.forWindow(window);
ok(singleWrapper, "Widget should exist in window.");
ok(singleWrapper.node, "Widget node should exist in window.");
let expectedParent = CustomizableUI.getCustomizeTargetForArea(kNavBar, window);
is(singleWrapper.node.parentNode, expectedParent, "Widget should be in navbar.");
let otherWin = yield openAndLoadWindow(true);
placement = CustomizableUI.getPlacementOfWidget(spec.id);
ok(placement, "Widget should be placed.");
is(placement && placement.area, kNavBar, "Widget should be in navbar");
singleWrapper = widgetWrapper.forWindow(otherWin);
ok(singleWrapper, "Widget should exist in other window.");
if (singleWrapper) {
ok(singleWrapper.node, "Widget node should exist in other window.");
if (singleWrapper.node) {
let expectedParent = CustomizableUI.getCustomizeTargetForArea(kNavBar, otherWin);
is(singleWrapper.node.parentNode, expectedParent,
"Widget should be in navbar in other window.");
}
}
otherWin.close();
}
},
];
function asyncCleanup() {
yield resetCustomization();
}
function cleanup() {
removeCustomToolbars();
}
function test() {
waitForExplicitFinish();
registerCleanupFunction(cleanup);
runTests(gTests, asyncCleanup);
}

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

@ -170,9 +170,7 @@ function addWindow(windowOptions, callback) {
let win = OpenBrowserWindow(windowOptions);
let onLoad = function() {
win.removeEventListener("load", onLoad, false);
whenDelayedStartupFinished(win, function() {
// Would like to get rid of this executeSoon, but without it the url
// (TEST_URI) provided in addTabWithToolbarRunTests hasn't loaded
executeSoon(function() {
@ -187,9 +185,7 @@ function addWindow(windowOptions, callback) {
deferred.reject(ex);
}
});
};
win.addEventListener("load", onLoad, false);
});
return deferred.promise;
}

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

@ -10,6 +10,15 @@ let testDir = gTestPath.substr(0, gTestPath.lastIndexOf("/"));
Services.scriptloader.loadSubScript(testDir + "/helpers.js", this);
Services.scriptloader.loadSubScript(testDir + "/mockCommands.js", this);
function whenDelayedStartupFinished(aWindow, aCallback) {
Services.obs.addObserver(function observer(aSubject, aTopic) {
if (aWindow == aSubject) {
Services.obs.removeObserver(observer, aTopic);
executeSoon(aCallback);
}
}, "browser-delayed-startup-finished", false);
}
/**
* Force GC on shutdown, because it seems that GCLI can outrun the garbage
* collector in some situations, which causes test failures in later tests

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

@ -31,3 +31,4 @@ support-files =
[browser_toolbar_tooltip.js]
[browser_toolbar_webconsole_errors_count.js]
[browser_spectrum.js]
[browser_csstransformpreview.js]

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

@ -0,0 +1,139 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Tests that the spectrum color picker works correctly
const TEST_URI = "data:text/html;charset=utf-8,<div></div>";
const {CSSTransformPreviewer} = devtools.require("devtools/shared/widgets/CSSTransformPreviewer");
let doc, root;
function test() {
waitForExplicitFinish();
addTab(TEST_URI, () => {
doc = content.document;
root = doc.querySelector("div");
startTests();
});
}
function endTests() {
doc = root = null;
gBrowser.removeCurrentTab();
finish();
}
function startTests() {
testCreateAndDestroyShouldAppendAndRemoveElements();
}
function testCreateAndDestroyShouldAppendAndRemoveElements() {
ok(root, "We have the root node to append the preview to");
is(root.childElementCount, 0, "Root node is empty");
let p = new CSSTransformPreviewer(root);
p.preview("matrix(1, -0.2, 0, 1, 0, 0)");
ok(root.childElementCount > 0, "Preview has appended elements");
ok(root.querySelector("canvas"), "Canvas preview element is here");
p.destroy();
is(root.childElementCount, 0, "Destroying preview removed all nodes");
testCanvasDimensionIsConstrainedByMaxDim();
}
function testCanvasDimensionIsConstrainedByMaxDim() {
let p = new CSSTransformPreviewer(root);
p.MAX_DIM = 500;
p.preview("scale(1)", "center", 1000, 1000);
let canvas = root.querySelector("canvas");
is(canvas.width, 500, "Canvas width is correct");
is(canvas.height, 500, "Canvas height is correct");
p.destroy();
testCallingPreviewSeveralTimesReusesTheSameCanvas();
}
function testCallingPreviewSeveralTimesReusesTheSameCanvas() {
let p = new CSSTransformPreviewer(root);
p.preview("scale(1)", "center", 1000, 1000);
let canvas = root.querySelector("canvas");
p.preview("rotate(90deg)");
let canvases = root.querySelectorAll("canvas");
is(canvases.length, 1, "Still one canvas element");
is(canvases[0], canvas, "Still the same canvas element");
p.destroy();
testCanvasDimensionAreCorrect();
}
function testCanvasDimensionAreCorrect() {
// Only test a few simple transformations
let p = new CSSTransformPreviewer(root);
// Make sure we have a square
let w = 200, h = w;
p.MAX_DIM = w;
// We can't test the content of the canvas here, just that, given a max width
// the aspect ratio of the canvas seems correct.
// Translate a square by its width, should be a rectangle
p.preview("translateX(200px)", "center", w, h);
let canvas = root.querySelector("canvas");
is(canvas.width, w, "width is correct");
is(canvas.height, h/2, "height is half of the width");
// Rotate on the top right corner, should be a rectangle
p.preview("rotate(-90deg)", "top right", w, h);
is(canvas.width, w, "width is correct");
is(canvas.height, h/2, "height is half of the width");
// Rotate on the bottom left corner, should be a rectangle
p.preview("rotate(90deg)", "top right", w, h);
is(canvas.width, w/2, "width is half of the height");
is(canvas.height, h, "height is correct");
// Scale from center, should still be a square
p.preview("scale(2)", "center", w, h);
is(canvas.width, w, "width is correct");
is(canvas.height, h, "height is correct");
// Skew from center, 45deg, should be a rectangle
p.preview("skew(45deg)", "center", w, h);
is(canvas.width, w, "width is correct");
is(canvas.height, h/2, "height is half of the height");
p.destroy();
testPreviewingInvalidTransformReturnsFalse();
}
function testPreviewingInvalidTransformReturnsFalse() {
let p = new CSSTransformPreviewer(root);
ok(!p.preview("veryWow(muchPx) suchTransform(soDeg)"), "Returned false for invalid transform");
ok(!p.preview("rotae(3deg)"), "Returned false for invalid transform");
// Verify the canvas is empty by checking the image data
let canvas = root.querySelector("canvas"), ctx = canvas.getContext("2d");
let data = ctx.getImageData(0, 0, canvas.width, canvas.height).data;
for (let i = 0, n = data.length; i < n; i += 4) {
// Let's not log 250*250*4 asserts! Instead, just log when it fails
let red = data[i];
let green = data[i + 1];
let blue = data[i + 2];
let alpha = data[i + 3];
if (red !== 0 || green !== 0 || blue !== 0 || alpha !== 0) {
ok(false, "Image data is not empty after an invalid transformed was previewed");
break;
}
}
is(p.preview("translateX(30px)"), true, "Returned true for a valid transform");
endTests();
}

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

@ -0,0 +1,389 @@
/* 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";
/**
* The CSSTransformPreview module displays, using a <canvas> a rectangle, with
* a given width and height and its transformed version, given a css transform
* property and origin. It also displays arrows from/to each corner.
*
* It is useful to visualize how a css transform affected an element. It can
* help debug tricky transformations. It is used today in a tooltip, and this
* tooltip is shown when hovering over a css transform declaration in the rule
* and computed view panels.
*
* TODO: For now, it multiplies matrices itself to calculate the coordinates of
* the transformed box, but that should be removed as soon as we can get access
* to getQuads().
*/
const HTML_NS = "http://www.w3.org/1999/xhtml";
/**
* The TransformPreview needs an element to output a canvas tag.
*
* Usage example:
*
* let t = new CSSTransformPreviewer(myRootElement);
* t.preview("rotate(45deg)", "top left", 200, 400);
* t.preview("skew(19deg)", "center", 100, 500);
* t.preview("matrix(1, -0.2, 0, 1, 0, 0)");
* t.destroy();
*
* @param {nsIDOMElement} parentEl
* Where the canvas will go
*/
function CSSTransformPreviewer(parentEl) {
this.parentEl = parentEl;
this.doc = this.parentEl.ownerDocument;
this.canvas = null;
this.ctx = null;
}
module.exports.CSSTransformPreviewer = CSSTransformPreviewer;
CSSTransformPreviewer.prototype = {
/**
* The preview look-and-feel can be changed using these properties
*/
MAX_DIM: 250,
PAD: 5,
ORIGINAL_FILL: "#1F303F",
ORIGINAL_STROKE: "#B2D8FF",
TRANSFORMED_FILL: "rgba(200, 200, 200, .5)",
TRANSFORMED_STROKE: "#B2D8FF",
ARROW_STROKE: "#329AFF",
ORIGIN_STROKE: "#329AFF",
ARROW_TIP_HEIGHT: 10,
ARROW_TIP_WIDTH: 8,
CORNER_SIZE_RATIO: 6,
/**
* Destroy removes the canvas from the parentelement passed in the constructor
*/
destroy: function() {
if (this.canvas) {
this.parentEl.removeChild(this.canvas);
}
if (this._hiddenDiv) {
this.parentEl.removeChild(this._hiddenDiv);
}
this.parentEl = this.canvas = this.ctx = this.doc = null;
},
_createMarkup: function() {
this.canvas = this.doc.createElementNS(HTML_NS, "canvas");
this.canvas.setAttribute("id", "canvas");
this.canvas.setAttribute("width", this.MAX_DIM);
this.canvas.setAttribute("height", this.MAX_DIM);
this.canvas.style.position = "relative";
this.parentEl.appendChild(this.canvas);
this.ctx = this.canvas.getContext("2d");
},
_getComputed: function(name, value, width, height) {
if (!this._hiddenDiv) {
// Create a hidden element to apply the style to
this._hiddenDiv = this.doc.createElementNS(HTML_NS, "div");
this._hiddenDiv.style.visibility = "hidden";
this._hiddenDiv.style.position = "absolute";
this.parentEl.appendChild(this._hiddenDiv);
}
// Camelcase the name
name = name.replace(/-([a-z]{1})/g, (m, letter) => letter.toUpperCase());
// Apply width and height to make sure computation is made correctly
this._hiddenDiv.style.width = width + "px";
this._hiddenDiv.style.height = height + "px";
// Show the hidden div, apply the style, read the computed style, hide the
// hidden div again
this._hiddenDiv.style.display = "block";
this._hiddenDiv.style[name] = value;
let computed = this.doc.defaultView.getComputedStyle(this._hiddenDiv);
let computedValue = computed[name];
this._hiddenDiv.style.display = "none";
return computedValue;
},
_getMatrixFromTransformString: function(transformStr) {
let matrix = transformStr.substring(0, transformStr.length - 1).
substring(transformStr.indexOf("(") + 1).split(",");
matrix.forEach(function(value, index) {
matrix[index] = parseFloat(value, 10);
});
let transformMatrix = null;
if (matrix.length === 6) {
// 2d transform
transformMatrix = [
[matrix[0], matrix[2], matrix[4], 0],
[matrix[1], matrix[3], matrix[5], 0],
[0, 0, 1, 0],
[0, 0, 0, 1]
];
} else {
// 3d transform
transformMatrix = [
[matrix[0], matrix[4], matrix[8], matrix[12]],
[matrix[1], matrix[5], matrix[9], matrix[13]],
[matrix[2], matrix[6], matrix[10], matrix[14]],
[matrix[3], matrix[7], matrix[11], matrix[15]]
];
}
return transformMatrix;
},
_getOriginFromOriginString: function(originStr) {
let offsets = originStr.split(" ");
offsets.forEach(function(item, index) {
offsets[index] = parseInt(item, 10);
});
return offsets;
},
_multiply: function(m1, m2) {
let m = [];
for (let m1Line = 0; m1Line < m1.length; m1Line++) {
m[m1Line] = 0;
for (let m2Col = 0; m2Col < m2.length; m2Col++) {
m[m1Line] += m1[m1Line][m2Col] * m2[m2Col];
}
}
return [m[0], m[1]];
},
_getTransformedPoint: function(matrix, point, origin) {
let pointMatrix = [point[0] - origin[0], point[1] - origin[1], 1, 1];
return this._multiply(matrix, pointMatrix);
},
_getTransformedPoints: function(matrix, rect, origin) {
return rect.map(point => {
let tPoint = this._getTransformedPoint(matrix, [point[0], point[1]], origin);
return [tPoint[0] + origin[0], tPoint[1] + origin[1]];
});
},
/**
* For canvas to avoid anti-aliasing
*/
_round: x => Math.round(x) + .5,
_drawShape: function(points, fillStyle, strokeStyle) {
this.ctx.save();
this.ctx.lineWidth = 1;
this.ctx.strokeStyle = strokeStyle;
this.ctx.fillStyle = fillStyle;
this.ctx.beginPath();
this.ctx.moveTo(this._round(points[0][0]), this._round(points[0][1]));
for (var i = 1; i < points.length; i++) {
this.ctx.lineTo(this._round(points[i][0]), this._round(points[i][1]));
}
this.ctx.lineTo(this._round(points[0][0]), this._round(points[0][1]));
this.ctx.fill();
this.ctx.stroke();
this.ctx.restore();
},
_drawArrow: function(x1, y1, x2, y2) {
// do not draw if the line is too small
if (Math.abs(x2-x1) < 20 && Math.abs(y2-y1) < 20) {
return;
}
this.ctx.save();
this.ctx.strokeStyle = this.ARROW_STROKE;
this.ctx.fillStyle = this.ARROW_STROKE;
this.ctx.lineWidth = 1;
this.ctx.beginPath();
this.ctx.moveTo(this._round(x1), this._round(y1));
this.ctx.lineTo(this._round(x2), this._round(y2));
this.ctx.stroke();
this.ctx.beginPath();
this.ctx.translate(x2, y2);
let radians = Math.atan((y1 - y2) / (x1 - x2));
radians += ((x1 >= x2) ? -90 : 90) * Math.PI / 180;
this.ctx.rotate(radians);
this.ctx.moveTo(0, 0);
this.ctx.lineTo(this.ARROW_TIP_WIDTH / 2, this.ARROW_TIP_HEIGHT);
this.ctx.lineTo(-this.ARROW_TIP_WIDTH / 2, this.ARROW_TIP_HEIGHT);
this.ctx.closePath();
this.ctx.fill();
this.ctx.restore();
},
_drawOrigin: function(x, y) {
this.ctx.save();
this.ctx.strokeStyle = this.ORIGIN_STROKE;
this.ctx.fillStyle = this.ORIGIN_STROKE;
this.ctx.beginPath();
this.ctx.arc(x, y, 4, 0, 2 * Math.PI, false);
this.ctx.stroke();
this.ctx.fill();
this.ctx.restore();
},
/**
* Computes the largest width and height of all the given shapes and changes
* all of the shapes' points (by reference) so they fit into the configured
* MAX_DIM - 2*PAD area.
* @return {Object} A {w, h} giving the size the canvas should be
*/
_fitAllShapes: function(allShapes) {
let allXs = [], allYs = [];
for (let shape of allShapes) {
for (let point of shape) {
allXs.push(point[0]);
allYs.push(point[1]);
}
}
let minX = Math.min.apply(Math, allXs);
let maxX = Math.max.apply(Math, allXs);
let minY = Math.min.apply(Math, allYs);
let maxY = Math.max.apply(Math, allYs);
let spanX = maxX - minX;
let spanY = maxY - minY;
let isWide = spanX > spanY;
let cw = isWide ? this.MAX_DIM :
this.MAX_DIM * Math.min(spanX, spanY) / Math.max(spanX, spanY);
let ch = !isWide ? this.MAX_DIM :
this.MAX_DIM * Math.min(spanX, spanY) / Math.max(spanX, spanY);
let mapX = x => this.PAD + ((cw - 2 * this.PAD) / (maxX - minX)) * (x - minX);
let mapY = y => this.PAD + ((ch - 2 * this.PAD) / (maxY - minY)) * (y - minY);
for (let shape of allShapes) {
for (let point of shape) {
point[0] = mapX(point[0]);
point[1] = mapY(point[1]);
}
}
return {w: cw, h: ch};
},
_drawShapes: function(shape, corner, transformed, transformedCorner) {
this._drawOriginal(shape);
this._drawOriginalCorner(corner);
this._drawTransformed(transformed);
this._drawTransformedCorner(transformedCorner);
},
_drawOriginal: function(points) {
this._drawShape(points, this.ORIGINAL_FILL, this.ORIGINAL_STROKE);
},
_drawTransformed: function(points) {
this._drawShape(points, this.TRANSFORMED_FILL, this.TRANSFORMED_STROKE);
},
_drawOriginalCorner: function(points) {
this._drawShape(points, this.ORIGINAL_STROKE, this.ORIGINAL_STROKE);
},
_drawTransformedCorner: function(points) {
this._drawShape(points, this.TRANSFORMED_STROKE, this.TRANSFORMED_STROKE);
},
_drawArrows: function(shape, transformed) {
this._drawArrow(shape[0][0], shape[0][1], transformed[0][0], transformed[0][1]);
this._drawArrow(shape[1][0], shape[1][1], transformed[1][0], transformed[1][1]);
this._drawArrow(shape[2][0], shape[2][1], transformed[2][0], transformed[2][1]);
this._drawArrow(shape[3][0], shape[3][1], transformed[3][0], transformed[3][1]);
},
/**
* Draw a transform preview
*
* @param {String} transform
* The css transform value as a string, as typed by the user, as long
* as it can be computed by the browser
* @param {String} origin
* Same as above for the transform-origin value. Defaults to "center"
* @param {Number} width
* The width of the container. Defaults to 200
* @param {Number} height
* The height of the container. Defaults to 200
* @return {Boolean} Whether or not the preview could be created. Will return
* false for instance if the transform is invalid
*/
preview: function(transform, origin="center", width=200, height=200) {
// Create/clear the canvas
if (!this.canvas) {
this._createMarkup();
}
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
// Get computed versions of transform and origin
transform = this._getComputed("transform", transform, width, height);
if (transform && transform !== "none") {
origin = this._getComputed("transform-origin", origin, width, height);
// Get the matrix, origin and width height data for the previewed element
let originData = this._getOriginFromOriginString(origin);
let matrixData = this._getMatrixFromTransformString(transform);
// Compute the original box rect and transformed box rect
let shapePoints = [
[0, 0],
[width, 0],
[width, height],
[0, height]
];
let transformedPoints = this._getTransformedPoints(matrixData, shapePoints, originData);
// Do the same for the corner triangle shape
let cornerSize = Math.min(shapePoints[2][1] - shapePoints[1][1],
shapePoints[1][0] - shapePoints[0][0]) / this.CORNER_SIZE_RATIO;
let cornerPoints = [
[shapePoints[1][0], shapePoints[1][1]],
[shapePoints[1][0], shapePoints[1][1] + cornerSize],
[shapePoints[1][0] - cornerSize, shapePoints[1][1]]
];
let transformedCornerPoints = this._getTransformedPoints(matrixData, cornerPoints, originData);
// Resize points to fit everything in the canvas
let {w, h} = this._fitAllShapes([
shapePoints,
transformedPoints,
cornerPoints,
transformedCornerPoints,
[originData]
]);
this.canvas.setAttribute("width", w);
this.canvas.setAttribute("height", h);
this._drawShapes(shapePoints, cornerPoints, transformedPoints, transformedCornerPoints)
this._drawArrows(shapePoints, transformedPoints);
this._drawOrigin(originData[0], originData[1]);
return true;
} else {
return false;
}
}
};

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

@ -12,6 +12,7 @@ const {Spectrum} = require("devtools/shared/widgets/Spectrum");
const EventEmitter = require("devtools/shared/event-emitter");
const {colorUtils} = require("devtools/css-color");
const Heritage = require("sdk/core/heritage");
const {CSSTransformPreviewer} = require("devtools/shared/widgets/CSSTransformPreviewer");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
@ -100,7 +101,6 @@ let PanelFactory = {
panel.setAttribute("hidden", true);
panel.setAttribute("ignorekeys", true);
// Prevent the click used to close the panel from being consumed
panel.setAttribute("consumeoutsideclicks", options.get("consumeOutsideClick"));
panel.setAttribute("noautofocus", options.get("noAutoFocus"));
panel.setAttribute("type", "arrow");
@ -229,6 +229,10 @@ Tooltip.prototype = {
return this.panel.state !== "closed" && this.panel.state !== "hiding";
},
setSize: function(width, height) {
this.panel.sizeTo(width, height);
},
/**
* Empty the tooltip's content
*/
@ -304,7 +308,8 @@ Tooltip.prototype = {
* The container for all target nodes
* @param {Function} targetNodeCb
* A function that accepts a node argument and returns true or false
* to signify if the tooltip should be shown on that node or not.
* (or a promise that resolves or rejects) to signify if the tooltip
* should be shown on that node or not.
* Additionally, the function receives a second argument which is the
* tooltip instance itself, to be used to add/modify the content of the
* tooltip if needed. If omitted, the tooltip will be shown everytime.
@ -312,7 +317,7 @@ Tooltip.prototype = {
* An optional delay that will be observed before showing the tooltip.
* Defaults to this.defaultShowDelay.
*/
startTogglingOnHover: function(baseNode, targetNodeCb, showDelay = this.defaultShowDelay) {
startTogglingOnHover: function(baseNode, targetNodeCb, showDelay=this.defaultShowDelay) {
if (this._basedNode) {
this.stopTogglingOnHover();
}
@ -357,7 +362,12 @@ Tooltip.prototype = {
},
_showOnHover: function(target) {
if (this._targetNodeCb(target, this)) {
let res = this._targetNodeCb(target, this);
if (res && res.then) {
res.then(() => {
this.show(target);
});
} else if (res) {
this.show(target);
}
},
@ -527,6 +537,8 @@ Tooltip.prototype = {
let w = options.naturalWidth || imgObj.naturalWidth;
let h = options.naturalHeight || imgObj.naturalHeight;
label.textContent = w + " x " + h;
this.setSize(vbox.width, vbox.height);
}
},
@ -583,6 +595,54 @@ Tooltip.prototype = {
// Put the iframe in the tooltip
this.content = iframe;
return def.promise;
},
/**
* Set the content of the tooltip to be the result of CSSTransformPreviewer.
* Meaning a canvas previewing a css transformation.
*
* @param {String} transform
* The CSS transform value (e.g. "rotate(45deg) translateX(50px)")
* @param {PageStyleActor} pageStyle
* An instance of the PageStyleActor that will be used to retrieve
* computed styles
* @param {NodeActor} node
* The NodeActor for the currently selected node
* @return A promise that resolves when the tooltip content is ready, or
* rejects if no transform is provided or is invalid
*/
setCssTransformContent: function(transform, pageStyle, node) {
let def = promise.defer();
if (transform) {
// Look into the computed styles to find the width and height and possibly
// the origin if it hadn't been provided
pageStyle.getComputed(node, {
filter: "user",
markMatched: false,
onlyMatched: false
}).then(styles => {
let origin = styles["transform-origin"].value;
let width = parseInt(styles["width"].value);
let height = parseInt(styles["height"].value);
let root = this.doc.createElementNS(XHTML_NS, "div");
let previewer = new CSSTransformPreviewer(root);
this.content = root;
if (!previewer.preview(transform, origin, width, height)) {
// If the preview didn't work, reject the promise
def.reject();
} else {
// Else, make sure the tooltip has the right size and resolve
this.setSize(previewer.canvas.width, previewer.canvas.height);
def.resolve();
}
});
} else {
def.reject();
}
return def.promise;
}
};

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

@ -297,6 +297,8 @@ CssHtmlTree.prototype = {
return promise.resolve(undefined);
}
this.tooltip.hide();
if (aElement === this.viewedElement) {
return promise.resolve(undefined);
}
@ -507,21 +509,27 @@ CssHtmlTree.prototype = {
*/
_buildTooltipContent: function(target)
{
// If the hovered element is not a property view and is not a background
// image, then don't show a tooltip
let isPropertyValue = target.classList.contains("property-value");
if (!isPropertyValue) {
return false;
}
let propName = target.parentNode.querySelector(".property-name");
let isBackgroundImage = propName.textContent === "background-image";
if (!isBackgroundImage) {
return false;
// Test for image url
if (target.classList.contains("theme-link")) {
let propValue = target.parentNode;
let propName = propValue.parentNode.querySelector(".property-name");
if (propName.textContent === "background-image") {
this.tooltip.setCssBackgroundImageContent(propValue.textContent);
return true;
}
}
// Fill some content
this.tooltip.setCssBackgroundImageContent(target.textContent);
return true;
// Test for css transform
if (target.classList.contains("property-value")) {
let def = promise.defer();
let propValue = target;
let propName = target.parentNode.querySelector(".property-name");
if (propName.textContent === "transform") {
this.tooltip.setCssTransformContent(propValue.textContent,
this.pageStyle, this.viewedElement).then(def.resolve);
return def.promise;
}
}
},
/**

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

@ -1154,27 +1154,32 @@ CssRuleView.prototype = {
* prepare some content for the tooltip
*/
_buildTooltipContent: function(target) {
let isImageHref = target.classList.contains("theme-link") &&
target.parentNode.classList.contains("ruleview-propertyvalue");
let property = target.textProperty, def = promise.defer(), hasTooltip = false;
// If the inplace-editor is visible or if this is not a background image
// don't show the tooltip
if (!isImageHref) {
return false;
// Test for css transform
if (property && property.name === "transform") {
this.previewTooltip.setCssTransformContent(property.value, this.pageStyle,
this._viewedElement).then(def.resolve);
hasTooltip = true;
}
// Retrieve the TextProperty for the hovered element
let property = target.parentNode.textProperty;
let href = property.rule.domRule.href;
// Test for image
let isImageHref = target.classList.contains("theme-link") &&
target.parentNode.classList.contains("ruleview-propertyvalue");
if (isImageHref) {
property = target.parentNode.textProperty;
this.previewTooltip.setCssBackgroundImageContent(property.value,
property.rule.domRule.href);
def.resolve();
hasTooltip = true;
}
// Fill some content
this.previewTooltip.setCssBackgroundImageContent(property.value, href);
if (hasTooltip) {
this.colorPicker.revert();
this.colorPicker.hide();
}
// Hide the color picker tooltip if shown and revert changes
this.colorPicker.revert();
this.colorPicker.hide();
return true;
return def.promise;
},
/**
@ -1330,7 +1335,7 @@ CssRuleView.prototype = {
/**
* Update the highlighted element.
*
* @param {nsIDOMElement} aElement
* @param {NodeActor} aElement
* The node whose style rules we'll inspect.
*/
highlight: function CssRuleView_highlight(aElement)
@ -1424,6 +1429,9 @@ CssRuleView.prototype = {
this._clearRules();
this._viewedElement = null;
this._elementStyle = null;
this.previewTooltip.hide();
this.colorPicker.hide();
},
/**

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

@ -53,6 +53,8 @@ support-files = browser_ruleview_pseudoelement.html
[browser_bug913014_matched_expand.js]
[browser_bug765105_background_image_tooltip.js]
[browser_bug889638_rule_view_color_picker.js]
[browser_bug726427_csstransform_tooltip.js]
[browser_bug940500_rule_view_pick_gradient_color.js]
[browser_ruleview_original_source_link.js]
support-files =
@ -61,3 +63,4 @@ support-files =
sourcemaps.css.map
sourcemaps.scss
[browser_computedview_original_source_link.js]
[browser_bug946331_close_tooltip_on_new_selection.js]

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

@ -0,0 +1,206 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
let contentDoc;
let inspector;
let ruleView;
let computedView;
const PAGE_CONTENT = [
'<style type="text/css">',
' #testElement {',
' width: 500px;',
' height: 300px;',
' background: red;',
' transform: skew(16deg);',
' }',
' .test-element {',
' transform-origin: top left;',
' transform: rotate(45deg);',
' }',
' div {',
' transform: scaleX(1.5);',
' transform-origin: bottom right;',
' }',
' [attr] {',
' }',
'</style>',
'<div id="testElement" class="test-element" attr="value">transformed element</div>'
].join("\n");
function test() {
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function(evt) {
gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, true);
contentDoc = content.document;
waitForFocus(createDocument, content);
}, true);
content.location = "data:text/html,rule view css transform tooltip test";
}
function createDocument() {
contentDoc.body.innerHTML = PAGE_CONTENT;
openRuleView((aInspector, aRuleView) => {
inspector = aInspector;
ruleView = aRuleView;
startTests();
});
}
function startTests() {
inspector.selection.setNode(contentDoc.querySelector("#testElement"));
inspector.once("inspector-updated", testTransformTooltipOnIDSelector);
}
function endTests() {
contentDoc = inspector = ruleView = computedView = null;
gBrowser.removeCurrentTab();
finish();
}
function testTransformTooltipOnIDSelector() {
info("Testing that a transform tooltip appears on the #ID rule");
let panel = ruleView.previewTooltip.panel;
ok(panel, "The XUL panel exists for the rule-view preview tooltips");
let {valueSpan} = getRuleViewProperty("#testElement", "transform");
assertTooltipShownOn(ruleView.previewTooltip, valueSpan, () => {
// The transform preview is canvas, so there's not much we can test, so for
// now, let's just be happy with the fact that the tooltips is shown!
ok(true, "Tooltip shown on the transform property of the #ID rule");
ruleView.previewTooltip.hide();
executeSoon(testTransformTooltipOnClassSelector);
});
}
function testTransformTooltipOnClassSelector() {
info("Testing that a transform tooltip appears on the .class rule");
let {valueSpan} = getRuleViewProperty(".test-element", "transform");
assertTooltipShownOn(ruleView.previewTooltip, valueSpan, () => {
// The transform preview is canvas, so there's not much we can test, so for
// now, let's just be happy with the fact that the tooltips is shown!
ok(true, "Tooltip shown on the transform property of the .class rule");
ruleView.previewTooltip.hide();
executeSoon(testTransformTooltipOnTagSelector);
});
}
function testTransformTooltipOnTagSelector() {
info("Testing that a transform tooltip appears on the tag rule");
let {valueSpan} = getRuleViewProperty("div", "transform");
assertTooltipShownOn(ruleView.previewTooltip, valueSpan, () => {
// The transform preview is canvas, so there's not much we can test, so for
// now, let's just be happy with the fact that the tooltips is shown!
ok(true, "Tooltip shown on the transform property of the tag rule");
ruleView.previewTooltip.hide();
executeSoon(testTransformTooltipNotShownOnInvalidTransform);
});
}
function testTransformTooltipNotShownOnInvalidTransform() {
info("Testing that a transform tooltip does not appear for invalid values");
let ruleEditor;
for (let rule of ruleView._elementStyle.rules) {
if (rule.matchedSelectors[0] === "[attr]") {
ruleEditor = rule.editor;
}
}
ruleEditor.addProperty("transform", "muchTransform(suchAngle)", "");
let {valueSpan} = getRuleViewProperty("[attr]", "transform");
assertTooltipNotShownOn(ruleView.previewTooltip, valueSpan, () => {
executeSoon(testTransformTooltipOnComputedView);
});
}
function testTransformTooltipOnComputedView() {
info("Testing that a transform tooltip appears in the computed view too");
inspector.sidebar.select("computedview");
computedView = inspector.sidebar.getWindowForTab("computedview").computedview.view;
let doc = computedView.styleDocument;
let panel = computedView.tooltip.panel;
let {valueSpan} = getComputedViewProperty("transform");
assertTooltipShownOn(computedView.tooltip, valueSpan, () => {
// The transform preview is canvas, so there's not much we can test, so for
// now, let's just be happy with the fact that the tooltips is shown!
ok(true, "Tooltip shown on the computed transform property");
computedView.tooltip.hide();
executeSoon(endTests);
});
}
function assertTooltipShownOn(tooltip, element, cb) {
// If there is indeed a show-on-hover on element, the xul panel will be shown
tooltip.panel.addEventListener("popupshown", function shown() {
tooltip.panel.removeEventListener("popupshown", shown, true);
cb();
}, true);
tooltip._showOnHover(element);
}
function assertTooltipNotShownOn(tooltip, element, cb) {
// The only way to make sure the tooltip is not shown is try and show it, wait
// for a given amount of time, and then check if it's shown or not
tooltip._showOnHover(element);
setTimeout(() => {
ok(!tooltip.isShown(), "The tooltip did not appear on hover of the element");
cb();
}, tooltip.defaultShowDelay + 100);
}
function getRule(selectorText) {
let rule;
[].forEach.call(ruleView.doc.querySelectorAll(".ruleview-rule"), aRule => {
let selector = aRule.querySelector(".ruleview-selector-matched");
if (selector && selector.textContent === selectorText) {
rule = aRule;
}
});
return rule;
}
function getRuleViewProperty(selectorText, propertyName) {
let prop;
let rule = getRule(selectorText);
if (rule) {
// Look for the propertyName in that rule element
[].forEach.call(rule.querySelectorAll(".ruleview-property"), property => {
let nameSpan = property.querySelector(".ruleview-propertyname");
let valueSpan = property.querySelector(".ruleview-propertyvalue");
if (nameSpan.textContent === propertyName) {
prop = {nameSpan: nameSpan, valueSpan: valueSpan};
}
});
}
return prop;
}
function getComputedViewProperty(name) {
let prop;
[].forEach.call(computedView.styleDocument.querySelectorAll(".property-view"), property => {
let nameSpan = property.querySelector(".property-name");
let valueSpan = property.querySelector(".property-value");
if (nameSpan.textContent === name) {
prop = {nameSpan: nameSpan, valueSpan: valueSpan};
}
});
return prop;
}

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

@ -142,8 +142,9 @@ function testComputedView() {
let panel = computedView.tooltip.panel;
let {valueSpan} = getComputedViewProperty("background-image");
let uriSpan = valueSpan.querySelector(".theme-link");
assertTooltipShownOn(computedView.tooltip, valueSpan, () => {
assertTooltipShownOn(computedView.tooltip, uriSpan, () => {
let images = panel.getElementsByTagName("image");
is(images.length, 1, "Tooltip contains an image");
ok(images[0].src === "chrome://global/skin/icons/warning-64.png");

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

@ -0,0 +1,82 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
let contentDoc;
let inspector;
let ruleView;
let computedView;
const PAGE_CONTENT = '<div class="one">el 1</div><div class="two">el 2</div>';
function test() {
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function(evt) {
gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, true);
contentDoc = content.document;
waitForFocus(createDocument, content);
}, true);
content.location = "data:text/html,rule/computed views tooltip hiding test";
}
function createDocument() {
contentDoc.body.innerHTML = PAGE_CONTENT;
openRuleView((aInspector, aRuleView) => {
inspector = aInspector;
ruleView = aRuleView;
inspector.sidebar.once("computedview-ready", () => {
computedView = inspector.sidebar.getWindowForTab("computedview").computedview.view;
startTests();
});
});
}
function startTests() {
inspector.selection.setNode(contentDoc.querySelector(".one"));
inspector.once("inspector-updated", testRuleView);
}
function endTests() {
contentDoc = inspector = ruleView = computedView = null;
gBrowser.removeCurrentTab();
finish();
}
function testRuleView() {
info("Testing rule view tooltip closes on new selection");
// Show the rule view tooltip
let tooltip = ruleView.previewTooltip;
tooltip.show();
tooltip.once("shown", () => {
// Select a new node and assert that the tooltip closes
tooltip.once("hidden", () => {
ok(true, "Rule view tooltip closed after a new node got selected");
inspector.once("inspector-updated", testComputedView);
});
inspector.selection.setNode(contentDoc.querySelector(".two"));
});
}
function testComputedView() {
info("Testing computed view tooltip closes on new selection");
inspector.sidebar.select("computedview");
computedView = inspector.sidebar.getWindowForTab("computedview").computedview.view;
// Show the computed view tooltip
let tooltip = computedView.tooltip;
tooltip.show();
tooltip.once("shown", () => {
// Select a new node and assert that the tooltip closes
tooltip.once("hidden", () => {
ok(true, "Computed view tooltip closed after a new node got selected");
inspector.once("inspector-updated", endTests);
});
inspector.selection.setNode(contentDoc.querySelector(".one"));
});
}

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

@ -3,6 +3,17 @@
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<!ENTITY aboutDialog.title "About &brandFullName;">
<!-- LOCALIZATION NOTE update.applyButton.*, update.upgradeButton.*):
# Only one button is present at a time.
# The button when displayed is located directly under the Firefox version in
# the about dialog (see bug 596813 for screenshots).
-->
<!ENTITY update.updateButton.label "Restart to Update">
<!ENTITY update.updateButton.accesskey "R">
<!ENTITY update.applyButtonBillboard.label "Apply Update…">
<!ENTITY update.applyButtonBillboard.accesskey "A">
<!-- LOCALIZATION NOTE (warningDesc.version): This is a warning about the experimental nature of Nightly and Aurora builds. It is only shown in those versions. -->
<!ENTITY warningDesc.version "&brandShortName; is experimental and may be unstable.">
<!-- LOCALIZATION NOTE (warningDesc.telemetryDesc): This is a notification that Nightly/Aurora builds automatically send Telemetry data back to Mozilla. It is only shown in those versions. "It" refers to brandShortName. -->
@ -41,8 +52,6 @@
<!-- LOCALIZATION NOTE (update.checkingForUpdates): try to make the localized text short (see bug 596813 for screenshots). -->
<!ENTITY update.checkingForUpdates "Checking for updates…">
<!-- LOCALIZATION NOTE (update.checkingAddonCompat): try to make the localized text short (see bug 596813 for screenshots). -->
<!ENTITY update.checkingAddonCompat "Checking Add-on compatibility…">
<!-- LOCALIZATION NOTE (update.noUpdatesFound): try to make the localized text short (see bug 596813 for screenshots). -->
<!ENTITY update.noUpdatesFound "&brandShortName; is up to date">
<!-- LOCALIZATION NOTE (update.adminDisabled): try to make the localized text short (see bug 596813 for screenshots). -->

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

@ -191,24 +191,10 @@ sanitizeEverythingWarning2=All history will be cleared.
# provided that the user has modified the default set of history items to clear.
sanitizeSelectedWarning=All selected items will be cleared.
# Check for Updates in the About Dialog - button labels and accesskeys
# LOCALIZATION NOTE - all of the following update buttons labels will only be
# displayed one at a time. So, if a button is displayed nothing else will
# be displayed alongside of the button. The button when displayed is located
# directly under the Firefox version in the about dialog (see bug 596813 for
# screenshots).
update.checkInsideButton.label=Check for Updates
update.checkInsideButton.accesskey=C
update.resumeButton.label=Resume Downloading %S…
update.resumeButton.accesskey=D
update.openUpdateUI.applyButton.label=Apply Update…
update.openUpdateUI.applyButton.accesskey=A
update.restart.updateButton.label=Restart to Update
update.restart.updateButton.accesskey=R
update.openUpdateUI.upgradeButton.label=Upgrade Now…
update.openUpdateUI.upgradeButton.accesskey=U
update.restart.upgradeButton.label=Upgrade Now
update.restart.upgradeButton.accesskey=U
# LOCALIZATION NOTE (downloadAndInstallButton.label): %S is replaced by the
# version of the update: "Update to 28.0".
update.downloadAndInstallButton.label=Update to %S
update.downloadAndInstallButton.accesskey=U
# RSS Pretty Print
feedShowFeedNew=Subscribe to '%S'…

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

@ -100,4 +100,5 @@
#endif
</hbox>
</html:body>
<observes element="bcast_windowState" attribute="*"/>
</html:html>

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

@ -201,6 +201,8 @@ pref("signon.rememberSignons", true);
pref("layout.spellcheckDefault", 1);
/* extension manager and xpinstall */
// Completely disable extensions
pref("extensions.defaultProviders.enabled", false);
// Disable all add-on locations other than the profile
pref("extensions.enabledScopes", 1);
// Auto-disable any add-ons that are "dropped in" to the profile

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

@ -2,8 +2,6 @@
# 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/.
NO_PROFILE_GUIDED_OPTIMIZE = 1
include $(topsrcdir)/config/config.mk
DIST_PROGRAM = CommandExecuteHandler$(BIN_SUFFIX)

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

@ -16,3 +16,5 @@ DIST_SUBDIR = ''
for var in ('UNICODE', '_UNICODE', 'NS_NO_XPCOM'):
DEFINES[var] = True
NO_PGO = True

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

@ -2,8 +2,6 @@
# 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/.
NO_PROFILE_GUIDED_OPTIMIZE = 1
include $(topsrcdir)/config/config.mk
OS_LIBS = \

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

@ -14,3 +14,5 @@ DIST_SUBDIR = 'metro/install'
for var in ('UNICODE', '_UNICODE'):
DEFINES[var] = True
NO_PGO = True

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

@ -9,8 +9,6 @@ USE_STATIC_LIBS = 1
MOZ_GLUE_LDFLAGS =
MOZ_GLUE_PROGRAM_LDFLAGS =
NO_PROFILE_GUIDED_OPTIMIZE = 1
include $(topsrcdir)/config/config.mk
OS_LIBS = \

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

@ -15,3 +15,5 @@ DIST_SUBDIR = ''
for var in ('UNICODE', '_UNICODE'):
DEFINES[var] = True
NO_PGO = True

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

@ -197,6 +197,12 @@ documenttab[selected] .documenttab-selection {
height: 100%;
}
#startui-page[viewstate="snapped"],
#startui-page[viewstate="portrait"] {
overflow-x: hidden;
overflow-y: scroll;
}
#startui-body {
height: 100%;
margin: 0;

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

@ -64,7 +64,9 @@ def config_status(topobjdir='.', topsrcdir='.',
help='display verbose output')
parser.add_option('-n', dest='not_topobjdir', action='store_true',
help='do not consider current directory as top object directory')
(options, args) = parser.parse_args()
parser.add_option('-d', '--diff', action='store_true',
help='print diffs of changed files.')
options, args = parser.parse_args()
# Without -n, the current directory is meant to be the top object directory
if not options.not_topobjdir:
@ -98,3 +100,7 @@ def config_status(topobjdir='.', topsrcdir='.',
for line in summary.summaries():
print(line, file=sys.stderr)
if options.diff:
for path, diff in sorted(summary.file_diffs.items()):
print(diff)

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

@ -1,20 +1,13 @@
==================================
Mozilla Build System Documentation
==================================
Overview
========
.. toctree::
:maxdepth: 1
glossary
============
Build System
============
Important Concepts
==================
.. toctree::
:maxdepth: 1
glossary
build-overview
supported-configurations
Mozconfig Files <mozconfigs>
@ -41,24 +34,3 @@ Mozilla build system.
mozbuild/index
mozbuild/dumbmake
Python Packages
===============
.. toctree::
:maxdepth: 2
python/codegen
python/makeutils
python/mozbuild
python/mozpack
python/mozversioncontrol
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

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

@ -1,7 +0,0 @@
makeutils Module
================
.. automodule:: makeutils
:members:
:undoc-members:
:show-inheritance:

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

@ -1,35 +0,0 @@
action Package
==============
:mod:`link_deps` Module
-----------------------
.. automodule:: mozbuild.action.link_deps
:members:
:undoc-members:
:show-inheritance:
:mod:`process_install_manifest` Module
--------------------------------------
.. automodule:: mozbuild.action.process_install_manifest
:members:
:undoc-members:
:show-inheritance:
:mod:`xpccheck` Module
----------------------
.. automodule:: mozbuild.action.xpccheck
:members:
:undoc-members:
:show-inheritance:
:mod:`xpidl-process` Module
---------------------------
.. automodule:: mozbuild.action.xpidl-process
:members:
:undoc-members:
:show-inheritance:

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

@ -1,35 +0,0 @@
backend Package
===============
:mod:`base` Module
------------------
.. automodule:: mozbuild.backend.base
:members:
:undoc-members:
:show-inheritance:
:mod:`common` Module
--------------------
.. automodule:: mozbuild.backend.common
:members:
:undoc-members:
:show-inheritance:
:mod:`configenvironment` Module
-------------------------------
.. automodule:: mozbuild.backend.configenvironment
:members:
:undoc-members:
:show-inheritance:
:mod:`recursivemake` Module
---------------------------
.. automodule:: mozbuild.backend.recursivemake
:members:
:undoc-members:
:show-inheritance:

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

@ -1,11 +0,0 @@
compilation Package
===================
:mod:`warnings` Module
----------------------
.. automodule:: mozbuild.compilation.warnings
:members:
:undoc-members:
:show-inheritance:

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

@ -1,19 +0,0 @@
controller Package
==================
:mod:`building` Module
----------------------
.. automodule:: mozbuild.controller.building
:members:
:undoc-members:
:show-inheritance:
:mod:`clobber` Module
---------------------
.. automodule:: mozbuild.controller.clobber
:members:
:undoc-members:
:show-inheritance:

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

@ -1,51 +0,0 @@
frontend Package
================
:mod:`data` Module
------------------
.. automodule:: mozbuild.frontend.data
:members:
:undoc-members:
:show-inheritance:
:mod:`emitter` Module
---------------------
.. automodule:: mozbuild.frontend.emitter
:members:
:undoc-members:
:show-inheritance:
:mod:`mach_commands` Module
---------------------------
.. automodule:: mozbuild.frontend.mach_commands
:members:
:undoc-members:
:show-inheritance:
:mod:`reader` Module
--------------------
.. automodule:: mozbuild.frontend.reader
:members:
:undoc-members:
:show-inheritance:
:mod:`sandbox` Module
---------------------
.. automodule:: mozbuild.frontend.sandbox
:members:
:undoc-members:
:show-inheritance:
:mod:`sandbox_symbols` Module
-----------------------------
.. automodule:: mozbuild.frontend.sandbox_symbols
:members:
:undoc-members:
:show-inheritance:

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

@ -1,103 +0,0 @@
mozbuild Package
================
:mod:`base` Module
------------------
.. automodule:: mozbuild.base
:members:
:undoc-members:
:show-inheritance:
:mod:`config` Module
--------------------
.. automodule:: mozbuild.config
:members:
:undoc-members:
:show-inheritance:
:mod:`html_build_viewer` Module
-------------------------------
.. automodule:: mozbuild.html_build_viewer
:members:
:undoc-members:
:show-inheritance:
:mod:`mach_commands` Module
---------------------------
.. automodule:: mozbuild.mach_commands
:members:
:undoc-members:
:show-inheritance:
:mod:`makeutil` Module
----------------------
.. automodule:: mozbuild.makeutil
:members:
:undoc-members:
:show-inheritance:
:mod:`mozconfig` Module
-----------------------
.. automodule:: mozbuild.mozconfig
:members:
:undoc-members:
:show-inheritance:
:mod:`mozinfo` Module
---------------------
.. automodule:: mozbuild.mozinfo
:members:
:undoc-members:
:show-inheritance:
:mod:`pythonutil` Module
------------------------
.. automodule:: mozbuild.pythonutil
:members:
:undoc-members:
:show-inheritance:
:mod:`sphinx` Module
--------------------
.. automodule:: mozbuild.sphinx
:members:
:undoc-members:
:show-inheritance:
:mod:`util` Module
------------------
.. automodule:: mozbuild.util
:members:
:undoc-members:
:show-inheritance:
:mod:`virtualenv` Module
------------------------
.. automodule:: mozbuild.virtualenv
:members:
:undoc-members:
:show-inheritance:
Subpackages
-----------
.. toctree::
mozbuild.action
mozbuild.backend
mozbuild.compilation
mozbuild.controller
mozbuild.frontend
mozbuild.test

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

@ -1,19 +0,0 @@
chrome Package
==============
:mod:`flags` Module
-------------------
.. automodule:: mozpack.chrome.flags
:members:
:undoc-members:
:show-inheritance:
:mod:`manifest` Module
----------------------
.. automodule:: mozpack.chrome.manifest
:members:
:undoc-members:
:show-inheritance:

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

@ -1,35 +0,0 @@
packager Package
================
:mod:`packager` Package
-----------------------
.. automodule:: mozpack.packager
:members:
:undoc-members:
:show-inheritance:
:mod:`formats` Module
---------------------
.. automodule:: mozpack.packager.formats
:members:
:undoc-members:
:show-inheritance:
:mod:`l10n` Module
------------------
.. automodule:: mozpack.packager.l10n
:members:
:undoc-members:
:show-inheritance:
:mod:`unpack` Module
--------------------
.. automodule:: mozpack.packager.unpack
:members:
:undoc-members:
:show-inheritance:

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

@ -1,76 +0,0 @@
mozpack Package
===============
:mod:`copier` Module
--------------------
.. automodule:: mozpack.copier
:members:
:undoc-members:
:show-inheritance:
:mod:`errors` Module
--------------------
.. automodule:: mozpack.errors
:members:
:undoc-members:
:show-inheritance:
:mod:`executables` Module
-------------------------
.. automodule:: mozpack.executables
:members:
:undoc-members:
:show-inheritance:
:mod:`files` Module
-------------------
.. automodule:: mozpack.files
:members:
:undoc-members:
:show-inheritance:
:mod:`manifests` Module
-----------------------
.. automodule:: mozpack.manifests
:members:
:undoc-members:
:show-inheritance:
:mod:`mozjar` Module
--------------------
.. automodule:: mozpack.mozjar
:members:
:undoc-members:
:show-inheritance:
:mod:`path` Module
------------------
.. automodule:: mozpack.path
:members:
:undoc-members:
:show-inheritance:
:mod:`unify` Module
-------------------
.. automodule:: mozpack.unify
:members:
:undoc-members:
:show-inheritance:
Subpackages
-----------
.. toctree::
mozpack.chrome
mozpack.packager
mozpack.test

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

@ -1,11 +0,0 @@
mozversioncontrol Package
=========================
:mod:`repoupdate` Module
------------------------
.. automodule:: mozversioncontrol.repoupdate
:members:
:undoc-members:
:show-inheritance:

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

@ -75,6 +75,7 @@ MACH_MODULES = [
'testing/xpcshell/mach_commands.py',
'testing/talos/mach_commands.py',
'testing/xpcshell/mach_commands.py',
'tools/docs/mach_commands.py',
'tools/mercurial/mach_commands.py',
'tools/mach_commands.py',
]

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

@ -4,8 +4,4 @@
# 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/.
ANDROID_RESFILES = [
'res/values/strings.xml',
]
DEFINES['ANDROID_PACKAGE_NAME'] = CONFIG['ANDROID_PACKAGE_NAME']

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

@ -3,11 +3,3 @@
# 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/.
ANDROID_RESFILES = [
'res/drawable-hdpi/icon.png',
'res/drawable-ldpi/icon.png',
'res/drawable-mdpi/icon.png',
'res/layout/main.xml',
'res/values/strings.xml',
]

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

@ -3,11 +3,3 @@
# 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/.
ANDROID_RESFILES = [
'res/drawable-hdpi/icon.png',
'res/drawable-ldpi/icon.png',
'res/drawable-mdpi/icon.png',
'res/layout/main.xml',
'res/values/strings.xml',
]

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

@ -3,13 +3,3 @@
# 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/.
ANDROID_RESFILES = [
'res/drawable/ateamlogo.png',
'res/drawable/ic_stat_first.png',
'res/drawable/ic_stat_neterror.png',
'res/drawable/ic_stat_warning.png',
'res/drawable/icon.png',
'res/layout/main.xml',
'res/values/strings.xml',
]

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

@ -3,14 +3,3 @@
# 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/.
ANDROID_RESFILES = [
'res/drawable-hdpi/ateamlogo.png',
'res/drawable-hdpi/icon.png',
'res/drawable-ldpi/ateamlogo.png',
'res/drawable-ldpi/icon.png',
'res/drawable-mdpi/ateamlogo.png',
'res/drawable-mdpi/icon.png',
'res/layout/main.xml',
'res/values/strings.xml',
]

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

@ -4,6 +4,8 @@
# 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/.
SPHINX_TREES['build'] = 'docs'
if CONFIG['OS_ARCH'] not in ('WINNT', 'OS2'):
DIRS += ['unix']
elif CONFIG['OS_ARCH'] == 'WINNT':

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

@ -5,8 +5,6 @@
INTERNAL_TOOLS = 1
NO_PROFILE_GUIDED_OPTIMIZE = 1
VPATH += $(topsrcdir)/build
OS_CXXFLAGS := $(filter-out -fno-exceptions,$(OS_CXXFLAGS)) -fexceptions

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

@ -4,7 +4,6 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
INTERNAL_TOOLS = 1
NO_PROFILE_GUIDED_OPTIMIZE = 1
include $(topsrcdir)/config/rules.mk

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

@ -18,3 +18,5 @@ GENERATED_SOURCES += [
]
DEFINES['ELFHACK_BUILD'] = True
NO_PGO = True

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

@ -25,3 +25,5 @@ HOST_SOURCES += [
HOST_PROGRAM = 'elfhack'
DEFINES['ELFHACK_BUILD'] = True
NO_PGO = True

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

@ -4,7 +4,6 @@
STL_FLAGS =
NO_EXPAND_LIBS = 1
NO_PROFILE_GUIDED_OPTIMIZE = 1
include $(topsrcdir)/config/rules.mk

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

@ -15,3 +15,5 @@ if CONFIG['MOZ_LIBSTDCXX_HOST_VERSION']:
]
FORCE_STATIC_LIB = True
NO_PGO = True

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

@ -13,6 +13,7 @@ mock.pth:python/mock-1.0.0
mozilla.pth:build
mozilla.pth:config
mozilla.pth:xpcom/typelib/xpt/tools
moztreedocs.pth:tools/docs
copy:build/buildconfig.py
packages.txt:testing/mozbase/packages.txt
objdir:build

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

@ -2,8 +2,6 @@
# 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/.
NO_PROFILE_GUIDED_OPTIMIZE = 1
ifdef ENABLE_TESTS
USE_STATIC_LIBS = 1

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

@ -14,3 +14,5 @@ if CONFIG['ENABLE_TESTS']:
SOURCES += [
'crashinject.cpp',
]
NO_PGO = True

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

@ -35,7 +35,7 @@ endif
# responsibility between Makefile.in and mozbuild files.
_MOZBUILD_EXTERNAL_VARIABLES := \
ANDROID_GENERATED_RESFILES \
ANDROID_RESFILES \
ANDROID_RES_DIRS \
CMSRCS \
CMMSRCS \
CPP_UNIT_TESTS \
@ -70,6 +70,7 @@ _MOZBUILD_EXTERNAL_VARIABLES := \
$(NULL)
_DEPRECATED_VARIABLES := \
ANDROID_RESFILES \
MOCHITEST_FILES_PARTS \
MOCHITEST_BROWSER_FILES_PARTS \
SHORT_LIBNAME \

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

@ -7,29 +7,6 @@
ifndef INCLUDED_JAVA_BUILD_MK #{
ifdef ANDROID_RESFILES #{
ifndef IGNORE_ANDROID_RESFILES #{
res-dep := .deps-copy-java-res
GENERATED_DIRS += res
GARBAGE += $(res-dep)
export:: $(res-dep)
res-dep-preqs := \
$(addprefix $(srcdir)/,$(ANDROID_RESFILES)) \
$(call mkdir_deps,res) \
$(if $(IS_LANGUAGE_REPACK),FORCE) \
$(NULL)
# nop-build: only copy res/ files when needed
$(res-dep): $(res-dep-preqs)
$(call copy_dir,$(srcdir)/res,$(CURDIR)/res)
@$(TOUCH) $@
endif #} IGNORE_ANDROID_RESFILES
endif #} ANDROID_RESFILES
ifdef JAVAFILES #{
GENERATED_DIRS += classes
@ -39,7 +16,8 @@ endif #} JAVAFILES
ifdef ANDROID_APK_NAME #{
_ANDROID_RES_FLAG := -S $(or $(ANDROID_RES_DIR),res)
android_res_dirs := $(addprefix $(srcdir)/,$(or $(ANDROID_RES_DIRS),res))
_ANDROID_RES_FLAG := $(addprefix -S ,$(android_res_dirs))
_ANDROID_ASSETS_FLAG := $(addprefix -A ,$(ANDROID_ASSETS_DIR))
GENERATED_DIRS += classes
@ -57,7 +35,11 @@ classes.dex: $(JAVAFILES)
R.java: .aapt.deps
$(ANDROID_APK_NAME).ap_: .aapt.deps
.aapt.deps: AndroidManifest.xml $(wildcard $(ANDROID_RES_DIR)) $(wildcard $(ANDROID_ASSETS_DIR))
# This uses the fact that Android resource directories list all
# resource files one subdirectory below the parent resource directory.
android_res_files := $(wildcard $(addsuffix /*,$(wildcard $(addsuffix /*,$(android_res_dirs)))))
.aapt.deps: AndroidManifest.xml $(android_res_files) $(wildcard $(ANDROID_ASSETS_DIR))
$(AAPT) package -f -M $< -I $(ANDROID_SDK)/android.jar $(_ANDROID_RES_FLAG) $(_ANDROID_ASSETS_FLAG) \
-J ${@D} \
-F $(ANDROID_APK_NAME).ap_

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

@ -642,7 +642,7 @@ tools::
endif
##############################################
ifndef NO_PROFILE_GUIDED_OPTIMIZE
ifneq (1,$(NO_PROFILE_GUIDED_OPTIMIZE))
ifdef MOZ_PROFILE_USE
ifeq ($(OS_ARCH)_$(GNU_CC), WINNT_)
# When building with PGO, we have to make sure to re-link

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

@ -1545,6 +1545,7 @@ public:
static JSContext *GetCurrentJSContext();
static JSContext *GetSafeJSContext();
static JSContext *GetCurrentJSContextForThread();
static JSContext *GetDefaultJSContextForThread();
/**

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

@ -5262,6 +5262,17 @@ nsContentUtils::GetDefaultJSContextForThread()
}
}
/* static */
JSContext *
nsContentUtils::GetCurrentJSContextForThread()
{
if (MOZ_LIKELY(NS_IsMainThread())) {
return GetCurrentJSContext();
} else {
return workers::GetCurrentThreadJSContext();
}
}
/* static */
nsresult
nsContentUtils::ASCIIToLower(nsAString& aStr)

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

@ -39,7 +39,6 @@
#include "nsIDOMNode.h"
#include "nsContentUtils.h"
#include "nsCxPusher.h"
#include "nsLayoutUtils.h"
#include "nsIContentPolicy.h"
#include "nsEventDispatcher.h"
@ -47,6 +46,7 @@
#include "mozAutoDocUpdate.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/ScriptSettings.h"
#if defined(XP_WIN)
// Undefine LoadImage to prevent naming conflict with Windows.
@ -1194,12 +1194,6 @@ nsImageLoadingContent::ClearPendingRequest(nsresult aReason,
if (!mPendingRequest)
return;
// Push a null JSContext on the stack so that code that runs within
// the below code doesn't think it's being called by JS. See bug
// 604262.
nsCxPusher pusher;
pusher.PushNull();
// Deregister this image from the refresh driver so it no longer receives
// notifications.
nsLayoutUtils::DeregisterImageRequest(GetFramePresContext(), mPendingRequest,
@ -1259,11 +1253,6 @@ nsImageLoadingContent::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
if (!aDocument)
return;
// Push a null JSContext on the stack so that callbacks triggered by the
// below code won't think they're being called from JS.
nsCxPusher pusher;
pusher.PushNull();
TrackImage(mCurrentRequest);
TrackImage(mPendingRequest);
@ -1279,11 +1268,6 @@ nsImageLoadingContent::UnbindFromTree(bool aDeep, bool aNullParent)
if (!doc)
return;
// Push a null JSContext on the stack so that callbacks triggered by the
// below code won't think they're being called from JS.
nsCxPusher pusher;
pusher.PushNull();
UntrackImage(mCurrentRequest);
UntrackImage(mPendingRequest);

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

@ -14,10 +14,12 @@
#include "mozilla/dom/HTMLCanvasElement.h"
#include "nsContentUtils.h"
#include "mozilla/Preferences.h"
#include "mozilla/gfx/2D.h"
namespace mozilla {
using namespace dom;
using namespace gfx;
struct ImageCacheKey {
ImageCacheKey(Element* aImage, HTMLCanvasElement* aCanvas)
@ -32,7 +34,7 @@ struct ImageCacheEntryData {
, mILC(aOther.mILC)
, mCanvas(aOther.mCanvas)
, mRequest(aOther.mRequest)
, mSurface(aOther.mSurface)
, mSourceSurface(aOther.mSourceSurface)
, mSize(aOther.mSize)
{}
ImageCacheEntryData(const ImageCacheKey& aKey)
@ -51,7 +53,7 @@ struct ImageCacheEntryData {
nsRefPtr<HTMLCanvasElement> mCanvas;
// Value
nsCOMPtr<imgIRequest> mRequest;
nsRefPtr<gfxASurface> mSurface;
RefPtr<SourceSurface> mSourceSurface;
gfxIntSize mSize;
nsExpirationState mState;
};
@ -127,7 +129,7 @@ void
CanvasImageCache::NotifyDrawImage(Element* aImage,
HTMLCanvasElement* aCanvas,
imgIRequest* aRequest,
gfxASurface* aSurface,
SourceSurface* aSource,
const gfxIntSize& aSize)
{
if (!gImageCache) {
@ -137,7 +139,7 @@ CanvasImageCache::NotifyDrawImage(Element* aImage,
ImageCacheEntry* entry = gImageCache->mCache.PutEntry(ImageCacheKey(aImage, aCanvas));
if (entry) {
if (entry->mData->mSurface) {
if (entry->mData->mSourceSurface) {
// We are overwriting an existing entry.
gImageCache->mTotal -= entry->mData->SizeInBytes();
gImageCache->RemoveObject(entry->mData);
@ -150,7 +152,7 @@ CanvasImageCache::NotifyDrawImage(Element* aImage,
getter_AddRefs(entry->mData->mRequest));
}
entry->mData->mILC = ilc;
entry->mData->mSurface = aSurface;
entry->mData->mSourceSurface = aSource;
entry->mData->mSize = aSize;
gImageCache->mTotal += entry->mData->SizeInBytes();
@ -164,7 +166,7 @@ CanvasImageCache::NotifyDrawImage(Element* aImage,
gImageCache->AgeOneGeneration();
}
gfxASurface*
SourceSurface*
CanvasImageCache::Lookup(Element* aImage,
HTMLCanvasElement* aCanvas,
gfxIntSize* aSize)
@ -184,7 +186,7 @@ CanvasImageCache::Lookup(Element* aImage,
gImageCache->MarkUsed(entry->mData);
*aSize = entry->mData->mSize;
return entry->mData->mSurface;
return entry->mData->mSourceSurface;
}
NS_IMPL_ISUPPORTS1(CanvasImageCacheShutdownObserver, nsIObserver)

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

@ -11,6 +11,9 @@ namespace dom {
class Element;
class HTMLCanvasElement;
} // namespace dom
namespace gfx {
class SourceSurface;
} // namespace gfx
} // namespace mozilla
class imgIRequest;
class gfxASurface;
@ -20,6 +23,7 @@ class gfxASurface;
namespace mozilla {
class CanvasImageCache {
typedef mozilla::gfx::SourceSurface SourceSurface;
public:
/**
* Notify that image element aImage was (or is about to be) drawn to aCanvas
@ -29,7 +33,7 @@ public:
static void NotifyDrawImage(dom::Element* aImage,
dom::HTMLCanvasElement* aCanvas,
imgIRequest* aRequest,
gfxASurface* aSurface,
SourceSurface* aSource,
const gfxIntSize& aSize);
/**
@ -38,9 +42,9 @@ public:
* (with the same image request) and the returned surface contains the image
* data, and the image size will be returned in aSize.
*/
static gfxASurface* Lookup(dom::Element* aImage,
dom::HTMLCanvasElement* aCanvas,
gfxIntSize* aSize);
static SourceSurface* Lookup(dom::Element* aImage,
dom::HTMLCanvasElement* aCanvas,
gfxIntSize* aSize);
};
}

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

@ -1450,29 +1450,21 @@ CanvasRenderingContext2D::CreatePattern(const HTMLImageOrCanvasOrVideoElement& e
htmlElement = &element.GetAsHTMLVideoElement();
}
EnsureTarget();
// The canvas spec says that createPattern should use the first frame
// of animated images
nsLayoutUtils::SurfaceFromElementResult res =
nsLayoutUtils::SurfaceFromElement(htmlElement,
nsLayoutUtils::SFE_WANT_FIRST_FRAME | nsLayoutUtils::SFE_WANT_NEW_SURFACE);
nsLayoutUtils::SFE_WANT_FIRST_FRAME, mTarget);
if (!res.mSurface) {
if (!res.mSourceSurface) {
error.Throw(NS_ERROR_NOT_AVAILABLE);
return nullptr;
}
// Ignore nullptr cairo surfaces! See bug 666312.
if (!res.mSurface->CairoSurface() || res.mSurface->CairoStatus()) {
error.Throw(NS_ERROR_NOT_AVAILABLE);
return nullptr;
}
EnsureTarget();
RefPtr<SourceSurface> srcSurf =
gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(mTarget, res.mSurface);
nsRefPtr<CanvasPattern> pat =
new CanvasPattern(this, srcSurf, repeatMode, res.mPrincipal,
new CanvasPattern(this, res.mSourceSurface, repeatMode, res.mPrincipal,
res.mIsWriteOnly, res.mCORSUsed);
return pat.forget();
@ -3084,11 +3076,8 @@ CanvasRenderingContext2D::DrawImage(const HTMLImageOrCanvasOrVideoElement& image
element = video;
}
gfxASurface* imgsurf =
srcSurf =
CanvasImageCache::Lookup(element, mCanvasElement, &imgSize);
if (imgsurf) {
srcSurf = gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(mTarget, imgsurf);
}
}
if (!srcSurf) {
@ -3096,9 +3085,9 @@ CanvasRenderingContext2D::DrawImage(const HTMLImageOrCanvasOrVideoElement& image
// of animated images
uint32_t sfeFlags = nsLayoutUtils::SFE_WANT_FIRST_FRAME;
nsLayoutUtils::SurfaceFromElementResult res =
nsLayoutUtils::SurfaceFromElement(element, sfeFlags);
nsLayoutUtils::SurfaceFromElement(element, sfeFlags, mTarget);
if (!res.mSurface) {
if (!res.mSourceSurface) {
// Spec says to silently do nothing if the element is still loading.
if (!res.mIsStillLoading) {
error.Throw(NS_ERROR_NOT_AVAILABLE);
@ -3106,11 +3095,6 @@ CanvasRenderingContext2D::DrawImage(const HTMLImageOrCanvasOrVideoElement& image
return;
}
// Ignore cairo surfaces that are bad! See bug 666312.
if (res.mSurface->CairoStatus()) {
return;
}
imgSize = res.mSize;
// Scale sw/sh based on aspect ratio
@ -3129,11 +3113,11 @@ CanvasRenderingContext2D::DrawImage(const HTMLImageOrCanvasOrVideoElement& image
}
if (res.mImageRequest) {
CanvasImageCache::NotifyDrawImage(element, mCanvasElement,
res.mImageRequest, res.mSurface, imgSize);
CanvasImageCache::NotifyDrawImage(element, mCanvasElement, res.mImageRequest,
res.mSourceSurface, imgSize);
}
srcSurf = gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(mTarget, res.mSurface);
srcSurf = res.mSourceSurface;
}
if (optional_argc == 0) {

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

@ -28,6 +28,7 @@
#include "mozilla/LinkedList.h"
#include "mozilla/CheckedInt.h"
#include "mozilla/Scoped.h"
#include "mozilla/gfx/2D.h"
#ifdef XP_MACOSX
#include "ForceDiscreteGPUHelperCGL.h"
@ -420,18 +421,19 @@ public:
{
if (IsContextLost())
return;
nsRefPtr<gfxImageSurface> isurf;
RefPtr<gfx::DataSourceSurface> data;
WebGLTexelFormat srcFormat;
nsLayoutUtils::SurfaceFromElementResult res = SurfaceFromElement(elt);
rv = SurfaceFromElementResultToImageSurface(res, getter_AddRefs(isurf),
rv = SurfaceFromElementResultToImageSurface(res, data,
&srcFormat);
if (rv.Failed() || !isurf)
if (rv.Failed() || !data)
return;
uint32_t byteLength = isurf->Stride() * isurf->Height();
gfx::IntSize size = data->GetSize();
uint32_t byteLength = data->Stride() * size.height;
return TexImage2D_base(target, level, internalformat,
isurf->Width(), isurf->Height(), isurf->Stride(),
0, format, type, isurf->Data(), byteLength,
size.width, size.height, data->Stride(),
0, format, type, data->GetData(), byteLength,
-1, srcFormat, mPixelStorePremultiplyAlpha);
}
void TexParameterf(GLenum target, GLenum pname, GLfloat param) {
@ -459,19 +461,20 @@ public:
{
if (IsContextLost())
return;
nsRefPtr<gfxImageSurface> isurf;
RefPtr<gfx::DataSourceSurface> data;
WebGLTexelFormat srcFormat;
nsLayoutUtils::SurfaceFromElementResult res = SurfaceFromElement(elt);
rv = SurfaceFromElementResultToImageSurface(res, getter_AddRefs(isurf),
rv = SurfaceFromElementResultToImageSurface(res, data,
&srcFormat);
if (rv.Failed() || !isurf)
if (rv.Failed() || !data)
return;
uint32_t byteLength = isurf->Stride() * isurf->Height();
gfx::IntSize size = data->GetSize();
uint32_t byteLength = data->Stride() * size.height;
return TexSubImage2D_base(target, level, xoffset, yoffset,
isurf->Width(), isurf->Height(),
isurf->Stride(), format, type,
isurf->Data(), byteLength,
size.width, size.height,
data->Stride(), format, type,
data->GetData(), byteLength,
-1, srcFormat, mPixelStorePremultiplyAlpha);
}
@ -992,7 +995,7 @@ protected:
nsLayoutUtils::SurfaceFromElementResult SurfaceFromElement(ElementType* aElement) {
MOZ_ASSERT(aElement);
uint32_t flags =
nsLayoutUtils::SFE_WANT_IMAGE_SURFACE;
nsLayoutUtils::SFE_WANT_IMAGE_SURFACE;
if (mPixelStoreColorspaceConversion == LOCAL_GL_NONE)
flags |= nsLayoutUtils::SFE_NO_COLORSPACE_CONVERSION;
@ -1007,7 +1010,7 @@ protected:
}
nsresult SurfaceFromElementResultToImageSurface(nsLayoutUtils::SurfaceFromElementResult& res,
gfxImageSurface **imageOut,
RefPtr<gfx::DataSourceSurface>& imageOut,
WebGLTexelFormat *format);
void CopyTexSubImage2D_base(GLenum target,

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

@ -48,6 +48,7 @@
using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::gl;
using namespace mozilla::gfx;
static bool BaseTypeAndSizeFromUniformType(GLenum uType, GLenum *baseType, GLint *unitSize);
static GLenum InternalFormatForFormatAndType(GLenum format, GLenum type, bool isGLES2);
@ -2640,14 +2641,14 @@ WebGLContext::StencilOpSeparate(GLenum face, GLenum sfail, GLenum dpfail, GLenum
nsresult
WebGLContext::SurfaceFromElementResultToImageSurface(nsLayoutUtils::SurfaceFromElementResult& res,
gfxImageSurface **imageOut, WebGLTexelFormat *format)
RefPtr<DataSourceSurface>& imageOut, WebGLTexelFormat *format)
{
*imageOut = nullptr;
*format = WebGLTexelFormat::None;
if (!res.mSurface)
if (!res.mSourceSurface)
return NS_OK;
if (res.mSurface->GetType() != gfxSurfaceTypeImage) {
RefPtr<DataSourceSurface> data = res.mSourceSurface->GetDataSurface();
if (!data) {
// SurfaceFromElement lied!
return NS_OK;
}
@ -2687,22 +2688,17 @@ WebGLContext::SurfaceFromElementResultToImageSurface(nsLayoutUtils::SurfaceFromE
// Notice that there is never a need to mark the WebGL canvas as write-only, since we reject write-only/cross-domain
// texture sources in the first place.
gfxImageSurface* surf = static_cast<gfxImageSurface*>(res.mSurface.get());
res.mSurface.forget();
*imageOut = surf;
switch (surf->Format()) {
case gfxImageFormatARGB32:
switch (data->GetFormat()) {
case FORMAT_B8G8R8A8:
*format = WebGLTexelFormat::BGRA8; // careful, our ARGB means BGRA
break;
case gfxImageFormatRGB24:
case FORMAT_B8G8R8X8:
*format = WebGLTexelFormat::BGRX8; // careful, our RGB24 is not tightly packed. Whence BGRX8.
break;
case gfxImageFormatA8:
case FORMAT_A8:
*format = WebGLTexelFormat::A8;
break;
case gfxImageFormatRGB16_565:
case FORMAT_R5G6B5:
*format = WebGLTexelFormat::RGB565;
break;
default:
@ -2710,6 +2706,8 @@ WebGLContext::SurfaceFromElementResultToImageSurface(nsLayoutUtils::SurfaceFromE
return NS_ERROR_NOT_IMPLEMENTED;
}
imageOut = data;
return NS_OK;
}

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

@ -9,6 +9,7 @@
#include "nsIDocument.h"
#include "prprf.h"
#include "nsGlobalWindow.h"
#include "ScriptSettings.h"
#include "mozilla/Likely.h"
using namespace mozilla;
@ -271,10 +272,10 @@ nsDOMEventTargetHelper::SetEventHandler(nsIAtom* aType,
const JS::Value& aValue)
{
nsRefPtr<EventHandlerNonNull> handler;
JSObject* callable;
JS::Rooted<JSObject*> callable(aCx);
if (aValue.isObject() &&
JS_ObjectIsCallable(aCx, callable = &aValue.toObject())) {
handler = new EventHandlerNonNull(callable);
handler = new EventHandlerNonNull(callable, mozilla::dom::GetIncumbentGlobal());
}
SetEventHandler(aType, EmptyString(), handler);
return NS_OK;

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

@ -883,19 +883,23 @@ nsEventListenerManager::CompileEventHandlerInternal(nsListenerStruct *aListenerS
JS::Rooted<JSObject*> scope(cx, listener->GetEventScope());
context->BindCompiledEventHandler(mTarget, scope, handler, &boundHandler);
aListenerStruct = nullptr;
// Note - We pass null for aIncumbentGlobal below. We could also pass the
// compilation global, but since the handler is guaranteed to be scripted,
// there's no need to use an override, since the JS engine will always give
// us the right answer.
if (!boundHandler) {
listener->ForgetHandler();
} else if (listener->EventName() == nsGkAtoms::onerror && win) {
nsRefPtr<OnErrorEventHandlerNonNull> handlerCallback =
new OnErrorEventHandlerNonNull(boundHandler);
new OnErrorEventHandlerNonNull(boundHandler, /* aIncumbentGlobal = */ nullptr);
listener->SetHandler(handlerCallback);
} else if (listener->EventName() == nsGkAtoms::onbeforeunload && win) {
nsRefPtr<OnBeforeUnloadEventHandlerNonNull> handlerCallback =
new OnBeforeUnloadEventHandlerNonNull(boundHandler);
new OnBeforeUnloadEventHandlerNonNull(boundHandler, /* aIncumbentGlobal = */ nullptr);
listener->SetHandler(handlerCallback);
} else {
nsRefPtr<EventHandlerNonNull> handlerCallback =
new EventHandlerNonNull(boundHandler);
new EventHandlerNonNull(boundHandler, /* aIncumbentGlobal = */ nullptr);
listener->SetHandler(handlerCallback);
}
}

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

@ -2504,11 +2504,11 @@ void
nsEventStateManager::DoScrollZoom(nsIFrame *aTargetFrame,
int32_t adjustment)
{
// Exclude form controls and XUL content.
// Exclude form controls and content in chrome docshells.
nsIContent *content = aTargetFrame->GetContent();
if (content &&
!content->IsNodeOfType(nsINode::eHTML_FORM_CONTROL) &&
!content->OwnerDoc()->IsXUL())
!nsContentUtils::IsInChromeDocshell(content->OwnerDoc()))
{
// positive adjustment to decrease zoom, negative to increase
int32_t change = (adjustment > 0) ? -1 : 1;

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

@ -207,10 +207,6 @@ public:
virtual VideoFrameContainer* GetVideoFrameContainer() MOZ_FINAL MOZ_OVERRIDE;
layers::ImageContainer* GetImageContainer();
// Called by the video frame to get the print surface, if this is
// a static document and we're not actually playing video
gfxASurface* GetPrintSurface() { return mPrintSurface; }
// Dispatch events
using nsGenericHTMLElement::DispatchEvent;
virtual nsresult DispatchEvent(const nsAString& aName) MOZ_FINAL MOZ_OVERRIDE;
@ -1013,8 +1009,6 @@ protected:
// non-intrinsic value.
bool mPreservesPitch;
nsRefPtr<gfxASurface> mPrintSurface;
// Reference to the source element last returned by GetNextSource().
// This is the child source element which we're trying to load from.
nsCOMPtr<nsIContent> mSourceLoadCandidate;

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

@ -3223,11 +3223,6 @@ VideoFrameContainer* HTMLMediaElement::GetVideoFrameContainer()
if (mVideoFrameContainer)
return mVideoFrameContainer;
// If we have a print surface, this is just a static image so
// no image container is required
if (mPrintSurface)
return nullptr;
// Only video frames need an image container.
nsCOMPtr<nsIDOMHTMLVideoElement> video = do_QueryObject(this);
if (!video)
@ -3604,26 +3599,7 @@ HTMLMediaElement::CopyInnerTo(Element* aDest)
NS_ENSURE_SUCCESS(rv, rv);
if (aDest->OwnerDoc()->IsStaticDocument()) {
HTMLMediaElement* dest = static_cast<HTMLMediaElement*>(aDest);
if (mPrintSurface) {
dest->mPrintSurface = mPrintSurface;
dest->mMediaSize = mMediaSize;
} else {
nsIFrame* frame = GetPrimaryFrame();
Element* element;
if (frame && frame->GetType() == nsGkAtoms::HTMLVideoFrame &&
static_cast<nsVideoFrame*>(frame)->ShouldDisplayPoster()) {
nsIContent* content = static_cast<nsVideoFrame*>(frame)->GetPosterImage();
element = content ? content->AsElement() : nullptr;
} else {
element = const_cast<HTMLMediaElement*>(this);
}
nsLayoutUtils::SurfaceFromElementResult res =
nsLayoutUtils::SurfaceFromElement(element,
nsLayoutUtils::SFE_WANT_NEW_SURFACE);
dest->mPrintSurface = res.mSurface;
dest->mMediaSize = nsIntSize(res.mSize.width, res.mSize.height);
}
dest->mMediaSize = mMediaSize;
}
return rv;
}

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

@ -38,11 +38,11 @@
#include "mozilla/Selection.h"
#include "nsEventListenerManager.h"
#include "nsContentUtils.h"
#include "nsCxPusher.h"
#include "mozilla/Preferences.h"
#include "nsTextNode.h"
#include "nsIController.h"
#include "mozilla/TextEvents.h"
#include "mozilla/dom/ScriptSettings.h"
using namespace mozilla;
using namespace mozilla::dom;
@ -1283,13 +1283,12 @@ nsTextEditorState::PrepareEditor(const nsAString *aValue)
// What follows is a bit of a hack. The editor uses the public DOM APIs
// for its content manipulations, and it causes it to fail some security
// checks deep inside when initializing. So we push a null JSContext
// on the JS stack here to make it clear that we're native code.
// checks deep inside when initializing. So we explictly make it clear that
// we're native code.
// Note that any script that's directly trying to access our value
// has to be going through some scriptable object to do that and that
// already does the relevant security checks.
nsCxPusher pusher;
pusher.PushNull();
AutoSystemCaller asc;
rv = newEditor->Init(domdoc, GetRootNode(), mSelCon, editorFlags);
NS_ENSURE_SUCCESS(rv, rv);
@ -1777,9 +1776,8 @@ nsTextEditorState::GetValue(nsAString& aValue, bool aIgnoreWrap) const
// XXXbz if we could just get the textContent of our anonymous content (eg
// if plaintext editor didn't create <br> nodes all over), we wouldn't need
// this.
{ /* Scope for context pusher */
nsCxPusher pusher;
pusher.PushNull();
{ /* Scope for AutoSystemCaller. */
AutoSystemCaller asc;
mEditor->OutputToString(NS_LITERAL_STRING("text/plain"), flags,
aValue);
@ -1857,9 +1855,8 @@ nsTextEditorState::SetValue(const nsAString& aValue, bool aUserInput,
// Time to mess with our security context... See comments in GetValue()
// for why this is needed. Note that we have to do this up here, because
// otherwise SelectAll() will fail.
{ /* Scope for context pusher */
nsCxPusher pusher;
pusher.PushNull();
{
AutoSystemCaller asc;
nsCOMPtr<nsISelection> domSel;
nsCOMPtr<nsISelectionPrivate> selPriv;

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

@ -32,6 +32,11 @@ static const int kOpusSamplingRate = 48000;
// The duration of an Opus frame, and it must be 2.5, 5, 10, 20, 40 or 60 ms.
static const int kFrameDurationMs = 20;
// The supported sampling rate of input signal (Hz),
// must be one of the following. Will resampled to 48kHz otherwise.
static const int kOpusSupportedInputSamplingRates[5] =
{8000, 12000, 16000, 24000, 48000};
namespace {
// An endian-neutral serialization of integers. Serializing T in little endian
@ -146,12 +151,14 @@ OpusTrackEncoder::Init(int aChannels, int aSamplingRate)
if (aChannels <= 0) {
return NS_ERROR_FAILURE;
}
// The granule position is required to be incremented at a rate of 48KHz, and
// it is simply calculated as |granulepos = samples * (48000/source_rate)|,
// that is, the source sampling rate must divide 48000 evenly.
// If this constraint is not satisfied, we resample the input to 48kHz.
if (!((aSamplingRate >= 8000) && (kOpusSamplingRate / aSamplingRate) *
aSamplingRate == kOpusSamplingRate)) {
// According to www.opus-codec.org, creating an opus encoder requires the
// sampling rate of source signal be one of 8000, 12000, 16000, 24000, or
// 48000. If this constraint is not satisfied, we resample the input to 48kHz.
nsTArray<int> supportedSamplingRates;
supportedSamplingRates.AppendElements(kOpusSupportedInputSamplingRates,
MOZ_ARRAY_LENGTH(kOpusSupportedInputSamplingRates));
if (!supportedSamplingRates.Contains(aSamplingRate)) {
int error;
mResampler = speex_resampler_init(mChannels,
aSamplingRate,

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

@ -11,6 +11,7 @@
#include "WebMBufferedParser.h"
#include "mozilla/dom/TimeRanges.h"
#include "VorbisUtils.h"
#include <algorithm>
#define VPX_DONT_DEFINE_STDINT_TYPES
#include "vpx/vp8dx.h"
@ -147,6 +148,7 @@ WebMReader::WebMReader(AbstractMediaDecoder* aDecoder)
mOpusParser(nullptr),
mOpusDecoder(nullptr),
mSkip(0),
mSeekPreroll(0),
#endif
mVideoTrack(0),
mAudioTrack(0),
@ -218,10 +220,20 @@ nsresult WebMReader::ResetDecode()
res = NS_ERROR_FAILURE;
}
// Ignore failed results from vorbis_synthesis_restart. They
// aren't fatal and it fails when ResetDecode is called at a
// time when no vorbis data has been read.
vorbis_synthesis_restart(&mVorbisDsp);
if (mAudioCodec == NESTEGG_CODEC_VORBIS) {
// Ignore failed results from vorbis_synthesis_restart. They
// aren't fatal and it fails when ResetDecode is called at a
// time when no vorbis data has been read.
vorbis_synthesis_restart(&mVorbisDsp);
#ifdef MOZ_OPUS
} else if (mAudioCodec == NESTEGG_CODEC_OPUS) {
if (mOpusDecoder) {
// Reset the decoder.
opus_multistream_decoder_ctl(mOpusDecoder, OPUS_RESET_STATE);
mSkip = mOpusParser->mPreSkip;
}
#endif
}
mVideoPackets.Reset();
mAudioPackets.Reset();
@ -431,6 +443,8 @@ nsresult WebMReader::ReadMetadata(MediaInfo* aInfo,
mInfo.mAudio.mChannels = mOpusParser->mChannels;
mInfo.mAudio.mChannels = mInfo.mAudio.mChannels > 2 ? 2 : mInfo.mAudio.mChannels;
mChannels = mInfo.mAudio.mChannels;
mSeekPreroll = params.seek_preroll;
#endif
} else {
Cleanup();
@ -627,6 +641,7 @@ bool WebMReader::DecodeAudioPacket(nestegg_packet* aPacket, int64_t aOffset)
if (ret < 0)
return false;
NS_ASSERTION(ret == frames, "Opus decoded too few audio samples");
CheckedInt64 startTime = tstamp_usecs;
// Trim the initial frames while the decoder is settling.
if (mSkip > 0) {
@ -643,7 +658,7 @@ bool WebMReader::DecodeAudioPacket(nestegg_packet* aPacket, int64_t aOffset)
nsAutoArrayPtr<AudioDataValue> trimBuffer(new AudioDataValue[samples]);
for (int i = 0; i < samples; i++)
trimBuffer[i] = buffer[skipFrames*channels + i];
startTime = startTime + FramesToUsecs(skipFrames, rate);
frames = keepFrames;
buffer = trimBuffer;
@ -708,14 +723,12 @@ bool WebMReader::DecodeAudioPacket(nestegg_packet* aPacket, int64_t aOffset)
NS_WARNING("Int overflow converting WebM audio duration");
return false;
}
CheckedInt64 time = tstamp_usecs;
CheckedInt64 time = startTime - (mCodecDelay / NS_PER_USEC);
if (!time.isValid()) {
NS_WARNING("Int overflow adding total_duration and tstamp_usecs");
NS_WARNING("Int overflow shifting tstamp by codec delay");
nestegg_free_packet(aPacket);
return false;
};
AudioQueue().Push(new AudioData(mDecoder->GetResource()->Tell(),
time.value(),
duration.value(),
@ -982,7 +995,11 @@ nsresult WebMReader::Seek(int64_t aTarget, int64_t aStartTime, int64_t aEndTime,
return NS_ERROR_FAILURE;
}
uint32_t trackToSeek = mHasVideo ? mVideoTrack : mAudioTrack;
int r = nestegg_track_seek(mContext, trackToSeek, aTarget * NS_PER_USEC);
uint64_t target = aTarget * NS_PER_USEC;
if (mSeekPreroll) {
target = std::max(static_cast<uint64_t>(aStartTime * NS_PER_USEC), target - mSeekPreroll);
}
int r = nestegg_track_seek(mContext, trackToSeek, target);
if (r != 0) {
return NS_ERROR_FAILURE;
}

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

@ -197,6 +197,7 @@ private:
nsAutoPtr<OpusParser> mOpusParser;
OpusMSDecoder *mOpusDecoder;
int mSkip; // Number of samples left to trim before playback.
uint64_t mSeekPreroll; // Number of nanoseconds that must be discarded after seeking.
#endif
// Queue of video and audio packets that have been read but not decoded. These

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

@ -322,7 +322,7 @@ nsXBLPrototypeHandler::ExecuteHandler(EventTarget* aTarget,
}
nsRefPtr<EventHandlerNonNull> handlerCallback =
new EventHandlerNonNull(bound);
new EventHandlerNonNull(bound, /* aIncumbentGlobal = */ nullptr);
nsEventHandler eventHandler(handlerCallback);

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

@ -46,11 +46,6 @@ ifeq ($(OS_ARCH),WINNT)
MODULE_OPTIMIZE_FLAGS = -O2
endif
# disable PGO for Sun Studio
ifdef SOLARIS_SUNPRO_CC
NO_PROFILE_GUIDED_OPTIMIZE = 1
endif
include $(topsrcdir)/config/rules.mk
# next line allows use of MOZ_OBJDIR in .mozconfig with older gcc on BeOS, maybe others

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

@ -62,3 +62,7 @@ if CONFIG['OS_TARGET'] == 'Android':
if CONFIG['OS_ARCH'] == 'WINNT' and CONFIG['MOZ_MEMORY']:
DEFINES['HAVE_MALLOC_USABLE_SIZE'] = True
DEFINES['SQLITE_WITHOUT_MSIZE'] = True
# disable PGO for Sun Studio
if CONFIG['SOLARIS_SUNPRO_CC']:
NO_PGO = True

191
dom/base/ScriptSettings.cpp Normal file
Просмотреть файл

@ -0,0 +1,191 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
// vim: ft=cpp tw=78 sw=2 et ts=2
/* 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 "mozilla/dom/ScriptSettings.h"
#include "mozilla/ThreadLocal.h"
#include "mozilla/Assertions.h"
#include "jsapi.h"
#include "xpcpublic.h"
#include "nsIGlobalObject.h"
#include "nsIScriptGlobalObject.h"
#include "nsIScriptContext.h"
#include "nsContentUtils.h"
#include "nsTArray.h"
namespace mozilla {
namespace dom {
class ScriptSettingsStack;
static mozilla::ThreadLocal<ScriptSettingsStack*> sScriptSettingsTLS;
ScriptSettingsStackEntry ScriptSettingsStackEntry::SystemSingleton;
class ScriptSettingsStack {
public:
static ScriptSettingsStack& Ref() {
return *sScriptSettingsTLS.get();
}
ScriptSettingsStack() {};
void Push(ScriptSettingsStackEntry* aSettings) {
// The bottom-most entry must always be a candidate entry point.
MOZ_ASSERT_IF(mStack.Length() == 0 || mStack.LastElement()->IsSystemSingleton(),
aSettings->mIsCandidateEntryPoint);
mStack.AppendElement(aSettings);
}
void PushSystem() {
mStack.AppendElement(&ScriptSettingsStackEntry::SystemSingleton);
}
void Pop() {
MOZ_ASSERT(mStack.Length() > 0);
mStack.RemoveElementAt(mStack.Length() - 1);
}
nsIGlobalObject* Incumbent() {
if (!mStack.Length()) {
return nullptr;
}
return mStack.LastElement()->mGlobalObject;
}
nsIGlobalObject* EntryPoint() {
if (!mStack.Length())
return nullptr;
for (int i = mStack.Length() - 1; i >= 0; --i) {
if (mStack[i]->mIsCandidateEntryPoint) {
return mStack[i]->mGlobalObject;
}
}
MOZ_ASSUME_UNREACHABLE("Non-empty stack should always have an entry point");
}
private:
// These pointers are caller-owned.
nsTArray<ScriptSettingsStackEntry*> mStack;
};
void
InitScriptSettings()
{
if (!sScriptSettingsTLS.initialized()) {
bool success = sScriptSettingsTLS.init();
if (!success) {
MOZ_CRASH();
}
}
ScriptSettingsStack* ptr = new ScriptSettingsStack();
sScriptSettingsTLS.set(ptr);
}
void DestroyScriptSettings()
{
ScriptSettingsStack* ptr = sScriptSettingsTLS.get();
MOZ_ASSERT(ptr);
sScriptSettingsTLS.set(nullptr);
delete ptr;
}
// Note: When we're ready to expose it, GetEntryGlobal will look similar to
// GetIncumbentGlobal below.
nsIGlobalObject*
GetIncumbentGlobal()
{
// We need the current JSContext in order to check the JS for
// scripted frames that may have appeared since anyone last
// manipulated the stack. If it's null, that means that there
// must be no entry point on the stack, and therefore no incumbent
// global either.
JSContext *cx = nsContentUtils::GetCurrentJSContextForThread();
if (!cx) {
MOZ_ASSERT(ScriptSettingsStack::Ref().EntryPoint() == nullptr);
return nullptr;
}
// See what the JS engine has to say. If we've got a scripted caller
// override in place, the JS engine will lie to us and pretend that
// there's nothing on the JS stack, which will cause us to check the
// incumbent script stack below.
JS::RootedScript script(cx);
if (JS_DescribeScriptedCaller(cx, &script, nullptr)) {
JS::RootedObject global(cx, JS_GetGlobalFromScript(script));
MOZ_ASSERT(global);
return xpc::GetNativeForGlobal(global);
}
// Ok, nothing from the JS engine. Let's use whatever's on the
// explicit stack.
return ScriptSettingsStack::Ref().Incumbent();
}
AutoEntryScript::AutoEntryScript(nsIGlobalObject* aGlobalObject,
bool aIsMainThread,
JSContext* aCx)
: mStack(ScriptSettingsStack::Ref())
, mEntry(aGlobalObject, /* aCandidate = */ true)
{
MOZ_ASSERT(aGlobalObject);
if (!aCx) {
// If the caller didn't provide a cx, hunt one down. This isn't exactly
// fast, but the callers that care about performance can pass an explicit
// cx for now. Eventually, the whole cx pushing thing will go away
// entirely.
MOZ_ASSERT(aIsMainThread, "cx is mandatory off-main-thread");
nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(aGlobalObject);
if (sgo && sgo->GetScriptContext()) {
aCx = sgo->GetScriptContext()->GetNativeContext();
}
if (!aCx) {
aCx = nsContentUtils::GetSafeJSContext();
}
}
if (aIsMainThread) {
mCxPusher.Push(aCx);
}
mAc.construct(aCx, aGlobalObject->GetGlobalJSObject());
mStack.Push(&mEntry);
}
AutoEntryScript::~AutoEntryScript()
{
MOZ_ASSERT(mStack.Incumbent() == mEntry.mGlobalObject);
mStack.Pop();
}
AutoIncumbentScript::AutoIncumbentScript(nsIGlobalObject* aGlobalObject)
: mStack(ScriptSettingsStack::Ref())
, mEntry(aGlobalObject, /* aCandidate = */ false)
, mCallerOverride(nsContentUtils::GetCurrentJSContextForThread())
{
mStack.Push(&mEntry);
}
AutoIncumbentScript::~AutoIncumbentScript()
{
MOZ_ASSERT(mStack.Incumbent() == mEntry.mGlobalObject);
mStack.Pop();
}
AutoSystemCaller::AutoSystemCaller(bool aIsMainThread)
: mStack(ScriptSettingsStack::Ref())
{
if (aIsMainThread) {
mCxPusher.PushNull();
}
mStack.PushSystem();
}
AutoSystemCaller::~AutoSystemCaller()
{
mStack.Pop();
}
} // namespace dom
} // namespace mozilla

115
dom/base/ScriptSettings.h Normal file
Просмотреть файл

@ -0,0 +1,115 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
// vim: ft=cpp tw=78 sw=2 et ts=2
/* 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/. */
/* Utilities for managing the script settings object stack defined in webapps */
#ifndef mozilla_dom_ScriptSettings_h
#define mozilla_dom_ScriptSettings_h
#include "nsCxPusher.h"
#include "MainThreadUtils.h"
#include "nsIGlobalObject.h"
#include "mozilla/Maybe.h"
class nsIGlobalObject;
namespace mozilla {
namespace dom {
/*
* System-wide setup/teardown routines. Init and Destroy should be invoked
* once each, at startup and shutdown (respectively).
*/
void InitScriptSettings();
void DestroyScriptSettings();
// Note: We don't yet expose GetEntryGlobal, because in order for it to be
// correct, we first need to replace a bunch of explicit cx pushing in the
// browser with AutoEntryScript. But GetIncumbentGlobal is simpler, because it
// can mostly be inferred from the JS stack.
nsIGlobalObject* GetIncumbentGlobal();
class ScriptSettingsStack;
struct ScriptSettingsStackEntry {
nsCOMPtr<nsIGlobalObject> mGlobalObject;
bool mIsCandidateEntryPoint;
ScriptSettingsStackEntry(nsIGlobalObject *aGlobal, bool aCandidate)
: mGlobalObject(aGlobal)
, mIsCandidateEntryPoint(aCandidate)
{
MOZ_ASSERT(mGlobalObject);
MOZ_ASSERT(mGlobalObject->GetGlobalJSObject(),
"Must have an actual JS global for the duration on the stack");
MOZ_ASSERT(JS_IsGlobalObject(mGlobalObject->GetGlobalJSObject()),
"No outer windows allowed");
}
~ScriptSettingsStackEntry() {
// We must have an actual JS global for the entire time this is on the stack.
MOZ_ASSERT_IF(mGlobalObject, mGlobalObject->GetGlobalJSObject());
}
bool IsSystemSingleton() { return this == &SystemSingleton; }
static ScriptSettingsStackEntry SystemSingleton;
private:
ScriptSettingsStackEntry() : mGlobalObject(nullptr)
, mIsCandidateEntryPoint(true)
{}
};
/*
* A class that represents a new script entry point.
*/
class AutoEntryScript {
public:
AutoEntryScript(nsIGlobalObject* aGlobalObject,
bool aIsMainThread = NS_IsMainThread(),
// Note: aCx is mandatory off-main-thread.
JSContext* aCx = nullptr);
~AutoEntryScript();
private:
dom::ScriptSettingsStack& mStack;
dom::ScriptSettingsStackEntry mEntry;
nsCxPusher mCxPusher;
mozilla::Maybe<JSAutoCompartment> mAc; // This can de-Maybe-fy when mCxPusher
// goes away.
};
/*
* A class that can be used to force a particular incumbent script on the stack.
*/
class AutoIncumbentScript {
public:
AutoIncumbentScript(nsIGlobalObject* aGlobalObject);
~AutoIncumbentScript();
private:
dom::ScriptSettingsStack& mStack;
dom::ScriptSettingsStackEntry mEntry;
JS::AutoHideScriptedCaller mCallerOverride;
};
/*
* A class used for C++ to indicate that existing entry and incumbent scripts
* should not apply to anything in scope, and that callees should act as if
* they were invoked "from C++".
*/
class AutoSystemCaller {
public:
AutoSystemCaller(bool aIsMainThread = NS_IsMainThread());
~AutoSystemCaller();
private:
dom::ScriptSettingsStack& mStack;
nsCxPusher mCxPusher;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_ScriptSettings_h

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

@ -59,6 +59,7 @@ EXPORTS.mozilla.dom += [
'MessagePortList.h',
'Navigator.h',
'ScreenOrientation.h',
'ScriptSettings.h',
'StructuredCloneTags.h',
'URL.h',
]
@ -94,6 +95,7 @@ UNIFIED_SOURCES += [
'nsWindowMemoryReporter.cpp',
'nsWindowRoot.cpp',
'nsWrapperCache.cpp',
'ScriptSettings.cpp',
'URL.cpp',
'WindowNamedPropertiesHandler.cpp',
]

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

@ -93,6 +93,7 @@ using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::layers;
using namespace mozilla::widget;
using namespace mozilla::gfx;
class gfxContext;
@ -1385,8 +1386,8 @@ nsDOMWindowUtils::NodesFromRect(float aX, float aY,
aIgnoreRootScrollFrame, aFlushLayout, aReturn);
}
static already_AddRefed<gfxImageSurface>
CanvasToImageSurface(nsIDOMHTMLCanvasElement* aCanvas)
static TemporaryRef<DataSourceSurface>
CanvasToDataSourceSurface(nsIDOMHTMLCanvasElement* aCanvas)
{
nsCOMPtr<nsINode> node = do_QueryInterface(aCanvas);
if (!node) {
@ -1397,9 +1398,8 @@ CanvasToImageSurface(nsIDOMHTMLCanvasElement* aCanvas)
"An nsINode that implements nsIDOMHTMLCanvasElement should "
"be an element.");
nsLayoutUtils::SurfaceFromElementResult result =
nsLayoutUtils::SurfaceFromElement(node->AsElement(),
nsLayoutUtils::SFE_WANT_IMAGE_SURFACE);
return result.mSurface.forget().downcast<gfxImageSurface>();
nsLayoutUtils::SurfaceFromElement(node->AsElement());
return result.mSourceSurface->GetDataSurface();
}
NS_IMETHODIMP
@ -1417,8 +1417,8 @@ nsDOMWindowUtils::CompareCanvases(nsIDOMHTMLCanvasElement *aCanvas1,
retVal == nullptr)
return NS_ERROR_FAILURE;
nsRefPtr<gfxImageSurface> img1 = CanvasToImageSurface(aCanvas1);
nsRefPtr<gfxImageSurface> img2 = CanvasToImageSurface(aCanvas2);
RefPtr<DataSourceSurface> img1 = CanvasToDataSourceSurface(aCanvas1);
RefPtr<DataSourceSurface> img2 = CanvasToDataSourceSurface(aCanvas2);
if (img1 == nullptr || img2 == nullptr ||
img1->GetSize() != img2->GetSize() ||
@ -1426,12 +1426,12 @@ nsDOMWindowUtils::CompareCanvases(nsIDOMHTMLCanvasElement *aCanvas1,
return NS_ERROR_FAILURE;
int v;
gfxIntSize size = img1->GetSize();
IntSize size = img1->GetSize();
uint32_t stride = img1->Stride();
// we can optimize for the common all-pass case
if (stride == (uint32_t) size.width * 4) {
v = memcmp(img1->Data(), img2->Data(), size.width * size.height * 4);
v = memcmp(img1->GetData(), img2->GetData(), size.width * size.height * 4);
if (v == 0) {
if (aMaxDifference)
*aMaxDifference = 0;
@ -1444,8 +1444,8 @@ nsDOMWindowUtils::CompareCanvases(nsIDOMHTMLCanvasElement *aCanvas1,
uint32_t different = 0;
for (int j = 0; j < size.height; j++) {
unsigned char *p1 = img1->Data() + j*stride;
unsigned char *p2 = img2->Data() + j*stride;
unsigned char *p1 = img1->GetData() + j*stride;
unsigned char *p2 = img2->GetData() + j*stride;
v = memcmp(p1, p2, stride);
if (v) {

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

@ -43,6 +43,7 @@
#include "nsReadableUtils.h"
#include "nsDOMClassInfo.h"
#include "nsJSEnvironment.h"
#include "ScriptSettings.h"
#include "mozilla/Preferences.h"
#include "mozilla/Likely.h"
@ -209,6 +210,7 @@
#include "mozilla/dom/WindowBinding.h"
#include "nsITabChild.h"
#include "nsIDOMMediaQueryList.h"
#include "mozilla/dom/ScriptSettings.h"
#ifdef MOZ_WEBSPEECH
#include "mozilla/dom/SpeechSynthesis.h"
@ -4944,8 +4946,9 @@ nsGlobalWindow::RequestAnimationFrame(const JS::Value& aCallback,
return NS_ERROR_INVALID_ARG;
}
JS::Rooted<JSObject*> callbackObj(cx, &aCallback.toObject());
nsRefPtr<FrameRequestCallback> callback =
new FrameRequestCallback(&aCallback.toObject());
new FrameRequestCallback(callbackObj, GetIncumbentGlobal());
ErrorResult rv;
*aHandle = RequestAnimationFrame(*callback, rv);
@ -11211,18 +11214,18 @@ nsGlobalWindow::OpenInternal(const nsAString& aUrl, const nsAString& aName,
aDialog, aNavigate, argv,
getter_AddRefs(domReturn));
} else {
// Push a null JSContext here so that the window watcher won't screw us
// Force a system caller here so that the window watcher won't screw us
// up. We do NOT want this case looking at the JS context on the stack
// when searching. Compare comments on
// nsIDOMWindow::OpenWindow and nsIWindowWatcher::OpenWindow.
// Note: Because nsWindowWatcher is so broken, it's actually important
// that we don't push a null cx here, because that screws it up when it
// tries to compute the caller principal to associate with dialog
// that we don't force a system caller here, because that screws it up
// when it tries to compute the caller principal to associate with dialog
// arguments. That whole setup just really needs to be rewritten. :-(
nsCxPusher pusher;
Maybe<AutoSystemCaller> asc;
if (!aContentModal) {
pusher.PushNull();
asc.construct();
}
@ -13229,10 +13232,10 @@ nsGlobalWindow::DisableNetworkEvent(uint32_t aType)
NS_IMETHODIMP nsGlobalWindow::SetOn##name_(JSContext *cx, \
const JS::Value &v) { \
nsRefPtr<EventHandlerNonNull> handler; \
JSObject *callable; \
JS::Rooted<JSObject*> callable(cx); \
if (v.isObject() && \
JS_ObjectIsCallable(cx, callable = &v.toObject())) { \
handler = new EventHandlerNonNull(callable); \
handler = new EventHandlerNonNull(callable, GetIncumbentGlobal()); \
} \
SetOn##name_(handler); \
return NS_OK; \
@ -13259,10 +13262,10 @@ nsGlobalWindow::DisableNetworkEvent(uint32_t aType)
} \
\
nsRefPtr<OnErrorEventHandlerNonNull> handler; \
JSObject *callable; \
JS::Rooted<JSObject*> callable(cx); \
if (v.isObject() && \
JS_ObjectIsCallable(cx, callable = &v.toObject())) { \
handler = new OnErrorEventHandlerNonNull(callable); \
handler = new OnErrorEventHandlerNonNull(callable, GetIncumbentGlobal()); \
} \
elm->SetEventHandler(handler); \
return NS_OK; \
@ -13290,10 +13293,10 @@ nsGlobalWindow::DisableNetworkEvent(uint32_t aType)
} \
\
nsRefPtr<OnBeforeUnloadEventHandlerNonNull> handler; \
JSObject *callable; \
JS::Rooted<JSObject*> callable(cx); \
if (v.isObject() && \
JS_ObjectIsCallable(cx, callable = &v.toObject())) { \
handler = new OnBeforeUnloadEventHandlerNonNull(callable); \
handler = new OnBeforeUnloadEventHandlerNonNull(callable, GetIncumbentGlobal()); \
} \
elm->SetEventHandler(handler); \
return NS_OK; \

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

@ -360,7 +360,7 @@ nsJSScriptTimeoutHandler::Init(nsGlobalWindow *aWindow, bool *aIsInterval,
mozilla::HoldJSObjects(this);
mFunction = new Function(funobj);
mFunction = new Function(funobj, GetIncumbentGlobal());
// Create our arg array. argc is the number of arguments passed
// to setTimeout or setInterval; the first two are our callback

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

@ -27,6 +27,7 @@
#include "nsPrintfCString.h"
#include "prprf.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/dom/DOMError.h"
#include "mozilla/dom/DOMErrorBinding.h"
#include "mozilla/dom/HTMLObjectElement.h"
@ -2015,12 +2016,12 @@ ConstructJSImplementation(JSContext* aCx, const char* aContractId,
return nullptr;
}
// Make sure to have nothing on the JS context stack while creating and
// Make sure to divorce ourselves from the calling JS while creating and
// initializing the object, so exceptions from that will get reported
// properly, since those are never exceptions that a spec wants to be thrown.
{ // Scope for the nsCxPusher
nsCxPusher pusher;
pusher.PushNull();
{
AutoSystemCaller asc;
// Get the XPCOM component containing the JS implementation.
nsCOMPtr<nsISupports> implISupports = do_CreateInstance(aContractId);
if (!implISupports) {

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

@ -25,8 +25,9 @@ namespace dom {
class CallbackFunction : public CallbackObject
{
public:
explicit CallbackFunction(JSObject* aCallable)
: CallbackObject(aCallable)
explicit CallbackFunction(JS::Handle<JSObject*> aCallable,
nsIGlobalObject* aIncumbentGlobal)
: CallbackObject(aCallable, aIncumbentGlobal)
{
MOZ_ASSERT(JS_ObjectIsCallable(nullptr, mCallback));
}

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

@ -24,8 +24,9 @@ namespace dom {
class CallbackInterface : public CallbackObject
{
public:
explicit CallbackInterface(JSObject* aCallback)
: CallbackObject(aCallback)
explicit CallbackInterface(JS::Handle<JSObject*> aCallback,
nsIGlobalObject *aIncumbentGlobal)
: CallbackObject(aCallback, aIncumbentGlobal)
{
}

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

@ -19,6 +19,7 @@
#include "xpcprivate.h"
#include "WorkerPrivate.h"
#include "nsGlobalWindow.h"
#include "WorkerScope.h"
namespace mozilla {
namespace dom {
@ -35,15 +36,17 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(CallbackObject)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(CallbackObject)
tmp->DropCallback();
NS_IMPL_CYCLE_COLLECTION_UNLINK(mIncumbentGlobal)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(CallbackObject)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIncumbentGlobal)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(CallbackObject)
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mCallback)
NS_IMPL_CYCLE_COLLECTION_TRACE_END
CallbackObject::CallSetup::CallSetup(JS::Handle<JSObject*> aCallback,
CallbackObject::CallSetup::CallSetup(CallbackObject* aCallback,
ErrorResult& aRv,
ExceptionHandling aExceptionHandling,
JSCompartment* aCompartment)
@ -63,8 +66,9 @@ CallbackObject::CallSetup::CallSetup(JS::Handle<JSObject*> aCallback,
// callable.
// First, find the real underlying callback.
JSObject* realCallback = js::UncheckedUnwrap(aCallback);
JSObject* realCallback = js::UncheckedUnwrap(aCallback->CallbackPreserveColor());
JSContext* cx = nullptr;
nsIGlobalObject* globalObject = nullptr;
if (mIsMainThread) {
// Now get the global and JSContext for this callback.
@ -85,18 +89,33 @@ CallbackObject::CallSetup::CallSetup(JS::Handle<JSObject*> aCallback,
// This happens - Removing it causes
// test_bug293235.xul to go orange.
: nsContentUtils::GetSafeJSContext();
globalObject = win;
} else {
// No DOM Window. Use the SafeJSContext.
// No DOM Window. Store the global and use the SafeJSContext.
JSObject* glob = js::GetGlobalForObjectCrossCompartment(realCallback);
globalObject = xpc::GetNativeForGlobal(glob);
MOZ_ASSERT(globalObject);
cx = nsContentUtils::GetSafeJSContext();
}
// Make sure our JSContext is pushed on the stack.
mCxPusher.Push(cx);
} else {
cx = workers::GetCurrentThreadJSContext();
globalObject = workers::GetCurrentThreadWorkerPrivate()->GlobalScope();
}
// Unmark the callable, and stick it in a Rooted before it can go gray again.
// Bail out if there's no useful global. This seems to happen intermittently
// on gaia-ui tests, probably because nsInProcessTabChildGlobal is returning
// null in some kind of teardown state.
if (!globalObject->GetGlobalJSObject()) {
return;
}
mAutoEntryScript.construct(globalObject, mIsMainThread, cx);
if (aCallback->IncumbentGlobalOrNull()) {
mAutoIncumbentScript.construct(aCallback->IncumbentGlobalOrNull());
}
// Unmark the callable (by invoking Callback() and not the CallbackPreserveColor()
// variant), and stick it in a Rooted before it can go gray again.
// Nothing before us in this function can trigger a CC, so it's safe to wait
// until here it do the unmark. This allows us to order the following two
// operations _after_ the Push() above, which lets us take advantage of the
@ -104,15 +123,14 @@ CallbackObject::CallSetup::CallSetup(JS::Handle<JSObject*> aCallback,
//
// We can do this even though we're not in the right compartment yet, because
// Rooted<> does not care about compartments.
JS::ExposeObjectToActiveJS(aCallback);
mRootedCallable.construct(cx, aCallback);
mRootedCallable.construct(cx, aCallback->Callback());
if (mIsMainThread) {
// Check that it's ok to run this callback at all.
// Make sure to unwrap aCallback before passing it in to get the global of
// the callback object, not the wrapper.
// Make sure to use realCallback to get the global of the callback object,
// not the wrapper.
bool allowed = nsContentUtils::GetSecurityManager()->
ScriptAllowed(js::GetGlobalForObjectCrossCompartment(js::UncheckedUnwrap(aCallback)));
ScriptAllowed(js::GetGlobalForObjectCrossCompartment(realCallback));
if (!allowed) {
return;
@ -120,7 +138,11 @@ CallbackObject::CallSetup::CallSetup(JS::Handle<JSObject*> aCallback,
}
// Enter the compartment of our callback, so we can actually work with it.
mAc.construct(cx, aCallback);
//
// Note that if the callback is a wrapper, this will not be the same
// compartment that we ended up in with mAutoEntryScript above, because the
// entry point is based off of the unwrapped callback (realCallback).
mAc.construct(cx, mRootedCallable.ref());
// And now we're ready to go.
mCx = cx;
@ -194,17 +216,11 @@ CallbackObject::CallSetup::~CallSetup()
// But be careful: it might not have been constructed at all!
mAc.destroyIfConstructed();
// XXXbz For that matter why do we need to manually call ScriptEvaluated at
// all? nsCxPusher::Pop will do that nowadays if !mScriptIsRunning, so the
// concerns from bug 295983 don't seem relevant anymore. Do we want to make
// sure it's still called when !mScriptIsRunning? I guess play it safe for
// now and do what CallEventHandler did, which is call always.
// Popping an nsCxPusher is safe even if it never got pushed.
mCxPusher.Pop();
mAutoIncumbentScript.destroyIfConstructed();
mAutoEntryScript.destroyIfConstructed();
// It is important that this is the last thing we do, after leaving the
// compartment and popping the context.
// compartment and undoing all our entry/incumbent script changes
if (mIsMainThread) {
nsContentUtils::LeaveMicroTask();
}

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

@ -24,8 +24,8 @@
#include "mozilla/Assertions.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/HoldDropJSObjects.h"
#include "mozilla/dom/ScriptSettings.h"
#include "nsContentUtils.h"
#include "nsCxPusher.h"
#include "nsWrapperCache.h"
#include "nsJSEnvironment.h"
#include "xpcpublic.h"
@ -45,9 +45,13 @@ public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(CallbackObject)
explicit CallbackObject(JSObject* aCallback)
// The caller may pass a global object which will act as an override for the
// incumbent script settings object when the callback is invoked (overriding
// the entry point computed from aCallback). If no override is required, the
// caller should pass null.
explicit CallbackObject(JS::Handle<JSObject*> aCallback, nsIGlobalObject *aIncumbentGlobal)
{
Init(aCallback);
Init(aCallback, aIncumbentGlobal);
}
virtual ~CallbackObject()
@ -76,6 +80,11 @@ public:
return JS::Handle<JSObject*>::fromMarkedLocation(mCallback.address());
}
nsIGlobalObject* IncumbentGlobalOrNull() const
{
return mIncumbentGlobal;
}
enum ExceptionHandling {
// Report any exception and don't throw it to the caller code.
eReportExceptions,
@ -90,17 +99,19 @@ public:
protected:
explicit CallbackObject(CallbackObject* aCallbackObject)
{
Init(aCallbackObject->mCallback);
Init(aCallbackObject->mCallback, aCallbackObject->mIncumbentGlobal);
}
private:
inline void Init(JSObject* aCallback)
inline void Init(JSObject* aCallback, nsIGlobalObject* aIncumbentGlobal)
{
MOZ_ASSERT(aCallback && !mCallback);
// Set mCallback before we hold, on the off chance that a GC could somehow
// happen in there... (which would be pretty odd, granted).
mCallback = aCallback;
mozilla::HoldJSObjects(this);
mIncumbentGlobal = aIncumbentGlobal;
}
CallbackObject(const CallbackObject&) MOZ_DELETE;
@ -116,6 +127,7 @@ protected:
}
JS::Heap<JSObject*> mCallback;
nsCOMPtr<nsIGlobalObject> mIncumbentGlobal;
class MOZ_STACK_CLASS CallSetup
{
@ -128,7 +140,7 @@ protected:
public:
// If aExceptionHandling == eRethrowContentExceptions then aCompartment
// needs to be set to the caller's compartment.
CallSetup(JS::Handle<JSObject*> aCallable, ErrorResult& aRv,
CallSetup(CallbackObject* aCallback, ErrorResult& aRv,
ExceptionHandling aExceptionHandling,
JSCompartment* aCompartment = nullptr);
~CallSetup();
@ -152,17 +164,17 @@ protected:
JSCompartment* mCompartment;
// And now members whose construction/destruction order we need to control.
nsCxPusher mCxPusher;
Maybe<AutoEntryScript> mAutoEntryScript;
Maybe<AutoIncumbentScript> mAutoIncumbentScript;
// Constructed the rooter within the scope of mCxPusher above, so that it's
// always within a request during its lifetime.
Maybe<JS::Rooted<JSObject*> > mRootedCallable;
// Can't construct a JSAutoCompartment without a JSContext either. Also,
// Put mAc after mCxPusher so that we exit the compartment before we pop the
// JSContext. Though in practice we'll often manually order those two
// things.
// Put mAc after mAutoEntryScript so that we exit the compartment before
// we pop the JSContext. Though in practice we'll often manually order
// those two things.
Maybe<JSAutoCompartment> mAc;
// An ErrorResult to possibly re-throw exceptions on and whether
@ -336,28 +348,7 @@ public:
nsRefPtr<WebIDLCallbackT> callback = GetWebIDLCallback();
return callback.forget();
}
XPCOMCallbackT* callback = GetXPCOMCallback();
if (!callback) {
return nullptr;
}
nsCOMPtr<nsIXPConnectWrappedJS> wrappedJS = do_QueryInterface(callback);
if (!wrappedJS) {
return nullptr;
}
AutoSafeJSContext cx;
JS::Rooted<JSObject*> obj(cx, wrappedJS->GetJSObject());
if (!obj) {
return nullptr;
}
JSAutoCompartment ac(cx, obj);
nsRefPtr<WebIDLCallbackT> newCallback = new WebIDLCallbackT(obj);
return newCallback.forget();
return nullptr;
}
private:

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

@ -3396,7 +3396,10 @@ for (uint32_t i = 0; i < length; ++i) {
else:
declType = CGGeneric("OwningNonNull<%s>" % name)
conversion = (
"${declName} = new %s(&${val}.toObject());\n" % name)
"{ // Scope for tempRoot\n"
" JS::Rooted<JSObject*> tempRoot(cx, &${val}.toObject());\n"
" ${declName} = new %s(tempRoot, mozilla::dom::GetIncumbentGlobal());\n"
"}" % name)
template = wrapObjectTemplate(conversion, type,
"${declName} = nullptr",
@ -3729,7 +3732,10 @@ for (uint32_t i = 0; i < length; ++i) {
else:
declType = CGGeneric("OwningNonNull<%s>" % name)
conversion = (
" ${declName} = new %s(&${val}.toObject());\n" % name)
"{ // Scope for tempRoot\n"
" JS::Rooted<JSObject*> tempRoot(cx, &${val}.toObject());\n"
" ${declName} = new %s(tempRoot, mozilla::dom::GetIncumbentGlobal());\n"
"}\n" % name)
if allowTreatNonCallableAsNull and type.treatNonCallableAsNull():
haveCallable = "JS_ObjectIsCallable(cx, &${val}.toObject())"
@ -10549,7 +10555,7 @@ class CGJSImplClass(CGBindingImplClass):
decorators = "MOZ_FINAL"
destructor = None
baseConstructors=["mImpl(new %s(aJSImplObject))" % jsImplName(descriptor.name),
baseConstructors=["mImpl(new %s(aJSImplObject, /* aIncumbentGlobal = */ nullptr))" % jsImplName(descriptor.name),
"mParent(aParent)"]
parentInterface = descriptor.interface.parent
while parentInterface:
@ -10676,12 +10682,12 @@ class CGCallback(CGClass):
def getConstructors(self):
return [ClassConstructor(
[Argument("JSObject*", "aCallback")],
[Argument("JS::Handle<JSObject*>", "aCallback"), Argument("nsIGlobalObject*", "aIncumbentGlobal")],
bodyInHeader=True,
visibility="public",
explicit=True,
baseConstructors=[
"%s(aCallback)" % self.baseName
"%s(aCallback, aIncumbentGlobal)" % self.baseName,
])]
def getMethodImpls(self, method):
@ -10706,7 +10712,7 @@ class CGCallback(CGClass):
argsWithoutThis = list(args)
args.insert(0, Argument("const T&", "thisObj"))
setupCall = ("CallSetup s(CallbackPreserveColor(), aRv, aExceptionHandling);\n"
setupCall = ("CallSetup s(this, aRv, aExceptionHandling);\n"
"if (!s.GetContext()) {\n"
" aRv.Throw(NS_ERROR_UNEXPECTED);\n"
" return${errorReturn};\n"
@ -10996,7 +11002,7 @@ class CallbackMember(CGNativeMember):
if self.needThisHandling:
# It's been done for us already
return ""
callSetup = "CallSetup s(CallbackPreserveColor(), aRv"
callSetup = "CallSetup s(this, aRv"
if self.rethrowContentException:
# getArgs doesn't add the aExceptionHandling argument but does add
# aCompartment for us.

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

@ -9,7 +9,8 @@
BEGIN_BLUETOOTH_NAMESPACE
int
AppendHeaderName(uint8_t* aRetBuf, const char* aName, int aLength)
AppendHeaderName(uint8_t* aRetBuf, int aBufferSize, const char* aName,
int aLength)
{
int headerLength = aLength + 3;
@ -17,13 +18,15 @@ AppendHeaderName(uint8_t* aRetBuf, const char* aName, int aLength)
aRetBuf[1] = (headerLength & 0xFF00) >> 8;
aRetBuf[2] = headerLength & 0x00FF;
memcpy(&aRetBuf[3], aName, aLength);
memcpy(&aRetBuf[3], aName, (aLength < aBufferSize - 3)? aLength
: aBufferSize - 3);
return headerLength;
}
int
AppendHeaderBody(uint8_t* aRetBuf, uint8_t* aData, int aLength)
AppendHeaderBody(uint8_t* aRetBuf, int aBufferSize, const uint8_t* aData,
int aLength)
{
int headerLength = aLength + 3;
@ -31,7 +34,8 @@ AppendHeaderBody(uint8_t* aRetBuf, uint8_t* aData, int aLength)
aRetBuf[1] = (headerLength & 0xFF00) >> 8;
aRetBuf[2] = headerLength & 0x00FF;
memcpy(&aRetBuf[3], aData, aLength);
memcpy(&aRetBuf[3], aData, (aLength < aBufferSize - 3)? aLength
: aBufferSize - 3);
return headerLength;
}

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