Merge from mozilla-central.

--HG--
rename : gfx/thebes/GLContext.cpp => gfx/gl/GLContext.cpp
rename : gfx/thebes/GLContext.h => gfx/gl/GLContext.h
rename : gfx/thebes/GLContextProviderCGL.mm => gfx/gl/GLContextProviderCGL.mm
rename : gfx/thebes/GLContextProviderEGL.cpp => gfx/gl/GLContextProviderEGL.cpp
rename : gfx/thebes/GLContextProviderGLX.cpp => gfx/gl/GLContextProviderGLX.cpp
rename : gfx/thebes/GLContextProviderOSMesa.cpp => gfx/gl/GLContextProviderOSMesa.cpp
rename : gfx/thebes/GLContextProviderWGL.cpp => gfx/gl/GLContextProviderWGL.cpp
rename : gfx/thebes/GLXLibrary.h => gfx/gl/GLXLibrary.h
rename : gfx/thebes/WGLLibrary.h => gfx/gl/WGLLibrary.h
rename : layout/svg/base/src/nsSVGLeafFrame.cpp => layout/svg/base/src/SVGFELeafFrame.cpp
This commit is contained in:
David Anderson 2011-11-23 15:19:11 -05:00
commit 902c694467
804 changed files with 17609 additions and 74123 deletions

View File

@ -1587,6 +1587,13 @@ nsAccessibleWrap::FirePlatformEvent(AccEvent* aEvent)
// Fire MSAA event for client area window.
NotifyWinEvent(winEvent, hWnd, OBJID_CLIENT, childID);
// JAWS announces collapsed combobox navigation based on focus events.
if (eventType == nsIAccessibleEvent::EVENT_SELECTION &&
accessible->Role() == nsIAccessibleRole::ROLE_COMBOBOX_OPTION &&
nsWinUtils::IsWindowEmulationFor(kJAWSModuleHandle)) {
NotifyWinEvent(EVENT_OBJECT_FOCUS, hWnd, OBJID_CLIENT, childID);
}
return NS_OK;
}

View File

@ -61,30 +61,6 @@ DEFINES += -DAB_CD=$(AB_CD)
APP_VERSION = $(shell cat $(srcdir)/../config/version.txt)
DEFINES += -DAPP_VERSION="$(APP_VERSION)"
DIST_FILES = application.ini
GRE_MILESTONE = $(shell $(PYTHON) $(topsrcdir)/config/printconfigsetting.py $(LIBXUL_DIST)/bin/platform.ini Build Milestone)
GRE_BUILDID = $(shell $(PYTHON) $(topsrcdir)/config/printconfigsetting.py $(LIBXUL_DIST)/bin/platform.ini Build BuildID)
DEFINES += -DGRE_MILESTONE=$(GRE_MILESTONE) -DGRE_BUILDID=$(GRE_BUILDID)
MOZ_SOURCE_STAMP ?= $(shell hg -R $(topsrcdir) parent --template="{node|short}\n" 2>/dev/null)
ifdef MOZ_SOURCE_STAMP
DEFINES += -DMOZ_SOURCE_STAMP="$(MOZ_SOURCE_STAMP)"
endif
SOURCE_REPO := $(shell hg -R $(topsrcdir) showconfig paths.default 2>/dev/null | sed -e "s/^ssh:/http:/")
ifdef SOURCE_REPO
DEFINES += -DMOZ_SOURCE_REPO="$(SOURCE_REPO)"
endif
DEFINES += -DMOZ_APP_BASENAME="$(MOZ_APP_BASENAME)" \
-DMOZ_APP_VENDOR="$(MOZ_APP_VENDOR)"
ifdef MOZ_APP_PROFILE
DEFINES += -DMOZ_APP_PROFILE="$(MOZ_APP_PROFILE)"
endif
ifdef LIBXUL_SDK
include $(topsrcdir)/config/rules.mk
else
@ -97,6 +73,7 @@ CPPSRCS = nsBrowserApp.cpp
LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/xre
LOCAL_INCLUDES += -I$(topsrcdir)/xpcom/base
LOCAL_INCLUDES += -I$(topsrcdir)/xpcom/build
LOCAL_INCLUDES += -I$(DEPTH)/build
DEFINES += -DXPCOM_GLUE
STL_FLAGS=
@ -187,10 +164,6 @@ endif # LIBXUL_SDK
DEFINES += -DFIREFOX_ICO=\"$(DIST)/branding/firefox.ico\" -DDOCUMENT_ICO=\"$(DIST)/branding/document.ico\"
ifdef MOZILLA_OFFICIAL
DEFINES += -DMOZILLA_OFFICIAL
endif
ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
libs::
$(INSTALL) $(IFLAGS1) $(DIST)/branding/mozicon128.png $(DIST)/bin/icons
@ -228,7 +201,7 @@ else
APPFILES = MacOS
endif
libs repackage:: $(PROGRAM) application.ini
libs repackage:: $(PROGRAM)
$(MKDIR) -p $(DIST)/$(APP_NAME).app/Contents/MacOS
rsync -a --exclude CVS --exclude "*.in" $(srcdir)/macbuild/Contents $(DIST)/$(APP_NAME).app --exclude English.lproj
$(MKDIR) -p $(DIST)/$(APP_NAME).app/Contents/Resources/$(AB).lproj

View File

@ -36,8 +36,8 @@
*
* ***** END LICENSE BLOCK ***** */
#include "application.ini.h"
#include "nsXPCOMGlue.h"
#include "nsXULAppAPI.h"
#if defined(XP_WIN)
#include <windows.h>
#include <stdlib.h>
@ -140,20 +140,7 @@ static const nsDynamicFunctionLoad kXULFuncs[] = {
static int do_main(const char *exePath, int argc, char* argv[])
{
nsCOMPtr<nsILocalFile> appini;
#ifdef XP_WIN
// exePath comes from mozilla::BinaryPath::Get, which returns a UTF-8
// encoded path, so it is safe to convert it
nsresult rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(exePath), false,
getter_AddRefs(appini));
#else
nsresult rv = NS_NewNativeLocalFile(nsDependentCString(exePath), false,
getter_AddRefs(appini));
#endif
if (NS_FAILED(rv)) {
return 255;
}
appini->SetNativeLeafName(NS_LITERAL_CSTRING("application.ini"));
nsresult rv;
// Allow firefox.exe to launch XULRunner apps via -app <application.ini>
// Note that -app must be the *first* argument.
@ -188,15 +175,32 @@ static int do_main(const char *exePath, int argc, char* argv[])
argc -= 2;
}
nsXREAppData *appData;
rv = XRE_CreateAppData(appini, &appData);
if (NS_FAILED(rv)) {
Output("Couldn't read application.ini");
return 255;
int result;
if (appini) {
nsXREAppData *appData;
rv = XRE_CreateAppData(appini, &appData);
if (NS_FAILED(rv)) {
Output("Couldn't read application.ini");
return 255;
}
result = XRE_main(argc, argv, appData);
XRE_FreeAppData(appData);
} else {
#ifdef XP_WIN
// exePath comes from mozilla::BinaryPath::Get, which returns a UTF-8
// encoded path, so it is safe to convert it
rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(exePath), PR_FALSE,
getter_AddRefs(appini));
#else
rv = NS_NewNativeLocalFile(nsDependentCString(exePath), PR_FALSE,
getter_AddRefs(appini));
#endif
if (NS_FAILED(rv)) {
return 255;
}
result = XRE_main(argc, argv, &sAppData);
}
int result = XRE_main(argc, argv, appData);
XRE_FreeAppData(appData);
return result;
}
@ -240,6 +244,8 @@ int main(int argc, char* argv[])
Output("Couldn't load XPCOM.\n");
return 255;
}
// Reset exePath so that it is the directory name and not the xpcom dll name
*lastSlash = 0;
rv = XPCOMGlueLoadXULFunctions(kXULFuncs);
if (NS_FAILED(rv)) {

View File

@ -3931,14 +3931,13 @@ var FullScreen = {
// full-screen. Only add listeners and show warning etc when the event we
// receive is targeted at the chrome document, i.e. only once every time
// we enter DOM full-screen mode.
let targetDoc = event.target.ownerDocument ? event.target.ownerDocument : event.target;
if (targetDoc != document) {
if (event.target != document) {
// However, if we receive a "mozfullscreenchange" event for a document
// which is not a subdocument of the currently selected tab, we know that
// we've switched tabs since the request to enter full-screen was made,
// so we should exit full-screen since the "full-screen document" isn't
// acutally visible.
if (targetDoc.defaultView.top != gBrowser.contentWindow) {
if (event.target.defaultView.top != gBrowser.contentWindow) {
document.mozCancelFullScreen();
}
return;

View File

@ -1,8 +1,8 @@
ac_add_options --enable-debug
ac_add_options --enable-trace-malloc
CC=/tools/gcc-4.5/bin/gcc
CXX=/tools/gcc-4.5/bin/g++
CC=/tools/gcc-4.5-0moz2/bin/gcc
CXX=/tools/gcc-4.5-0moz2/bin/g++
# Avoid dependency on libstdc++ 4.5
ac_add_options --enable-stdcxx-compat

View File

@ -3,5 +3,5 @@ ac_add_options --enable-official-branding
ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
ac_add_options --enable-update-packaging
CC=/tools/gcc-4.3.3/installed/bin/gcc
CXX=/tools/gcc-4.3.3/installed/bin/g++
CC=/tools/gcc-4.5-0moz2/bin/gcc
CXX=/tools/gcc-4.5-0moz2/bin/g++

View File

@ -5,8 +5,8 @@ ac_add_options --enable-codesighs
# Nightlies only since this has a cost in performance
ac_add_options --enable-js-diagnostics
CC=/tools/gcc-4.5/bin/gcc
CXX=/tools/gcc-4.5/bin/g++
CC=/tools/gcc-4.5-0moz2/bin/gcc
CXX=/tools/gcc-4.5-0moz2/bin/g++
# Avoid dependency on libstdc++ 4.5
ac_add_options --enable-stdcxx-compat

View File

@ -1,8 +1,8 @@
ac_add_options --enable-update-packaging
ac_add_options --enable-codesighs
CC=/tools/gcc-4.5/bin/gcc
CXX=/tools/gcc-4.5/bin/g++
CC=/tools/gcc-4.5-0moz2/bin/gcc
CXX=/tools/gcc-4.5-0moz2/bin/g++
# Avoid dependency on libstdc++ 4.5
ac_add_options --enable-stdcxx-compat

View File

@ -2,8 +2,8 @@ ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
ac_add_options --enable-update-packaging
ac_add_options --enable-official-branding
CC=/tools/gcc-4.5/bin/gcc
CXX=/tools/gcc-4.5/bin/g++
CC=/tools/gcc-4.5-0moz2/bin/gcc
CXX=/tools/gcc-4.5-0moz2/bin/g++
# Avoid dependency on libstdc++ 4.5
ac_add_options --enable-stdcxx-compat

View File

@ -9,8 +9,8 @@ ac_add_options --disable-updater
ac_add_options --prefix=$PREFIX
ac_add_options --libdir=$LIBDIR
CC=/tools/gcc-4.5/bin/gcc
CXX=/tools/gcc-4.5/bin/g++
CC=/tools/gcc-4.5-0moz2/bin/gcc
CXX=/tools/gcc-4.5-0moz2/bin/g++
# Avoid dependency on libstdc++ 4.5
ac_add_options --enable-stdcxx-compat

View File

@ -1,8 +1,8 @@
ac_add_options --enable-debug
ac_add_options --enable-trace-malloc
CC=/tools/gcc-4.5/bin/gcc
CXX=/tools/gcc-4.5/bin/g++
CC=/tools/gcc-4.5-0moz2/bin/gcc
CXX=/tools/gcc-4.5-0moz2/bin/g++
# Avoid dependency on libstdc++ 4.5
ac_add_options --enable-stdcxx-compat

View File

@ -3,5 +3,5 @@ ac_add_options --enable-official-branding
ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
ac_add_options --enable-update-packaging
CC=/tools/gcc/bin/gcc
CXX=/tools/gcc/bin/g++
CC=/tools/gcc-4.5-0moz2/bin/gcc
CXX=/tools/gcc-4.5-0moz2/bin/g++

View File

@ -5,8 +5,8 @@ ac_add_options --enable-codesighs
# Nightlies only since this has a cost in performance
ac_add_options --enable-js-diagnostics
CC=/tools/gcc-4.5/bin/gcc
CXX=/tools/gcc-4.5/bin/g++
CC=/tools/gcc-4.5-0moz2/bin/gcc
CXX=/tools/gcc-4.5-0moz2/bin/g++
# Avoid dependency on libstdc++ 4.5
ac_add_options --enable-stdcxx-compat

View File

@ -2,8 +2,8 @@ ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
ac_add_options --enable-update-packaging
ac_add_options --enable-official-branding
CC=/tools/gcc-4.5/bin/gcc
CXX=/tools/gcc-4.5/bin/g++
CC=/tools/gcc-4.5-0moz2/bin/gcc
CXX=/tools/gcc-4.5-0moz2/bin/g++
# Avoid dependency on libstdc++ 4.5
ac_add_options --enable-stdcxx-compat

View File

@ -9,8 +9,8 @@ ac_add_options --disable-updater
ac_add_options --prefix=$PREFIX
ac_add_options --libdir=$LIBDIR
CC=/tools/gcc-4.5/bin/gcc
CXX=/tools/gcc-4.5/bin/g++
CC=/tools/gcc-4.5-0moz2/bin/gcc
CXX=/tools/gcc-4.5-0moz2/bin/g++
# Avoid dependency on libstdc++ 4.5
ac_add_options --enable-stdcxx-compat

View File

@ -51,3 +51,7 @@ MOZ_EXTENSIONS_DEFAULT=" gnomevfs"
# because branding dependencies are broken.
MOZ_BRANDING_DIRECTORY=browser/branding/nightly
MOZ_OFFICIAL_BRANDING_DIRECTORY=browser/branding/official
MOZ_APP_ID={ec8030f7-c20a-464f-9b0e-13a3a9e97384}
MOZ_PROFILE_MIGRATOR=1
MOZ_EXTENSION_MANAGER=1
MOZ_APP_STATIC_INI=1

View File

@ -45,7 +45,7 @@ const Cu = Components.utils;
Cu.import("resource:///modules/domplate.jsm");
Cu.import("resource:///modules/InsideOutBox.jsm");
Cu.import("resource:///modules/Services.jsm");
Cu.import("resource://gre/modules/Services.jsm");
var EXPORTED_SYMBOLS = ["TreePanel", "DOMHelpers"];

View File

@ -26,6 +26,7 @@
* Julian Viereck <jviereck@mozilla.com>
* Paul Rouget <paul@mozilla.com>
* Kyle Simpson <ksimpson@mozilla.com>
* Johan Charlez <johan.charlez@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -1112,8 +1113,8 @@ InspectorUI.prototype = {
this.inspectToolbutton.checked = false;
// Detach event listeners from content window and child windows to disable
// highlighting. We still want to be notified if the user presses "ESCAPE"
// to unlock the node, so we don't remove the "keypress" event until
// the highlighter is removed.
// to close the inspector, or "RETURN" to unlock the node, so we don't
// remove the "keypress" event until the highlighter is removed.
this.highlighter.detachInspectListeners();
this.inspecting = false;
@ -1186,7 +1187,8 @@ InspectorUI.prototype = {
this.restoreToolState(this.winID);
this.win.focus();
Services.obs.notifyObservers(null, INSPECTOR_NOTIFICATIONS.OPENED, null);
Services.obs.notifyObservers({wrappedJSObject: this},
INSPECTOR_NOTIFICATIONS.OPENED, null);
},
/**
@ -1248,8 +1250,12 @@ InspectorUI.prototype = {
break;
case "keypress":
switch (event.keyCode) {
case this.chromeWin.KeyEvent.DOM_VK_RETURN:
case this.chromeWin.KeyEvent.DOM_VK_ESCAPE:
this.closeInspectorUI(false);
event.preventDefault();
event.stopPropagation();
break;
case this.chromeWin.KeyEvent.DOM_VK_RETURN:
this.toggleInspection();
event.preventDefault();
event.stopPropagation();

View File

@ -94,11 +94,14 @@ function setupHighlighterTests()
InspectorUI.toggleInspectorUI();
}
function runSelectionTests()
function runSelectionTests(subject)
{
Services.obs.removeObserver(runSelectionTests,
InspectorUI.INSPECTOR_NOTIFICATIONS.OPENED, false);
is(subject.wrappedJSObject, InspectorUI,
"InspectorUI accessible in the observer");
executeSoon(function() {
Services.obs.addObserver(performTestComparisons,
InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING, false);
@ -117,12 +120,12 @@ function performTestComparisons(evt)
is(InspectorUI.selection, h1, "selection matches node");
is(InspectorUI.selection, InspectorUI.highlighter.highlitNode, "selection matches highlighter");
Services.obs.addObserver(finishTestComparisons,
InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING, false);
div = doc.querySelector("div#checkOutThisWickedSpread");
executeSoon(function() {
Services.obs.addObserver(finishTestComparisons,
InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING, false);
InspectorUI.inspectNode(div);
});
}

View File

@ -105,13 +105,15 @@ function performTestComparisons1()
{
Services.obs.removeObserver(performTestComparisons1,
InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING, false);
Services.obs.addObserver(performTestComparisons2,
InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING, false);
is(InspectorUI.selection, div1, "selection matches div1 node");
is(InspectorUI.highlighter.highlitNode, div1, "highlighter matches selection");
executeSoon(moveMouseOver.bind(this, div2));
executeSoon(function() {
Services.obs.addObserver(performTestComparisons2,
InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING, false);
moveMouseOver(div2);
});
}
function performTestComparisons2()

View File

@ -44,7 +44,7 @@ function test()
Services.obs.removeObserver(lockNode,
InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING);
EventUtils.synthesizeKey("VK_ESCAPE", { });
EventUtils.synthesizeKey("VK_RETURN", { });
executeSoon(isTheNodeLocked);
}
@ -57,7 +57,7 @@ function test()
}
function unlockNode() {
EventUtils.synthesizeKey("VK_ESCAPE", { });
EventUtils.synthesizeKey("VK_RETURN", { });
executeSoon(isTheNodeUnlocked);
}
@ -66,9 +66,12 @@ function test()
{
ok(InspectorUI.inspecting, "the node is unlocked");
// Let's close the inspector
Services.obs.addObserver(finishUp,
InspectorUI.INSPECTOR_NOTIFICATIONS.CLOSED, false);
InspectorUI.closeInspectorUI();
EventUtils.synthesizeKey("VK_ESCAPE", {});
ok(true, "Inspector is closing successfuly");
}
function finishUp() {

View File

@ -343,7 +343,7 @@ Templater.prototype._toNode = function(thing, document) {
* then _handleAsync() is just 'inserter(thing, siblingNode)'
*/
Templater.prototype._handleAsync = function(thing, siblingNode, inserter) {
if (typeof thing.then === 'function') {
if (thing != null && typeof thing.then === 'function') {
// Placeholder element to be replaced once we have the real data
var tempNode = siblingNode.ownerDocument.createElement('span');
siblingNode.parentNode.insertBefore(tempNode, siblingNode);

View File

@ -84,7 +84,7 @@ gcli.addCommand({
let command = canon.getCommand(commandNames[i]);
if (!command.hidden && command.description) {
output.push("<tr>");
output.push('<th class="gcliCmdHelpRight">' + command.name + "</th>");
output.push('<th class="gcli-help-right">' + command.name + "</th>");
output.push("<td>&#x2192; " + command.description + "</td>");
output.push("</tr>");
}

View File

@ -3559,7 +3559,7 @@ HeadsUpDisplay.prototype = {
}
else {
this.gcliterm = new GcliTerm(aWindow, this.hudId, this.chromeDocument,
this.console, this.hintNode);
this.console, this.hintNode, this.consoleWrap);
aParentNode.appendChild(this.gcliterm.element);
}
}
@ -3657,21 +3657,19 @@ HeadsUpDisplay.prototype = {
consoleFilterToolbar.setAttribute("id", "viewGroup");
this.consoleFilterToolbar = consoleFilterToolbar;
let hintSpacerNode = this.makeXULNode("box");
hintSpacerNode.setAttribute("flex", 1);
this.hintNode = this.makeXULNode("div");
this.hintNode.setAttribute("class", "gcliterm-hint-node");
let hintParentNode = this.makeXULNode("vbox");
hintParentNode.setAttribute("flex", "0");
hintParentNode.setAttribute("class", "gcliterm-hint-parent");
hintParentNode.appendChild(hintSpacerNode);
hintParentNode.setAttribute("pack", "end");
hintParentNode.appendChild(this.hintNode);
hintParentNode.hidden = true;
let hbox = this.makeXULNode("hbox");
hbox.setAttribute("flex", "1");
hbox.setAttribute("class", "gcliterm-display");
this.outputNode = this.makeXULNode("richlistbox");
this.outputNode.setAttribute("class", "hud-output-node");
@ -3764,8 +3762,8 @@ HeadsUpDisplay.prototype = {
]
},
{
name: "PageWebDeveloper",
category: "webdev",
name: "PageLogging",
category: "logging",
severities: [
{ name: "ConsoleErrors", prefKey: "error" },
{ name: "ConsoleWarnings", prefKey: "warn" },
@ -6951,7 +6949,7 @@ let commandExports = undefined;
* The node to which we add GCLI's hints.
* @constructor
*/
function GcliTerm(aContentWindow, aHudId, aDocument, aConsole, aHintNode)
function GcliTerm(aContentWindow, aHudId, aDocument, aConsole, aHintNode, aConsoleWrap)
{
this.context = Cu.getWeakReference(aContentWindow);
this.hudId = aHudId;
@ -6977,7 +6975,7 @@ function GcliTerm(aContentWindow, aHudId, aDocument, aConsole, aHintNode)
completeElement: this.completeNode,
inputBackgroundElement: this.inputStack,
hintElement: this.hintNode,
completionPrompt: "",
consoleWrap: aConsoleWrap,
gcliTerm: this
};
@ -6995,7 +6993,15 @@ GcliTerm.prototype = {
*/
hide: function GcliTerm_hide()
{
this.hintNode.parentNode.hidden = true;
let permaHint = false;
try {
permaHint = Services.prefs.getBoolPref("devtools.gcli.permaHint");
}
catch (ex) {}
if (!permaHint) {
this.hintNode.parentNode.hidden = true;
}
},
/**

View File

@ -238,7 +238,11 @@ var console = {};
return type + fmt(json, 50, 0);
}
var str = aThing.toString(); //.replace(/\s+/g, " ");
if (typeof aThing == "function") {
return fmt(aThing.toString().replace(/\s+/g, " "), 80, 0);
}
var str = aThing.toString().replace(/\n/g, "|");
return fmt(str, 80, 0);
}
@ -295,10 +299,23 @@ var console = {};
}, this);
}
else {
reply += type + " (enumerated with for-in)\n";
var prop;
for (prop in aThing) {
reply += logProperty(prop, aThing[prop]);
reply += type + "\n";
var root = aThing;
var logged = [];
while (root != null) {
var properties = Object.keys(root);
properties.sort();
properties.forEach(function(property) {
if (!(property in logged)) {
logged[property] = property;
reply += logProperty(property, aThing[property]);
}
});
root = Object.getPrototypeOf(root);
if (root != null) {
reply += ' - prototype ' + getCtorName(root) + '\n';
}
}
}
}
@ -669,7 +686,7 @@ var mozl10n = {};
})(mozl10n);
define('gcli/index', ['require', 'exports', 'module' , 'gcli/canon', 'gcli/types/basic', 'gcli/types/javascript', 'gcli/types/node', 'gcli/cli', 'gcli/ui/inputter', 'gcli/ui/arg_fetch', 'gcli/ui/menu', 'gcli/ui/focus'], function(require, exports, module) {
define('gcli/index', ['require', 'exports', 'module' , 'gcli/canon', 'gcli/types/basic', 'gcli/types/javascript', 'gcli/types/node', 'gcli/cli', 'gcli/ui/display'], function(require, exports, module) {
// The API for use by command authors
exports.addCommand = require('gcli/canon').addCommand;
@ -684,12 +701,9 @@ define('gcli/index', ['require', 'exports', 'module' , 'gcli/canon', 'gcli/types
require('gcli/cli').startup();
var Requisition = require('gcli/cli').Requisition;
var cli = require('gcli/cli');
var Inputter = require('gcli/ui/inputter').Inputter;
var ArgFetcher = require('gcli/ui/arg_fetch').ArgFetcher;
var CommandMenu = require('gcli/ui/menu').CommandMenu;
var FocusManager = require('gcli/ui/focus').FocusManager;
var Display = require('gcli/ui/display').Display;
var cli = require('gcli/cli');
var jstype = require('gcli/types/javascript');
var nodetype = require('gcli/types/node');
@ -717,59 +731,30 @@ define('gcli/index', ['require', 'exports', 'module' , 'gcli/canon', 'gcli/types
* - inputBackgroundElement: GCLITerm.inputStack
*/
createView: function(opts) {
opts.autoHide = true;
opts.requisition = new Requisition(opts.environment, opts.chromeDocument);
opts.completionPrompt = '';
jstype.setGlobalObject(opts.jsEnvironment.globalObject);
nodetype.setDocument(opts.contentDocument);
cli.setEvalFunction(opts.jsEnvironment.evalFunction);
// Create a FocusManager for the various parts to register with
if (!opts.focusManager) {
opts.debug = true;
opts.focusManager = new FocusManager({ document: opts.chromeDocument });
if (opts.requisition == null) {
opts.requisition = new Requisition(opts.environment, opts.chromeDocument);
}
opts.inputter = new Inputter(opts);
opts.inputter.update();
if (opts.gcliTerm) {
opts.focusManager.onFocus.add(opts.gcliTerm.show, opts.gcliTerm);
opts.focusManager.onBlur.add(opts.gcliTerm.hide, opts.gcliTerm);
opts.focusManager.addMonitoredElement(opts.gcliTerm.hintNode, 'gcliTerm');
}
if (opts.hintElement) {
opts.menu = new CommandMenu(opts.chromeDocument, opts.requisition);
opts.hintElement.appendChild(opts.menu.element);
opts.argFetcher = new ArgFetcher(opts.chromeDocument, opts.requisition);
opts.hintElement.appendChild(opts.argFetcher.element);
opts.menu.onCommandChange();
}
opts.display = new Display(opts);
},
/**
* Undo the effects of createView() to prevent memory leaks
*/
removeView: function(opts) {
opts.hintElement.removeChild(opts.menu.element);
opts.menu.destroy();
opts.hintElement.removeChild(opts.argFetcher.element);
opts.argFetcher.destroy();
opts.display.destroy();
delete opts.display;
opts.inputter.destroy();
opts.focusManager.removeMonitoredElement(opts.gcliTerm.hintNode, 'gcliTerm');
opts.focusManager.onFocus.remove(opts.gcliTerm.show, opts.gcliTerm);
opts.focusManager.onBlur.remove(opts.gcliTerm.hide, opts.gcliTerm);
opts.focusManager.destroy();
opts.requisition.destroy();
delete opts.requisition;
cli.unsetEvalFunction();
nodetype.unsetDocument();
jstype.unsetGlobalObject();
opts.requisition.destroy();
},
commandOutputManager: require('gcli/canon').commandOutputManager
@ -1126,14 +1111,7 @@ canon.commandOutputManager = new CommandOutputManager();
define('gcli/util', ['require', 'exports', 'module' ], function(require, exports, module) {
/*
* This module is a Pilot-Lite. It exports a number of objects that replicate
* parts of the Pilot project. It aims to be mostly API compatible, while
* removing the submodule complexity and helping us make things work inside
* Firefox.
* The Pilot compatible exports are: console/dom/event
*
* In addition it contains a small event library similar to EventEmitter but
* which makes it harder to mistake the event in use.
* A number of DOM manipulation and event handling utilities.
*/
@ -1212,26 +1190,25 @@ exports.createEvent = function(name) {
var dom = {};
var NS_XHTML = 'http://www.w3.org/1999/xhtml';
dom.NS_XHTML = 'http://www.w3.org/1999/xhtml';
/**
* Pass-through to createElement or createElementNS
* Create an HTML or XHTML element depending on whether the document is HTML
* or XML based. Where HTML/XHTML elements are distinguished by whether they
* are created using doc.createElementNS('http://www.w3.org/1999/xhtml', tag)
* or doc.createElement(tag)
* If you want to create a XUL element then you don't have a problem knowing
* what namespace you want.
* @param doc The document in which to create the element
* @param tag The name of the tag to create
* @param ns Custom namespace, HTML/XHTML is assumed if this is missing
* @returns The created element
*/
dom.createElement = function(doc, tag, ns) {
// If we've not been given a namespace, but the document is XML, then we
// use an XHTML namespace, otherwise we use HTML
if (ns == null && doc.xmlVersion != null) {
ns = NS_XHTML;
}
if (ns == null) {
return doc.createElement(tag);
dom.createElement = function(doc, tag) {
if (dom.isXmlDocument(doc)) {
return doc.createElementNS(dom.NS_XHTML, tag);
}
else {
return doc.createElementNS(ns, tag);
return doc.createElement(tag);
}
};
@ -1264,19 +1241,17 @@ dom.importCss = function(cssText, doc) {
};
/**
* Using setInnerHtml(foo) rather than innerHTML = foo allows us to enable
* tweaks in XHTML documents.
* There are problems with innerHTML on XML documents, so we need to do a dance
* using document.createRange().createContextualFragment() when in XML mode
*/
dom.setInnerHtml = function(elem, html) {
if (!this.document || elem.namespaceURI === NS_XHTML) {
try {
dom.clearElement(elem);
var range = elem.ownerDocument.createRange();
html = '<div xmlns="' + NS_XHTML + '">' + html + '</div>';
elem.appendChild(range.createContextualFragment(html));
}
catch (ex) {
elem.innerHTML = html;
if (dom.isXmlDocument(elem.ownerDocument)) {
dom.clearElement(elem);
html = '<div xmlns="' + dom.NS_XHTML + '">' + html + '</div>';
var range = elem.ownerDocument.createRange();
var child = range.createContextualFragment(html).childNodes[0];
while (child.hasChildNodes()) {
elem.appendChild(child.firstChild);
}
}
else {
@ -1284,6 +1259,27 @@ dom.setInnerHtml = function(elem, html) {
}
};
/**
* How to detect if we're in an XUL document (and therefore should create
* elements in an XHTML namespace)
* In a Mozilla XUL document, document.xmlVersion = null, however in Chrome
* document.contentType = undefined.
* @param doc The document element to work from (defaulted to the global
* 'document' if missing
*/
dom.isXmlDocument = function(doc) {
doc = doc || document;
// Best test for Firefox
if (doc.contentType && doc.contentType != 'text/html') {
return true;
}
// Best test for Chrome
if (doc.xmlVersion != null) {
return true;
}
return false;
};
exports.dom = dom;
@ -4037,14 +4033,16 @@ UnassignedAssignment.prototype.setUnassigned = function(args) {
* The event object looks like { newText: X }.
* </ul>
*
* @param environment An opaque object passed to commands using ExecutionContext
* @param document A DOM Document passed to commands using ExecutionContext in
* order to allow creation of DOM nodes.
* @param environment An optional opaque object passed to commands using
* ExecutionContext.
* @param doc A DOM Document passed to commands using ExecutionContext in
* order to allow creation of DOM nodes. If missing Requisition will use the
* global 'document'.
* @constructor
*/
function Requisition(environment, document) {
function Requisition(environment, doc) {
this.environment = environment;
this.document = document;
this.document = doc || document;
// The command that we are about to execute.
// @see setCommandConversion()
@ -4186,7 +4184,6 @@ Requisition.prototype._onCommandAssignmentChange = function(ev) {
oldValue: ev.oldValue,
newValue: command
});
// this.inputChange();
};
/**
@ -4371,16 +4368,14 @@ Requisition.prototype.toString = function() {
/**
* Return an array of Status scores so we can create a marked up
* version of the command line input.
* @param cursor We only take a status of INCOMPLETE to be INCOMPLETE when the
* cursor is actually in the argument. Otherwise it's an error.
*/
Requisition.prototype.getInputStatusMarkup = function() {
Requisition.prototype.getInputStatusMarkup = function(cursor) {
var argTraces = this.createInputArgTrace();
// We only take a status of INCOMPLETE to be INCOMPLETE when the cursor is
// actually in the argument. Otherwise it's an error.
// Generally the 'argument at the cursor' is the argument before the cursor
// unless it is before the first char, in which case we take the first.
var cursor = this.input.cursor.start === 0 ?
0 :
this.input.cursor.start - 1;
cursor = cursor === 0 ? 0 : cursor - 1;
var cTrace = argTraces[cursor];
var statuses = [];
@ -4569,9 +4564,8 @@ Requisition.prototype.exec = function(input) {
* </ul>
*/
Requisition.prototype.update = function(input) {
this.input = input;
if (this.input.cursor == null) {
this.input.cursor = { start: input.length, end: input.length };
if (input.cursor == null) {
input.cursor = { start: input.length, end: input.length };
}
this._structuralChangeInProgress = true;
@ -5040,6 +5034,135 @@ define('gcli/promise', ['require', 'exports', 'module' ], function(require, expo
Components.utils.import("resource:///modules/devtools/Promise.jsm");
exports.Promise = Promise;
});
/*
* Copyright 2009-2011 Mozilla Foundation and contributors
* Licensed under the New BSD license. See LICENSE.txt or:
* http://opensource.org/licenses/BSD-3-Clause
*/
define('gcli/ui/display', ['require', 'exports', 'module' , 'gcli/ui/inputter', 'gcli/ui/arg_fetch', 'gcli/ui/menu', 'gcli/ui/focus'], function(require, exports, module) {
var Inputter = require('gcli/ui/inputter').Inputter;
var ArgFetcher = require('gcli/ui/arg_fetch').ArgFetcher;
var CommandMenu = require('gcli/ui/menu').CommandMenu;
var FocusManager = require('gcli/ui/focus').FocusManager;
/**
* Display is responsible for generating the UI for GCLI, this implementation
* is a special case for use inside Firefox
*/
function Display(options) {
this.hintElement = options.hintElement;
this.gcliTerm = options.gcliTerm;
this.consoleWrap = options.consoleWrap;
this.requisition = options.requisition;
// Create a FocusManager for the various parts to register with
this.focusManager = new FocusManager({ document: options.chromeDocument });
this.focusManager.onFocus.add(this.gcliTerm.show, this.gcliTerm);
this.focusManager.onBlur.add(this.gcliTerm.hide, this.gcliTerm);
this.focusManager.addMonitoredElement(this.gcliTerm.hintNode, 'gcliTerm');
this.inputter = new Inputter({
document: options.contentDocument,
requisition: options.requisition,
inputElement: options.inputElement,
completeElement: options.completeElement,
completionPrompt: '',
backgroundElement: options.backgroundElement,
focusManager: this.focusManager
});
this.menu = new CommandMenu({
document: options.contentDocument,
requisition: options.requisition,
menuClass: 'gcliterm-menu'
});
this.hintElement.appendChild(this.menu.element);
this.argFetcher = new ArgFetcher({
document: options.contentDocument,
requisition: options.requisition,
argFetcherClass: 'gcliterm-argfetcher'
});
this.hintElement.appendChild(this.argFetcher.element);
this.chromeWindow = options.chromeDocument.defaultView;
this.resizer = this.resizer.bind(this);
this.chromeWindow.addEventListener('resize', this.resizer, false);
this.requisition.commandChange.add(this.resizer, this);
}
/**
* Avoid memory leaks
*/
Display.prototype.destroy = function() {
this.chromeWindow.removeEventListener('resize', this.resizer, false);
delete this.resizer;
delete this.chromeWindow;
delete this.consoleWrap;
this.hintElement.removeChild(this.menu.element);
this.menu.destroy();
this.hintElement.removeChild(this.argFetcher.element);
this.argFetcher.destroy();
this.inputter.destroy();
this.focusManager.removeMonitoredElement(this.gcliTerm.hintNode, 'gcliTerm');
this.focusManager.onFocus.remove(this.gcliTerm.show, this.gcliTerm);
this.focusManager.onBlur.remove(this.gcliTerm.hide, this.gcliTerm);
this.focusManager.destroy();
delete this.gcliTerm;
delete this.hintElement;
};
/**
* Called on chrome window resize, or on divider slide
*/
Display.prototype.resizer = function() {
var parentRect = this.consoleWrap.getBoundingClientRect();
var parentHeight = parentRect.bottom - parentRect.top - 64;
if (parentHeight < 100) {
this.hintElement.classList.add('gcliterm-hint-nospace');
}
else {
this.hintElement.classList.remove('gcliterm-hint-nospace');
var isMenuVisible = this.menu.element.style.display !== 'none';
if (isMenuVisible) {
this.menu.setMaxHeight(parentHeight);
// Magic numbers. We have 2 options - lots of complex dom math to derive
// the height of a menu item (19 pixels) and the vertical padding
// (22 pixels), or we could just hard-code. The former is *slightly* more
// resilient to refactoring (but still breaks with dom structure changes),
// the latter is simpler, faster and easier.
var idealMenuHeight = (19 * this.menu.items.length) + 22;
if (idealMenuHeight > parentHeight) {
this.hintElement.style.overflowY = 'scroll';
this.hintElement.style.borderBottomColor = 'threedshadow';
}
else {
this.hintElement.style.overflowY = null;
this.hintElement.style.borderBottomColor = 'white';
}
}
else {
this.argFetcher.setMaxHeight(parentHeight);
this.hintElement.style.overflowY = null;
this.hintElement.style.borderBottomColor = 'white';
}
}
};
exports.Display = Display;
});
/*
* Copyright 2009-2011 Mozilla Foundation and contributors
@ -5067,7 +5190,7 @@ function Inputter(options) {
this.requisition = options.requisition;
// Suss out where the input element is
this.element = options.inputElement || 'gcliInput';
this.element = options.inputElement || 'gcli-input';
if (typeof this.element === 'string') {
this.document = options.document || document;
var name = this.element;
@ -5099,17 +5222,11 @@ function Inputter(options) {
this.element.addEventListener('keydown', this.onKeyDown, false);
this.element.addEventListener('keyup', this.onKeyUp, false);
if (options.completer == null) {
options.completer = new Completer(options);
}
else if (typeof options.completer === 'function') {
options.completer = new options.completer(options);
}
this.completer = options.completer;
this.completer = options.completer || new Completer(options);
this.completer.decorate(this);
// Use the provided history object, or instantiate our own
this.history = options.history = options.history || new History(options);
this.history = options.history || new History(options);
this._scrollingThroughHistory = false;
// Cursor position affects hint severity
@ -5124,6 +5241,8 @@ function Inputter(options) {
}
this.requisition.inputChange.add(this.onInputChange, this);
this.update();
}
/**
@ -5372,12 +5491,12 @@ Inputter.prototype.onKeyUp = function(ev) {
// 1 second) to the time of the keyup then we assume that we got them
// both, and do the completion.
if (this.lastTabDownAt + 1000 > ev.timeStamp) {
this.getCurrentAssignment().complete();
// It's possible for TAB to not change the input, in which case the
// onInputChange event will not fire, and the caret move will not be
// processed. So we check that this is done
// processed. So we check that this is done first
this._caretChange = Caret.TO_ARG_END;
this._processCaretChange(this.getInputState(), true);
this.getCurrentAssignment().complete();
}
this.lastTabDownAt = 0;
this._scrollingThroughHistory = false;
@ -5467,11 +5586,11 @@ cliView.Inputter = Inputter;
* Defaults to '&#x00bb;' (double greater-than, a.k.a right guillemet).
*/
function Completer(options) {
this.document = options.document;
this.document = options.document || document;
this.requisition = options.requisition;
this.elementCreated = false;
this.element = options.completeElement || 'gcliComplete';
this.element = options.completeElement || 'gcli-row-complete';
if (typeof this.element === 'string') {
var name = this.element;
this.element = this.document.getElementById(name);
@ -5479,15 +5598,15 @@ function Completer(options) {
if (!this.element) {
this.elementCreated = true;
this.element = dom.createElement(this.document, 'div');
this.element.className = 'gcliCompletion gcliVALID';
this.element.className = 'gcli-in-complete gcli-in-valid';
this.element.setAttribute('tabindex', '-1');
this.element.setAttribute('aria-live', 'polite');
}
}
this.completionPrompt = typeof options.completionPrompt === 'string'
? options.completionPrompt
: '&#x00bb;';
? options.completionPrompt
: '&#x00bb;';
if (options.inputBackgroundElement) {
this.backgroundElement = options.inputBackgroundElement;
@ -5595,9 +5714,9 @@ Completer.prototype.update = function(input) {
var current = this.requisition.getAssignmentAt(input.cursor.start);
var predictions = current.getPredictions();
var completion = '<span class="gcliPrompt">' + this.completionPrompt + '</span> ';
var completion = '<span class="gcli-prompt">' + this.completionPrompt + '</span> ';
if (input.typed.length > 0) {
var scores = this.requisition.getInputStatusMarkup();
var scores = this.requisition.getInputStatusMarkup(input.cursor.start);
completion += this.markupStatusScore(scores, input);
}
@ -5608,10 +5727,10 @@ Completer.prototype.update = function(input) {
// Display the suffix of the prediction as the completion.
var numLeadingSpaces = existing.match(/^(\s*)/)[0].length;
var suffix = tab.slice(existing.length - numLeadingSpaces);
completion += '<span class="gcliCompl">' + suffix + '</span>';
completion += '<span class="gcli-in-ontab">' + suffix + '</span>';
} else {
// Display the '-> prediction' at the end of the completer element
completion += ' &#xa0;<span class="gcliCompl">&#x21E5; ' +
completion += ' &#xa0;<span class="gcli-in-ontab">&#x21E5; ' +
tab + '</span>';
}
}
@ -5621,11 +5740,11 @@ Completer.prototype.update = function(input) {
var command = this.requisition.commandAssignment.getValue();
if (command && command.name === '{') {
if (this.requisition.getAssignment(0).getArg().suffix.indexOf('}') === -1) {
completion += '<span class="gcliCloseBrace">}</span>';
completion += '<span class="gcli-in-closebrace">}</span>';
}
}
dom.setInnerHtml(this.element, '<span>' + completion + '</span>');
dom.setInnerHtml(this.element, completion);
};
/**
@ -5646,7 +5765,7 @@ Completer.prototype.markupStatusScore = function(scores, input) {
console.error('No state at i=' + i + '. scores.len=' + scores.length);
state = Status.VALID;
}
completion += '<span class="gcli' + state.toString() + '">';
completion += '<span class="gcli-in-' + state.toString().toLowerCase() + '">';
lastStatus = scores[i];
}
var char = input.typed[i];
@ -5757,12 +5876,15 @@ var argFetchHtml = require('text!gcli/ui/arg_fetch.html');
/**
* A widget to display an inline dialog which allows the user to fill out
* the arguments to a command.
* @param document The document to use in creating widgets
* @param requisition The Requisition to fill out
* @param options An object containing the customizations, which include:
* - document: The document to use in creating widgets
* - requisition: The Requisition to fill out
* - argFetcherClass: Custom class name when generating the top level element
* which allows different layout systems
*/
function ArgFetcher(document, requisition) {
this.document = document;
this.requisition = requisition;
function ArgFetcher(options) {
this.document = options.document || document;
this.requisition = options.requisition;
// FF can be really hard to debug if doc is null, so we check early on
if (!this.document) {
@ -5770,7 +5892,7 @@ function ArgFetcher(document, requisition) {
}
this.element = dom.createElement(this.document, 'div');
this.element.className = 'gcliCliEle';
this.element.className = options.argFetcherClass || 'gcli-argfetch';
// We cache the fields we create so we can destroy them later
this.fields = [];
@ -5785,10 +5907,12 @@ function ArgFetcher(document, requisition) {
var templates = dom.createElement(this.document, 'div');
dom.setInnerHtml(templates, argFetchHtml);
this.reqTempl = templates.querySelector('#gcliReqTempl');
this.reqTempl = templates.querySelector('.gcli-af-template');
this.requisition.commandChange.add(this.onCommandChange, this);
this.requisition.inputChange.add(this.onInputChange, this);
this.onCommandChange();
}
/**
@ -5856,31 +5980,39 @@ ArgFetcher.prototype.onInputChange = function(ev) {
* of field for each assignment.
*/
ArgFetcher.prototype.getInputFor = function(assignment) {
var newField = getField(assignment.param.type, {
document: this.document,
type: assignment.param.type,
name: assignment.param.name,
requisition: this.requisition,
required: assignment.param.isDataRequired(),
named: !assignment.param.isPositionalAllowed()
});
try {
var newField = getField(assignment.param.type, {
document: this.document,
type: assignment.param.type,
name: assignment.param.name,
requisition: this.requisition,
required: assignment.param.isDataRequired(),
named: !assignment.param.isPositionalAllowed()
});
// BUG 664198 - remove on delete
newField.fieldChanged.add(function(ev) {
assignment.setConversion(ev.conversion);
}, this);
assignment.assignmentChange.add(function(ev) {
newField.setConversion(ev.conversion);
}.bind(this));
// BUG 664198 - remove on delete
newField.fieldChanged.add(function(ev) {
assignment.setConversion(ev.conversion);
}, this);
assignment.assignmentChange.add(function(ev) {
newField.setConversion(ev.conversion);
}.bind(this));
this.fields.push(newField);
newField.setConversion(this.assignment.conversion);
this.fields.push(newField);
newField.setConversion(this.assignment.conversion);
// Bug 681894: we add the field as a property of the assignment so that
// #linkMessageElement() can call 'field.setMessageElement(element)'
assignment.field = newField;
// Bug 681894: we add the field as a property of the assignment so that
// #linkMessageElement() can call 'field.setMessageElement(element)'
assignment.field = newField;
return newField.element;
return newField.element;
}
catch (ex) {
// This is called from within Templater which can make tracing errors hard
// so we log here if anything goes wrong
console.error(ex);
return '';
}
};
/**
@ -5912,6 +6044,22 @@ ArgFetcher.prototype.onFormCancel = function(ev) {
this.requisition.clear();
};
/**
* Change how much vertical space this dialog can take up
*/
ArgFetcher.prototype.setMaxHeight = function(height, isTooBig) {
this.fields.forEach(function(field) {
if (field.menu) {
// Magic number alert: 105 is roughly the size taken up by the rest of
// the dialog for the '{' command. We could spend ages calculating 105
// by doing math on the various components that contribute to the 105,
// but I don't think that would make it significantly less fragile under
// refactoring. Plus this works.
field.menu.setMaxHeight(height - 105);
}
});
};
argFetch.ArgFetcher = ArgFetcher;
@ -6104,7 +6252,7 @@ function StringField(type, options) {
this.element = dom.createElement(this.document, 'input');
this.element.type = 'text';
this.element.style.width = '100%';
this.element.className = 'gcli-field';
this.onInputChange = this.onInputChange.bind(this);
this.element.addEventListener('keyup', this.onInputChange, false);
@ -6264,7 +6412,7 @@ function SelectionField(type, options) {
this.items = [];
this.element = dom.createElement(this.document, 'select');
this.element.style.width = '180px';
this.element.className = 'gcli-field';
this._addOption({
name: l10n.lookupFormat('fieldSelectionSelect', [ options.name ])
});
@ -6339,11 +6487,11 @@ function JavascriptField(type, options) {
this.input = dom.createElement(this.document, 'input');
this.input.type = 'text';
this.input.addEventListener('keyup', this.onInputChange, false);
this.input.style.marginBottom = '0px';
this.input.style.width = options.name.length === 0 ? '240px' : '160px';
this.input.style.marginBottom = '0';
this.input.className = 'gcli-field';
this.element.appendChild(this.input);
this.menu = new Menu(this.document, { field: true });
this.menu = new Menu({ document: this.document, field: true });
this.element.appendChild(this.menu.element);
this.setConversion(this.type.parse(new Argument('')));
@ -6655,26 +6803,36 @@ var menuHtml = require('text!gcli/ui/menu.html');
/**
* Menu is a display of the commands that are possible given the state of a
* requisition.
* @param document The document from which we create elements.
* @param options A way to customize the menu display. Valid options are:
* - field:true Turns the menu display into a drop-down for use inside a
* JavascriptField.
* - field: [boolean] Turns the menu display into a drop-down for use inside a
* JavascriptField.
* - document: The document to use in creating widgets
* - menuClass: Custom class name when generating the top level element
* which allows different layout systems
*/
function Menu(document, options) {
this.element = dom.createElement(document, 'div');
this.element.className = 'gcliMenu';
function Menu(options) {
options = options || {};
this.document = options.document || document;
// FF can be really hard to debug if doc is null, so we check early on
if (!this.document) {
throw new Error('No document');
}
this.element = dom.createElement(this.document, 'div');
this.element.classList.add(options.menuClass || 'gcli-menu');
if (options && options.field) {
this.element.className += ' gcliMenuField';
this.element.classList.add(options.menuFieldClass || 'gcli-menu-field');
}
// Pull the HTML into the DOM, but don't add it to the document
if (menuCss != null) {
this.style = dom.importCss(menuCss, document);
this.style = dom.importCss(menuCss, this.document);
}
var templates = dom.createElement(document, 'div');
var templates = dom.createElement(this.document, 'div');
dom.setInnerHtml(templates, menuHtml);
this.optTempl = templates.querySelector('#gcliOptTempl');
this.optTempl = templates.querySelector('.gcli-menu-template');
// Contains the items that should be displayed
this.items = null;
@ -6734,19 +6892,31 @@ Menu.prototype.hide = function() {
this.element.style.display = 'none';
};
/**
* Change how much vertical space this menu can take up
*/
Menu.prototype.setMaxHeight = function(height) {
this.element.style.maxHeight = height + 'px';
};
exports.Menu = Menu;
/**
* CommandMenu is a special menu that integrates with a Requisition to display
* available commands.
* @param options A way to customize the menu display. Valid options include
* those valid for Menu(), plus:
* - requisition: The Requisition to fill out (required)
*/
function CommandMenu(document, requisition) {
Menu.call(this, document);
this.requisition = requisition;
function CommandMenu(options) {
Menu.call(this, options);
this.requisition = options.requisition;
this.requisition.commandChange.add(this.onCommandChange, this);
canon.canonChange.add(this.onCommandChange, this);
this.onCommandChange();
}
CommandMenu.prototype = Object.create(Menu.prototype);
@ -6767,8 +6937,8 @@ CommandMenu.prototype.destroy = function() {
CommandMenu.prototype.onItemClick = function(ev) {
var type = this.requisition.commandAssignment.param.type;
var text = type.stringify(ev.currentTarget.item);
var arg = new Argument(text);
var name = ev.currentTarget.querySelector('.gcli-menu-name').innerHTML;
var arg = new Argument(name);
arg.suffix = ' ';
var conversion = type.parse(arg);
@ -6828,68 +6998,61 @@ define('gcli/ui/domtemplate', ['require', 'exports', 'module' ], function(requir
});
define("text!gcli/ui/menu.css", [], void 0);
define("text!gcli/ui/menu.html", [], "" +
"<!--" +
"Template for the beginnings of a command menu." +
"This will work with things other than a command - many things are a set of" +
"things with a name and description." +
"In the command context it is evaluated once for every keypress in the cli" +
"when a command has not been entered." +
"-->" +
"<div id=\"gcliOptTempl\" aria-live=\"polite\">" +
" <div class=\"gcliOption\" foreach=\"item in ${items}\" onclick=\"${onItemClick}\"" +
" title=\"${item.manual || ''}\">" +
" ${__element.item = item; ''}" +
" <span class=\"gcliOptionName\">${item.name}</span>" +
" <span class=\"gcliOptionDesc\">${item.description}</span>" +
" </div>" +
" <div class=\"gcliMenuError\" if=\"${error}\">${error}</div>" +
"</div>" +
define("text!gcli/ui/menu.html", [], "\n" +
"<table class=\"gcli-menu-template\" aria-live=\"polite\">\n" +
" <tr class=\"gcli-menu-option\" foreach=\"item in ${items}\"\n" +
" onclick=\"${onItemClick}\" title=\"${item.manual || ''}\">\n" +
" <td class=\"gcli-menu-name\">${item.name}</td>\n" +
" <td class=\"gcli-menu-desc\">${item.description}</td>\n" +
" </tr>\n" +
" <tr if=\"${error}\">\n" +
" <td class=\"gcli-menu-error\" colspan=\"2\">${error}</td>\n" +
" </tr>\n" +
"</table>\n" +
"");
define("text!gcli/ui/arg_fetch.css", [], void 0);
define("text!gcli/ui/arg_fetch.html", [], "" +
"<!--" +
"Template for an Assignment." +
"Evaluated each time the commandAssignment changes" +
"-->" +
"<div id=\"gcliReqTempl\" aria-live=\"polite\">" +
" <div>" +
" <div class=\"gcliCmdDesc\">" +
" ${requisition.commandAssignment.getValue().description}" +
" </div>" +
" <table class=\"gcliParams\">" +
" <tbody class=\"gcliAssignment\"" +
" foreach=\"assignment in ${requisition.getAssignments()}\">" +
" <!-- Parameter -->" +
" <tr class=\"gcliGroupRow\">" +
" <td class=\"gcliParamName\">" +
" <label for=\"gcliForm${assignment.param.name}\">" +
" ${assignment.param.description ? assignment.param.description + ':' : ''}" +
" </label>" +
" </td>" +
" <td class=\"gcliParamInput\">${getInputFor(assignment)}</td>" +
" <td>" +
" <span class=\"gcliRequired\" if=\"${assignment.param.isDataRequired()}\"> *</span>" +
" </td>" +
" </tr>" +
" <tr class=\"gcliGroupRow\">" +
" <td class=\"gcliParamError\" colspan=\"2\">" +
" ${linkMessageElement(assignment, __element)}" +
" </td>" +
" </tr>" +
" </tbody>" +
" <tfoot>" +
" <tr>" +
" <td colspan=\"3\" class=\"gcliParamSubmit\">" +
" <input type=\"submit\" value=\"Cancel\" onclick=\"${onFormCancel}\"/>" +
" <input type=\"submit\" value=\"OK\" onclick=\"${onFormOk}\" save=\"${okElement}\"/>" +
" </td>" +
" </tr>" +
" </tfoot>" +
" </table>" +
" </div>" +
"</div>" +
define("text!gcli/ui/arg_fetch.html", [], "\n" +
"<!--\n" +
"Template for an Assignment.\n" +
"Evaluated each time the commandAssignment changes\n" +
"-->\n" +
"<div class=\"gcli-af-template\" aria-live=\"polite\">\n" +
" <div>\n" +
" <div class=\"gcli-af-cmddesc\">\n" +
" ${requisition.commandAssignment.getValue().description}\n" +
" </div>\n" +
" <table class=\"gcli-af-params\">\n" +
" <tbody foreach=\"assignment in ${requisition.getAssignments()}\">\n" +
" <!-- Parameter -->\n" +
" <tr>\n" +
" <td class=\"gcli-af-paramname\">\n" +
" <label for=\"gcliForm${assignment.param.name}\">\n" +
" ${assignment.param.description ? assignment.param.description + ':' : ''}\n" +
" </label>\n" +
" </td>\n" +
" <td>${getInputFor(assignment)}</td>\n" +
" <td>\n" +
" <span class=\"gcli-af-required\" if=\"${assignment.param.isDataRequired()}\">*</span>\n" +
" </td>\n" +
" </tr>\n" +
" <tr>\n" +
" <td class=\"gcli-af-error\" colspan=\"2\">\n" +
" ${linkMessageElement(assignment, __element)}\n" +
" </td>\n" +
" </tr>\n" +
" </tbody>\n" +
" <tfoot>\n" +
" <tr>\n" +
" <td colspan=\"3\" class=\"gcli-af-submit\">\n" +
" <input type=\"submit\" value=\"Cancel\" onclick=\"${onFormCancel}\"/>\n" +
" <input type=\"submit\" value=\"OK\" onclick=\"${onFormOk}\" save=\"${okElement}\"/>\n" +
" </td>\n" +
" </tr>\n" +
" </tfoot>\n" +
" </table>\n" +
" </div>\n" +
"</div>\n" +
"");
/*

View File

@ -36,6 +36,7 @@ function onLoad() {
}
catch (ex) {
gcli._internal.console.error('Test Failure', ex);
ok(false, '' + ex);
}
finally {
closeConsole();
@ -82,7 +83,7 @@ function testCallCommands() {
is(gcliterm.completeNode.textContent, " ecd", "Completion for \"ecd\"");
// Test a normal command's life cycle
gcliterm.opts.inputter.setInput("echo hello world");
gcliterm.opts.display.inputter.setInput("echo hello world");
gcliterm.opts.requisition.exec();
let nodes = hud.outputNode.querySelectorAll("description");

View File

@ -913,7 +913,7 @@ function update(input) {
status = requ.getStatus();
assignC = requ.getAssignmentAt(input.cursor.start);
statuses = requ.getInputStatusMarkup().map(function(s) {
statuses = requ.getInputStatusMarkup(input.cursor.start).map(function(s) {
return s.toString()[0];
}).join('');
@ -1431,7 +1431,7 @@ function input(typed) {
}
status = requ.getStatus();
statuses = requ.getInputStatusMarkup().map(function(s) {
statuses = requ.getInputStatusMarkup(input.cursor.start).map(function(s) {
return s.toString()[0];
}).join('');
@ -1588,6 +1588,7 @@ function onLoad() {
catch (ex) {
failed = ex;
console.error('Test Failure', ex);
ok(false, '' + ex);
}
finally {
closeConsole();

View File

@ -21,7 +21,7 @@ function testFilterButtons() {
testMenuFilterButton("net");
testMenuFilterButton("css");
testMenuFilterButton("js");
testMenuFilterButton("webdev");
testMenuFilterButton("logging");
finishTest();
}

View File

@ -14,6 +14,7 @@
@DLL_PREFIX@mozjs@DLL_SUFFIX@
#endif
LICENSE
update.locale
browserconfig.properties
chrome/US.jar
chrome/app-chrome.manifest

View File

@ -20,7 +20,7 @@ cliEvalJavascript=Enter JavaScript directly
# that has a number of pre-defined options the user interface presents these
# in a drop-down menu, where the first 'option' is an indicator that a
# selection should be made. This string describes that first option.
fieldSelectionSelect=Select a %S ...
fieldSelectionSelect=Select a %S
# LOCALIZATION NOTE (fieldArrayAdd): When a command has a parameter that can
# be repeated a number of times (e.g. like the 'cat a.txt b.txt' command) the

View File

@ -1,3 +1,12 @@
# LOCALIZATION NOTE These strings are used inside the Inspector
# which is available from the Web Developer sub-menu -> 'Inspect'.
#
# The correct localization of this file might be to keep it in
# English, or another language commonly spoken among web developers.
# You want to make that choice consistent across the developer tools.
# A good criteria is the language in which you'd find the best
# documentation on web development on the web.
# LOCALIZATION NOTE (confirmNavigationAway): Used in the Inspector tool, when
# the user tries to navigate away from a web page, to confirm the change of
# page.

View File

@ -1,6 +1,12 @@
<!-- LOCALIZATION NOTE : FILE This file contains the Scratchpad window strings -->
<!-- LOCALIZATION NOTE : FILE Do not translate commandkeys -->
<!-- LOCALIZATION NOTE : FILE The correct localization of this file might be to
- keep it in English, or another language commonly spoken among web developers.
- You want to make that choice consistent across the developer tools.
- A good criteria is the language in which you'd find the best
- documentation on web development on the web. -->
<!-- LOCALIZATION NOTE (scratchpad.title):
- The Scratchpad is intended to provide a simple text editor for creating
- and evaluating bits of JavaScript code for the purposes of function

View File

@ -1,3 +1,12 @@
# LOCALIZATION NOTE These strings are used inside the JavaScript scratchpad
# which is available from the Web Developer sub-menu -> 'Scratchpad'.
#
# The correct localization of this file might be to keep it in
# English, or another language commonly spoken among web developers.
# You want to make that choice consistent across the developer tools.
# A good criteria is the language in which you'd find the best
# documentation on web development on the web.
# LOCALIZATION NOTE (propertyPanel.updateButton.label): Used in the Property
# Panel that is opened by the Scratchpad window when inspecting an object. This
# is the Update button label.

View File

@ -1,3 +1,9 @@
<!-- LOCALIZATION NOTE : FILE The correct localization of this file might be to
- keep it in English, or another language commonly spoken among web developers.
- You want to make that choice consistent across the developer tools.
- A good criteria is the language in which you'd find the best
- documentation on web development on the web. -->
<!-- LOCALIZATION NOTE (userStylesLabel): This is the label for the checkbox
- that specifies whether the styles that are not from the user's stylesheet
- should be displayed or not. -->

View File

@ -1,4 +1,11 @@
# LOCALIZATION NOTE These strings are used inside the Style Inspector.
#
# The correct localization of this file might be to keep it in
# English, or another language commonly spoken among web developers.
# You want to make that choice consistent across the developer tools.
# A good criteria is the language in which you'd find the best
# documentation on web development on the web.
# LOCALIZATION NOTE (panelTitle): This is the panel title
panelTitle=Style Inspector

View File

@ -1,3 +1,9 @@
<!-- LOCALIZATION NOTE : FILE The correct localization of this file might be to
- keep it in English, or another language commonly spoken among web developers.
- You want to make that choice consistent across the developer tools.
- A good criteria is the language in which you'd find the best
- documentation on web development on the web. -->
<!ENTITY networkPanel.requestURL "Request URL">
<!ENTITY networkPanel.requestMethod "Request Method">
<!ENTITY networkPanel.statusCode "Status Code">

View File

@ -1,3 +1,10 @@
# LOCALIZATION NOTE
# The correct localization of this file might be to keep it in
# English, or another language commonly spoken among web developers.
# You want to make that choice consistent across the developer tools.
# A good criteria is the language in which you'd find the best
# documentation on web development on the web.
typeError=Error:
typeWarning=Warning:
typeNetwork=Network:
@ -18,19 +25,17 @@ btnPageCSS=CSS
tipPageCSS=Log CSS parsing errors
btnPageJS=JS
tipPageJS=Log JavaScript exceptions
# LOCALIZATION NOTE (btnPageWebDeveloper):
# LOCALIZATION NOTE (btnPageLogging):
#
# This is used as the text of the "Web Developer" button on the toolbar. It
# This is used as the text of the "Logging" button on the toolbar. It
# shows or hides messages that the web developer inserted on the page for
# debugging purposes, using calls such console.log() and console.error(). You
# may wish to localize this as "Page" if that is clearer in your locale. See
# bug 601667 for more information.
btnPageWebDeveloper=Web Developer
# LOCALIZATION NOTE (tipPageWebDeveloper):
# debugging purposes, using calls such console.log() and console.error().
btnPageLogging=Logging
# LOCALIZATION NOTE (tipPageLogging):
#
# This is used as the text of the tool tip for the "Web Developer" button on
# This is used as the text of the tool tip for the "Logging" button on
# the toolbar.
tipPageWebDeveloper=Log messages sent to the "console" object
tipPageLogging=Log messages sent to the "console" object
btnConsoleErrors=Errors
tipConsoleErrors=Log calls to console.error()
btnConsoleInfo=Info

View File

@ -36,6 +36,9 @@
* ***** END LICENSE BLOCK ***** */
/* From: $GCLI/mozilla/gcli/ui/gcliterm.css */
/* Bug 678152 calls for UX review which will fix the color names */
.gcliterm-input-node,
.gcliterm-complete-node {
border: none;
@ -44,29 +47,38 @@
vertical-align: middle;
background-color: transparent;
font: 12px Consolas, "Lucida Console", monospace;
padding: 2px 0 0 16px;
}
.gcliterm-input-node {
padding-top: 2px;
padding-bottom: 0;
-moz-padding-start: 16px;
-moz-padding-end: 0;
}
.gcliterm-complete-node {
color: #FFF;
padding: 4px 4px 2px 21px;
padding-top: 4px;
padding-bottom: 2px;
-moz-padding-start: 21px;
-moz-padding-end: 4px;
}
.gcliVALID {
.gcli-in-valid {
border-bottom: none;
}
.gcliINCOMPLETE {
.gcli-in-incomplete {
color: #DDD;
border-bottom: 1px dotted #999;
}
.gcliERROR {
.gcli-in-error {
color: #DDD;
border-bottom: 1px dotted #F00;
}
.gcliCompl {
.gcli-in-ontab {
color: #999;
}
@ -75,167 +87,200 @@
width: 100%;
}
.gcliterm-argfetcher {
display: -moz-box;
-moz-box-flex: 1;
}
.gcliterm-hint-node {
color: #000;
background: rgba(250, 250, 250, 0.8);
border: 1px solid #AAA;
border-bottom: 0px !important;
border-top: 1px solid threedshadow;
border-bottom: 1px solid #FFF;
border-left: 1px solid threedshadow;
border-right: 1px solid threedshadow;
border-top-right-radius: 5px;
border-top-left-radius: 5px;
margin-left: 10px;
margin-right: 10px;
display: inline-block;
overflow: auto;
padding: 10px;
margin-bottom: -1px;
}
.gcliterm-hint-parent {
border-bottom: 1px solid #AAA;
width: 300px;
padding: 10px 10px 0;
border-top: 1px solid threedshadow;
border-bottom: 1px solid threedshadow;
}
.gcliCmdHelpRight {
.gcli-help-right {
text-align: right;
}
.gcliterm-menu {
display: -moz-box;
-moz-box-flex: 1;
}
.gcliterm-hint-nospace {
display: none;
}
/*
* The language of a console is not en_US or any other common language
* (i.e we don't attempt to translate 'console.log(x)')
* So we fix .gcliterm-input-node/.gcliterm-complete-node elements to be ltr.
* As a result we also want the hints to pop up on the left (above the prompt)
*/
.gcliterm-input-node,
.gcliterm-complete-node,
.gcliterm-display {
direction: ltr;
}
/*
* We want the stuff under .gcliterm-display to obey normal direction rules
* so we need to swap back when the document is in rtl mode.
* The selectors below are faster, but equivalent to:
* .gcliterm-display > *:-moz-locale-dir(rtl) {
* direction: rtl;
* }
* In non-performance critical situations the above is preferred due to it's
* greater resilience to refactoring
*/
.gcliterm-hint-parent:-moz-locale-dir(rtl),
.hud-output-node:-moz-locale-dir(rtl) {
direction: rtl;
}
/* From: $GCLI/mozilla/gcli/ui/gcliterm-gnomestripe.css */
/* From: $GCLI/lib/gcli/ui/arg_fetch.css */
.gcliCmdDesc {
.gcli-argfetch {
width: 100%;
box-sizing: border-box;
-moz-box-sizing: border-box;
}
.gcli-af-cmddesc {
font-weight: bold;
text-align: center;
margin-bottom: 5px;
border-bottom: 1px solid #ddd;
padding-bottom: 3px;
padding: 3px 10px 0;
}
.gcliParamGroup {
font-weight: bold;
.gcli-af-params {
padding: 0 10px;
width: 100%;
box-sizing: border-box;
-moz-box-sizing: border-box;
}
.gcliParamName {
.gcli-af-paramname {
text-align: right;
font-size: 90%;
}
.gcliParamError {
.gcli-af-required {
font-size: 90%;
color: #f66;
padding-left: 5px;
}
.gcli-af-error {
font-size: 80%;
color: #900;
}
.gcliParamSubmit {
.gcli-af-submit {
text-align: right;
}
.gcliGroupSymbol {
font-size: 90%;
color: #666;
}
.gcliRequired {
font-size: 80%;
color: #666;
}
.gcliParams {
.gcli-field {
width: 100%;
}
/* From: $GCLI/lib/gcli/ui/hinter.css */
.gcliHintParent {
color: #000;
background: rgba(250, 250, 250, 0.8);
border: 1px solid #AAA;
border-top-right-radius: 5px;
border-top-left-radius: 5px;
margin-left: 10px;
margin-right: 10px;
display: inline-block;
/* From: $GCLI/lib/gcli/ui/menu.css */
.gcli-menu {
width: 100%;
overflow: hidden;
}
.gcliHints {
overflow: auto;
padding: 10px;
display: inline-block;
.gcli-menu-field {
border: 1px solid #aaa;
border-top: 0;
border-bottom-right-radius: 5px;
border-bottom-left-radius: 5px;
max-height: 300px;
margin: 0 3px;
padding: 0;
}
.gcliHints ul {
margin: 0;
padding: 0 15px;
.gcli-menu-template {
border-collapse: collapse;
width: 100%;
margin: 10px 0;
}
/* From: $GCLI/lib/gcli/ui/menu.css */
.gcliOption {
.gcli-menu-option {
overflow: hidden;
white-space: nowrap;
cursor: pointer;
padding: 2px;
}
.gcliOption:hover {
.gcli-menu-option:hover {
background-color: rgb(230, 230, 230);
}
.gcliOptionName {
padding-right: 5px;
.gcli-menu-name {
padding-top: 0;
padding-bottom: 0;
-moz-padding-start: 10px;
-moz-padding-end: 2px;
}
.gcliOptionDesc {
.gcli-menu-desc {
font-size: 80%;
color: #999;
}
.gcliMenuError {
.gcli-menu-error {
overflow: hidden;
white-space: nowrap;
padding: 8px 2px 2px 2px;
padding-top: 8px;
padding-bottom: 2px;
-moz-padding-start: 10px;
-moz-padding-end: 2px;
font-size: 80%;
color: red;
}
.gcliMenuField {
background-color: white;
color: black;
border: 1px solid #aaa;
padding: 2px;
max-height: 300px;
overflow-y: auto;
max-width: 220px;
overflow-x: hidden;
margin: 0px 10px;
border-top: 0px !important;
border-bottom-right-radius: 5px;
border-bottom-left-radius: 5px;
}
/* From: $GCLI/lib/gcli/ui/inputter.css */
.gcliCompletion {
.gcli-in-complete {
position: absolute;
z-index: -1000;
background-color: #DDD;
border: 1px transparent solid;
padding: 1px 1px 1px 2px;
}
.gcliCompletion {
color: #DDD;
}
.gcliINCOMPLETE {
.gcli-in-incomplete {
border-bottom: 2px dotted #999;
}
.gcliERROR {
.gcli-in-error {
border-bottom: 2px dotted #F00;
}
.gcliPrompt {
.gcli-in-ontab {
color: #999;
}
.gcli-in-closebrace {
color: #999;
}
.gcli-prompt {
color: #66F;
font-weight: bold;
}
.gcliCompl {
color: #999;
}
.gcliCloseBrace {
color: #999;
}

View File

@ -36,6 +36,9 @@
* ***** END LICENSE BLOCK ***** */
/* From: $GCLI/mozilla/gcli/ui/gcliterm.css */
/* Bug 678152 calls for UX review which will fix the color names */
.gcliterm-input-node,
.gcliterm-complete-node {
border: none;
@ -44,29 +47,38 @@
vertical-align: middle;
background-color: transparent;
font: 12px Consolas, "Lucida Console", monospace;
padding: 2px 0 0 16px;
}
.gcliterm-input-node {
padding-top: 2px;
padding-bottom: 0;
-moz-padding-start: 16px;
-moz-padding-end: 0;
}
.gcliterm-complete-node {
color: #FFF;
padding: 4px 4px 2px 21px;
padding-top: 4px;
padding-bottom: 2px;
-moz-padding-start: 21px;
-moz-padding-end: 4px;
}
.gcliVALID {
.gcli-in-valid {
border-bottom: none;
}
.gcliINCOMPLETE {
.gcli-in-incomplete {
color: #DDD;
border-bottom: 1px dotted #999;
}
.gcliERROR {
.gcli-in-error {
color: #DDD;
border-bottom: 1px dotted #F00;
}
.gcliCompl {
.gcli-in-ontab {
color: #999;
}
@ -75,167 +87,204 @@
width: 100%;
}
.gcliterm-argfetcher {
display: -moz-box;
-moz-box-flex: 1;
}
.gcliterm-hint-node {
color: #000;
background: rgba(250, 250, 250, 0.8);
border: 1px solid #AAA;
border-bottom: 0px !important;
border-top: 1px solid threedshadow;
border-bottom: 1px solid #FFF;
border-left: 1px solid threedshadow;
border-right: 1px solid threedshadow;
border-top-right-radius: 5px;
border-top-left-radius: 5px;
margin-left: 10px;
margin-right: 10px;
display: inline-block;
overflow: auto;
padding: 10px;
margin-bottom: -1px;
}
.gcliterm-hint-parent {
border-bottom: 1px solid #AAA;
width: 300px;
padding: 10px 10px 0;
border-top: 1px solid threedshadow;
border-bottom: 1px solid threedshadow;
}
.gcliCmdHelpRight {
.gcli-help-right {
text-align: right;
}
.gcliterm-menu {
display: -moz-box;
-moz-box-flex: 1;
}
.gcliterm-hint-nospace {
display: none;
}
/*
* The language of a console is not en_US or any other common language
* (i.e we don't attempt to translate 'console.log(x)')
* So we fix .gcliterm-input-node/.gcliterm-complete-node elements to be ltr.
* As a result we also want the hints to pop up on the left (above the prompt)
*/
.gcliterm-input-node,
.gcliterm-complete-node,
.gcliterm-display {
direction: ltr;
}
/*
* We want the stuff under .gcliterm-display to obey normal direction rules
* so we need to swap back when the document is in rtl mode.
* The selectors below are faster, but equivalent to:
* .gcliterm-display > *:-moz-locale-dir(rtl) {
* direction: rtl;
* }
* In non-performance critical situations the above is preferred due to it's
* greater resilience to refactoring
*/
.gcliterm-hint-parent:-moz-locale-dir(rtl),
.hud-output-node:-moz-locale-dir(rtl) {
direction: rtl;
}
/* From: $GCLI/mozilla/gcli/ui/gcliterm-pinstripe.css */
.gcliterm-complete-node {
padding-top: 6px !important;
}
/* From: $GCLI/lib/gcli/ui/arg_fetch.css */
.gcliCmdDesc {
.gcli-argfetch {
width: 100%;
box-sizing: border-box;
-moz-box-sizing: border-box;
}
.gcli-af-cmddesc {
font-weight: bold;
text-align: center;
margin-bottom: 5px;
border-bottom: 1px solid #ddd;
padding-bottom: 3px;
padding: 3px 10px 0;
}
.gcliParamGroup {
font-weight: bold;
.gcli-af-params {
padding: 0 10px;
width: 100%;
box-sizing: border-box;
-moz-box-sizing: border-box;
}
.gcliParamName {
.gcli-af-paramname {
text-align: right;
font-size: 90%;
}
.gcliParamError {
.gcli-af-required {
font-size: 90%;
color: #f66;
padding-left: 5px;
}
.gcli-af-error {
font-size: 80%;
color: #900;
}
.gcliParamSubmit {
.gcli-af-submit {
text-align: right;
}
.gcliGroupSymbol {
font-size: 90%;
color: #666;
}
.gcliRequired {
font-size: 80%;
color: #666;
}
.gcliParams {
.gcli-field {
width: 100%;
}
/* From: $GCLI/lib/gcli/ui/hinter.css */
.gcliHintParent {
color: #000;
background: rgba(250, 250, 250, 0.8);
border: 1px solid #AAA;
border-top-right-radius: 5px;
border-top-left-radius: 5px;
margin-left: 10px;
margin-right: 10px;
display: inline-block;
/* From: $GCLI/lib/gcli/ui/menu.css */
.gcli-menu {
width: 100%;
overflow: hidden;
}
.gcliHints {
overflow: auto;
padding: 10px;
display: inline-block;
.gcli-menu-field {
border: 1px solid #aaa;
border-top: 0;
border-bottom-right-radius: 5px;
border-bottom-left-radius: 5px;
max-height: 300px;
margin: 0 3px;
padding: 0;
}
.gcliHints ul {
margin: 0;
padding: 0 15px;
.gcli-menu-template {
border-collapse: collapse;
width: 100%;
margin: 10px 0;
}
/* From: $GCLI/lib/gcli/ui/menu.css */
.gcliOption {
.gcli-menu-option {
overflow: hidden;
white-space: nowrap;
cursor: pointer;
padding: 2px;
}
.gcliOption:hover {
.gcli-menu-option:hover {
background-color: rgb(230, 230, 230);
}
.gcliOptionName {
padding-right: 5px;
.gcli-menu-name {
padding-top: 0;
padding-bottom: 0;
-moz-padding-start: 10px;
-moz-padding-end: 2px;
}
.gcliOptionDesc {
.gcli-menu-desc {
font-size: 80%;
color: #999;
}
.gcliMenuError {
.gcli-menu-error {
overflow: hidden;
white-space: nowrap;
padding: 8px 2px 2px 2px;
padding-top: 8px;
padding-bottom: 2px;
-moz-padding-start: 10px;
-moz-padding-end: 2px;
font-size: 80%;
color: red;
}
.gcliMenuField {
background-color: white;
color: black;
border: 1px solid #aaa;
padding: 2px;
max-height: 300px;
overflow-y: auto;
max-width: 220px;
overflow-x: hidden;
margin: 0px 10px;
border-top: 0px !important;
border-bottom-right-radius: 5px;
border-bottom-left-radius: 5px;
}
/* From: $GCLI/lib/gcli/ui/inputter.css */
.gcliCompletion {
.gcli-in-complete {
position: absolute;
z-index: -1000;
background-color: #DDD;
border: 1px transparent solid;
padding: 1px 1px 1px 2px;
}
.gcliCompletion {
color: #DDD;
}
.gcliINCOMPLETE {
.gcli-in-incomplete {
border-bottom: 2px dotted #999;
}
.gcliERROR {
.gcli-in-error {
border-bottom: 2px dotted #F00;
}
.gcliPrompt {
.gcli-in-ontab {
color: #999;
}
.gcli-in-closebrace {
color: #999;
}
.gcli-prompt {
color: #66F;
font-weight: bold;
}
.gcliCompl {
color: #999;
}
.gcliCloseBrace {
color: #999;
}

View File

@ -36,6 +36,9 @@
* ***** END LICENSE BLOCK ***** */
/* From: $GCLI/mozilla/gcli/ui/gcliterm.css */
/* Bug 678152 calls for UX review which will fix the color names */
.gcliterm-input-node,
.gcliterm-complete-node {
border: none;
@ -44,29 +47,38 @@
vertical-align: middle;
background-color: transparent;
font: 12px Consolas, "Lucida Console", monospace;
padding: 2px 0 0 16px;
}
.gcliterm-input-node {
padding-top: 2px;
padding-bottom: 0;
-moz-padding-start: 16px;
-moz-padding-end: 0;
}
.gcliterm-complete-node {
color: #FFF;
padding: 4px 4px 2px 21px;
padding-top: 4px;
padding-bottom: 2px;
-moz-padding-start: 21px;
-moz-padding-end: 4px;
}
.gcliVALID {
.gcli-in-valid {
border-bottom: none;
}
.gcliINCOMPLETE {
.gcli-in-incomplete {
color: #DDD;
border-bottom: 1px dotted #999;
}
.gcliERROR {
.gcli-in-error {
color: #DDD;
border-bottom: 1px dotted #F00;
}
.gcliCompl {
.gcli-in-ontab {
color: #999;
}
@ -75,167 +87,200 @@
width: 100%;
}
.gcliterm-argfetcher {
display: -moz-box;
-moz-box-flex: 1;
}
.gcliterm-hint-node {
color: #000;
background: rgba(250, 250, 250, 0.8);
border: 1px solid #AAA;
border-bottom: 0px !important;
border-top: 1px solid threedshadow;
border-bottom: 1px solid #FFF;
border-left: 1px solid threedshadow;
border-right: 1px solid threedshadow;
border-top-right-radius: 5px;
border-top-left-radius: 5px;
margin-left: 10px;
margin-right: 10px;
display: inline-block;
overflow: auto;
padding: 10px;
margin-bottom: -1px;
}
.gcliterm-hint-parent {
border-bottom: 1px solid #AAA;
width: 300px;
padding: 10px 10px 0;
border-top: 1px solid threedshadow;
border-bottom: 1px solid threedshadow;
}
.gcliCmdHelpRight {
.gcli-help-right {
text-align: right;
}
.gcliterm-menu {
display: -moz-box;
-moz-box-flex: 1;
}
.gcliterm-hint-nospace {
display: none;
}
/*
* The language of a console is not en_US or any other common language
* (i.e we don't attempt to translate 'console.log(x)')
* So we fix .gcliterm-input-node/.gcliterm-complete-node elements to be ltr.
* As a result we also want the hints to pop up on the left (above the prompt)
*/
.gcliterm-input-node,
.gcliterm-complete-node,
.gcliterm-display {
direction: ltr;
}
/*
* We want the stuff under .gcliterm-display to obey normal direction rules
* so we need to swap back when the document is in rtl mode.
* The selectors below are faster, but equivalent to:
* .gcliterm-display > *:-moz-locale-dir(rtl) {
* direction: rtl;
* }
* In non-performance critical situations the above is preferred due to it's
* greater resilience to refactoring
*/
.gcliterm-hint-parent:-moz-locale-dir(rtl),
.hud-output-node:-moz-locale-dir(rtl) {
direction: rtl;
}
/* From: $GCLI/mozilla/gcli/ui/gcliterm-winstripe.css */
/* From: $GCLI/lib/gcli/ui/arg_fetch.css */
.gcliCmdDesc {
.gcli-argfetch {
width: 100%;
box-sizing: border-box;
-moz-box-sizing: border-box;
}
.gcli-af-cmddesc {
font-weight: bold;
text-align: center;
margin-bottom: 5px;
border-bottom: 1px solid #ddd;
padding-bottom: 3px;
padding: 3px 10px 0;
}
.gcliParamGroup {
font-weight: bold;
.gcli-af-params {
padding: 0 10px;
width: 100%;
box-sizing: border-box;
-moz-box-sizing: border-box;
}
.gcliParamName {
.gcli-af-paramname {
text-align: right;
font-size: 90%;
}
.gcliParamError {
.gcli-af-required {
font-size: 90%;
color: #f66;
padding-left: 5px;
}
.gcli-af-error {
font-size: 80%;
color: #900;
}
.gcliParamSubmit {
.gcli-af-submit {
text-align: right;
}
.gcliGroupSymbol {
font-size: 90%;
color: #666;
}
.gcliRequired {
font-size: 80%;
color: #666;
}
.gcliParams {
.gcli-field {
width: 100%;
}
/* From: $GCLI/lib/gcli/ui/hinter.css */
.gcliHintParent {
color: #000;
background: rgba(250, 250, 250, 0.8);
border: 1px solid #AAA;
border-top-right-radius: 5px;
border-top-left-radius: 5px;
margin-left: 10px;
margin-right: 10px;
display: inline-block;
/* From: $GCLI/lib/gcli/ui/menu.css */
.gcli-menu {
width: 100%;
overflow: hidden;
}
.gcliHints {
overflow: auto;
padding: 10px;
display: inline-block;
.gcli-menu-field {
border: 1px solid #aaa;
border-top: 0;
border-bottom-right-radius: 5px;
border-bottom-left-radius: 5px;
max-height: 300px;
margin: 0 3px;
padding: 0;
}
.gcliHints ul {
margin: 0;
padding: 0 15px;
.gcli-menu-template {
border-collapse: collapse;
width: 100%;
margin: 10px 0;
}
/* From: $GCLI/lib/gcli/ui/menu.css */
.gcliOption {
.gcli-menu-option {
overflow: hidden;
white-space: nowrap;
cursor: pointer;
padding: 2px;
}
.gcliOption:hover {
.gcli-menu-option:hover {
background-color: rgb(230, 230, 230);
}
.gcliOptionName {
padding-right: 5px;
.gcli-menu-name {
padding-top: 0;
padding-bottom: 0;
-moz-padding-start: 10px;
-moz-padding-end: 2px;
}
.gcliOptionDesc {
.gcli-menu-desc {
font-size: 80%;
color: #999;
}
.gcliMenuError {
.gcli-menu-error {
overflow: hidden;
white-space: nowrap;
padding: 8px 2px 2px 2px;
padding-top: 8px;
padding-bottom: 2px;
-moz-padding-start: 10px;
-moz-padding-end: 2px;
font-size: 80%;
color: red;
}
.gcliMenuField {
background-color: white;
color: black;
border: 1px solid #aaa;
padding: 2px;
max-height: 300px;
overflow-y: auto;
max-width: 220px;
overflow-x: hidden;
margin: 0px 10px;
border-top: 0px !important;
border-bottom-right-radius: 5px;
border-bottom-left-radius: 5px;
}
/* From: $GCLI/lib/gcli/ui/inputter.css */
.gcliCompletion {
.gcli-in-complete {
position: absolute;
z-index: -1000;
background-color: #DDD;
border: 1px transparent solid;
padding: 1px 1px 1px 2px;
}
.gcliCompletion {
color: #DDD;
}
.gcliINCOMPLETE {
.gcli-in-incomplete {
border-bottom: 2px dotted #999;
}
.gcliERROR {
.gcli-in-error {
border-bottom: 2px dotted #F00;
}
.gcliPrompt {
.gcli-in-ontab {
color: #999;
}
.gcli-in-closebrace {
color: #999;
}
.gcli-prompt {
color: #66F;
font-weight: bold;
}
.gcliCompl {
color: #999;
}
.gcliCloseBrace {
color: #999;
}

View File

@ -56,6 +56,7 @@ endif
DIRS += pgo
ifdef ENABLE_TESTS
DIRS += autoconf/test
ifeq (android,$(MOZ_WIDGET_TOOLKIT))
DIRS += mobile/sutagent/android \
mobile/sutagent/android/watcher \
@ -65,6 +66,60 @@ ifeq (android,$(MOZ_WIDGET_TOOLKIT))
endif
endif
ifdef MOZ_APP_BASENAME
DIST_FILES = application.ini
ifdef LIBXUL_SDK
GRE_MILESTONE = $(shell $(PYTHON) $(topsrcdir)/config/printconfigsetting.py $(LIBXUL_DIST)/bin/platform.ini Build Milestone)
APP_INI_DEPS = $(LIBXUL_DIST)/bin/platform.ini
else
GRE_MILESTONE = $(shell tail -n 1 $(topsrcdir)/config/milestone.txt 2>/dev/null || tail -1 $(topsrcdir)/config/milestone.txt)
APP_INI_DEPS = $(topsrcdir)/config/milestone.txt
endif
APP_BUILDID := $(shell cat $(DEPTH)/config/buildid)
APP_INI_DEPS += $(DEPTH)/config/buildid
DEFINES += -DGRE_MILESTONE=$(GRE_MILESTONE) -DAPP_BUILDID=$(APP_BUILDID)
DEFINES += -DMOZ_APP_VERSION="$(MOZ_APP_VERSION)"
APP_INI_DEPS += $(DEPTH)/config/autoconf.mk
MOZ_SOURCE_STAMP ?= $(firstword $(shell hg -R $(topsrcdir) parent --template="{node|short}\n" 2>/dev/null))
ifdef MOZ_SOURCE_STAMP
DEFINES += -DMOZ_SOURCE_STAMP="$(MOZ_SOURCE_STAMP)"
endif
_dollar=$$
SOURCE_REPO := $(shell cd $(topsrcdir) && hg showconfig paths.default 2>/dev/null | head -n1 | sed -e "s/^ssh:/http:/" -e "s/\/$(_dollar)//" )
ifdef SOURCE_REPO
DEFINES += -DMOZ_SOURCE_REPO="$(SOURCE_REPO)"
endif
DEFINES += \
-DMOZ_APP_BASENAME="$(MOZ_APP_BASENAME)" \
-DMOZ_APP_VENDOR="$(MOZ_APP_VENDOR)" \
-DMOZ_APP_ID="$(MOZ_APP_ID)" \
$(NULL)
ifdef MOZ_APP_PROFILE
DEFINES += -DMOZ_APP_PROFILE="$(MOZ_APP_PROFILE)"
endif
ifdef MOZILLA_OFFICIAL
DEFINES += -DMOZILLA_OFFICIAL
endif
ifdef MOZ_PROFILE_MIGRATOR
DEFINES += -DMOZ_PROFILE_MIGRATOR
endif
ifdef MOZ_EXTENSION_MANAGER
DEFINES += -DMOZ_EXTENSION_MANAGER
endif
endif
include $(topsrcdir)/config/rules.mk
# we install to _leaktest/
@ -99,6 +154,19 @@ leaktest.py: leaktest.py.in
chmod +x $@
GARBAGE += leaktest.py
ifdef MOZ_APP_BASENAME
application.ini: application.ini.in $(APP_INI_DEPS)
$(PYTHON) $(topsrcdir)/config/Preprocessor.py $(DEFINES) $< > $@
GARBAGE += application.ini
ifdef MOZ_APP_STATIC_INI
application.ini.h: appini_header.py application.ini
$(PYTHON) $^ > $@
export:: application.ini.h
GARBAGE += application.ini.h
endif
endif
libs:: $(_LEAKTEST_FILES)
$(INSTALL) $^ $(_LEAKTEST_DIR)

86
build/appini_header.py Normal file
View File

@ -0,0 +1,86 @@
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is a build helper for libraries
#
# The Initial Developer of the Original Code is
# the Mozilla Foundation
# Portions created by the Initial Developer are Copyright (C) 2011
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Mike Hommey <mh@glandium.org>
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
'''Parses a given application.ini file and outputs the corresponding
XULAppData structure as a C++ header file'''
import ConfigParser
import sys
def main(file):
config = ConfigParser.RawConfigParser()
config.read(file)
flags = set()
try:
if config.getint('XRE', 'EnableExtensionManager') == 1:
flags.add('NS_XRE_ENABLE_EXTENSION_MANAGER')
except: pass
try:
if config.getint('XRE', 'EnableProfileMigrator') == 1:
flags.add('NS_XRE_ENABLE_PROFILE_MIGRATOR')
except: pass
try:
if config.getint('Crash Reporter', 'Enabled') == 1:
flags.add('NS_XRE_ENABLE_CRASH_REPORTER')
except: pass
appdata = dict(("%s:%s" % (s, o), config.get(s, o)) for s in config.sections() for o in config.options(s))
appdata['flags'] = ' | '.join(flags) if flags else '0'
appdata['App:profile'] = '"%s"' % appdata['App:profile'] if 'App:profile' in appdata else 'NULL'
print '''#include "nsXULAppAPI.h"
static const nsXREAppData sAppData = {
sizeof(nsXREAppData),
NULL, // directory
"%(App:vendor)s",
"%(App:name)s",
"%(App:version)s",
"%(App:buildid)s",
"%(App:id)s",
NULL, // copyright
%(flags)s,
NULL, // xreDirectory
"%(Gecko:minversion)s",
"%(Gecko:maxversion)s",
"%(Crash Reporter:serverurl)s",
%(App:profile)s
};''' % appdata
if __name__ == '__main__':
if len(sys.argv) != 1:
main(sys.argv[1])
else:
print >>sys.stderr, "Usage: %s /path/to/application.ini" % sys.argv[0]

View File

@ -1,3 +1,9 @@
#if MOZ_APP_STATIC_INI
; This file is not used. If you modify it and want the application to use
; your modifications, start with the "-app /path/to/application.ini"
; argument.
#endif
#if 0
; ***** BEGIN LICENSE BLOCK *****
; Version: MPL 1.1/GPL 2.0/LGPL 2.1
;
@ -34,34 +40,38 @@
; the terms of any one of the MPL, the GPL or the LGPL.
;
; ***** END LICENSE BLOCK *****
#endif
#filter substitution
[App]
Vendor=@MOZ_APP_VENDOR@
Name=@MOZ_APP_BASENAME@
Version=@APP_VERSION@
Version=@MOZ_APP_VERSION@
#ifdef MOZ_APP_PROFILE
Profile=@MOZ_APP_PROFILE@
#endif
BuildID=@GRE_BUILDID@
BuildID=@APP_BUILDID@
#ifdef MOZ_SOURCE_REPO
SourceRepository=@MOZ_SOURCE_REPO@
#endif
#ifdef MOZ_SOURCE_STAMP
SourceStamp=@MOZ_SOURCE_STAMP@
#endif
ID={ec8030f7-c20a-464f-9b0e-13a3a9e97384}
ID=@MOZ_APP_ID@
[Gecko]
MinVersion=@GRE_MILESTONE@
MaxVersion=@GRE_MILESTONE@
[XRE]
#ifdef MOZ_PROFILE_MIGRATOR
EnableProfileMigrator=1
#endif
#ifdef MOZ_EXTENSION_MANAGER
EnableExtensionManager=1
#endif
[Crash Reporter]
#if MOZILLA_OFFICIAL
Enabled=1
#endif
ServerURL=https://crash-reports.mozilla.com/submit?id=ec8030f7-c20a-464f-9b0e-13a3a9e97384&version=@APP_VERSION@&buildid=@GRE_BUILDID@
ServerURL=https://crash-reports.mozilla.com/submit?id=@MOZ_APP_ID@&version=@MOZ_APP_VERSION@&buildid=@APP_BUILDID@

View File

@ -1,4 +1,4 @@
#! /usr/bin/env perl
#!/usr/bin/env perl
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
@ -16,10 +16,12 @@
#
# The Initial Developer of the Original Code is
# Netscape Communications Corporation.
# Portions created by the Initial Developer are Copyright (C) 1999
# Portions created by the Initial Developer are Copyright (C) 1999-2011
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Steve Lamm <slamm@netscape.com>
# Joey Armstrong <joey@mozilla.com>
#
# Alternatively, the contents of this file may be used under the terms of
# either of the GNU General Public License Version 2 or later (the "GPL"),
@ -35,29 +37,81 @@
#
# ***** END LICENSE BLOCK *****
# make-makefiles - Quickly create Makefiles for subdirectories.
# Also, creates any needed subdirectories.
#
# usage: make-makefiles [ -t <topsrcdir> -p <print_topsrcdir> -d <depth> ] [ <subdir> | <subdir>/Makefile ] ...
##----------------------------##
##---] CORE/CPAN INCLUDES [---##
##----------------------------##
use strict;
use warnings;
use Getopt::Long;
# Send comments, improvements, bugs to Steve Lamm (slamm@netscape.com).
use Benchmark;
use Cwd;
use File::Basename;
use File::Copy;
use File::Path qw{mkpath};
#$debug = 1;
##-------------------##
##---] EXPORTS [---##
##-------------------##
our $VERSION = qw(2.0);
if ($^O eq 'msys') {
$pwdcmd = 'pwd -W';
##--------------------##
##---] INCLUDES [---##
##--------------------##
##############################################################
# pymake: special case path handling for windows cmd shell.
# if invoked by cmd.exe and msys-perl is in play
# $0 may contain a drive letter
# modules use-or-expect msys/unix paths
# adjust $0 => C:/foo => /c/foo so string tests and
# manipulation can by applied properly.
##############################################################
sub BEGIN
{
if ($^O eq 'msys' && $ENV{PATH} =~ m!\w:/!)
{
$0 =~ s!^(\w):!/$1!;
}
eval 'use FindBin';
die $@ if ($@);
}
else {
$pwdcmd = 'pwd';
use lib $FindBin::Bin;
use makemakefile;
##-------------------##
##---] GLOBALS [---##
##-------------------##
my %argv;
my $t0 = Benchmark->new();
sub END
{
if ($argv{bench})
{
my $t1 = Benchmark->new();
my $delta = timediff($t1, $t0);
print STDERR timestr($delta), "\n";
}
}
##----------------##
##---] MAIN [---##
##----------------##
umask 0;
my $debug = $argv{debug} || 0;
my $pwdcmd = ($^O eq 'msys') ? 'pwd -W' : 'pwd';
# Determine various tree path variables
#
($topsrcdir, $ptopsrcdir, $depth, @makefiles) = parse_arguments(@ARGV);
my ($topsrcdir, $ptopsrcdir, $depth, @makefiles) = parse_arguments(@ARGV);
$object_fullpath = `$pwdcmd`;
my $object_fullpath = `$pwdcmd`; # Cwd::getcwd()
chdir $depth;
$object_root = `$pwdcmd`;
my $object_root = `$pwdcmd`; # Cwd::getcwd()
chomp $object_fullpath;
chomp $object_root;
@ -65,24 +119,23 @@ chomp $object_root;
# 'make-makefile' was called. For example, if make-makefile was
# called from "mozilla/gfx/src", then $source_subdir would be
# "gfx/src/".
$source_subdir = "$object_fullpath/";
my $source_subdir = "$object_fullpath/";
my $quoted_object_root = quotemeta($object_root);
$source_subdir =~ s|^$quoted_object_root/||;
# Prefix makefiles with $source_subdir so that paths
# will be relative to the top of the object tree.
#
for $makefile (@makefiles) {
my $makefile;
for $makefile (@makefiles) { # dead code ?
$makefile = "$source_subdir$makefile";
}
create_directories(@makefiles);
# Find the path to the source directory based on how 'make-makefile'
# was invoked. The path is either relative to the object directory
# or an absolute path.
$given_srcdir = find_srcdir($topsrcdir, $depth);
$pgiven_srcdir = find_srcdir($ptopsrcdir, $depth);
my $given_srcdir = find_srcdir($topsrcdir, $depth);
my $pgiven_srcdir = find_srcdir($ptopsrcdir, $depth);
if ($debug) {
warn "object_fullpath = $object_fullpath\n";
@ -92,18 +145,21 @@ if ($debug) {
warn "given_srcdir = $given_srcdir\n";
}
@unhandled = update_makefiles($given_srcdir, $pgiven_srcdir, @makefiles);
my @errors;
my @unhandled = update_makefiles_legacy($given_srcdir, $pgiven_srcdir, @makefiles);
push(@errors, $@) if ($@);
run_config_status(@unhandled);
push(@errors, $@) if ($@ && $argv{'no-warnings'});
exit scalar(@errors);
# end of Main
############################################################
sub dirname {
return $_[0] =~ /(.*)\/.*/ ? "$1" : '.';
}
###########################################################################
# find_depth: Pull the value of DEPTH out of a Makefile (or Makefile.in)
###########################################################################
sub find_depth {
my $depth = '';
open(MAKEFILE, "<$_[0]") || die "Unable to open $_[0]: $!\n";
@ -116,39 +172,115 @@ sub find_depth {
return $depth;
}
###########################################################################
## Intent: Parse command line arguments and assign values
###########################################################################
sub parse_arguments {
my @args = @_;
my $depth = '';
my $topsrcdir = '';
my $ptopsrcdir;
my @makefiles = ();
while (1) {
if ($args[0] eq '-d') {
$depth = $args[1];
shift @args;
shift @args;
} elsif ($args[0] eq '-t') {
$topsrcdir = $args[1];
shift @args;
shift @args;
} elsif ($args[0] eq '-p') {
$ptopsrcdir = $args[1];
shift @args;
shift @args;
} else {
last;
}
my @arglist = qw(badtokens! bench
chdir=s
debug
depth|d=s
enhanced
obj=s top|t=s ptop|p=s
src=s dst=s
);
unless(GetOptions(\%argv, @arglist))
{
my $script = join('/', $FindBin::RealBin, $FindBin::Script);
system("perldoc $script </dev/null");
exit
}
@args = @ARGV;
my $topsrcdir = $argv{top} || '';
if (! $topsrcdir)
{
$topsrcdir = $argv{top} = getTopDir();
}
if ($topsrcdir eq '') {
$topsrcdir = $0; # Figure out topsrcdir based on program name.
$topsrcdir =~ s|/?build/autoconf/.*$||;
my $ptopsrcdir ||= $argv{ptop} || $topsrcdir || '';
## Init --no- switch values
foreach my $var (qw(badtokens exclusions warnings))
{
$argv{"no-${var}"} = $argv{$var} || 0;
}
if ($ptopsrcdir eq '') {
$ptopsrcdir = $topsrcdir;
# Propogate parsed arguments for module use [--debug, --verbose]
while (my($k, $v) = each %argv)
{
$main::argv{$k} = $v;
}
if ($depth eq '') {
if ($argv{chdir})
{
chdir $argv{chdir} || die "chdir $argv{chdir} failed: $!";
}
##############################################################
## Arguments allowing make-makefile to be invoked from $topsrc
##############################################################
if (!$argv{top} || !$argv{obj})
{
}
## Limit access to container makefiles for now
elsif ($argv{enhanced})
{
my @errors;
## iterate over @ARGV to preserve original filename for 'unhandled'
my @files = map{ getRelPath($_) } @ARGV;
my $top = getTopDir();
my $obj = getObjDir();
mkdirr(map{ "$obj/$_" } @files);
push(@errors, $@) if ($@); # legacy behavior: do not exit with status
my $exclude = join('/', $FindBin::RealBin, $FindBin::Script);
$exclude .= '.excl'; # $argv{exclude}
my %exclude = getExclusions($exclude);
my @unhandled;
foreach my $relpath (@files)
{
my $rel = join('/', $relpath, 'Makefile.in');
my $mf = join('/', $top, $rel);
next if ($exclude{$rel});
print STDERR " ** relpath=[$relpath], mf=[$mf]\n" if ($main::argv{debug});
my $rc = updateMakefiles($relpath, {depth=>$depth, obj=>$obj, top=>$top});
if ($@)
{
push(@errors, $@);
}
elsif ($rc eq 'badtokens')
{
push(@unhandled, $mf);
}
}
run_config_status(@unhandled);
push(@errors, $@) if ($@ && $argv{'no-warnings'});
exit scalar(@errors);
}
my $depth = $argv{depth} || '';
if (! $depth)
{
foreach my $fyl (@args)
{
if (my $tmp = find_depth($fyl))
{
$depth = $tmp;
last;
}
}
}
if (! $depth) {
# Use $(DEPTH) in the Makefile or Makefile.in to determine the depth
if (-e "Makefile.in") {
$depth = find_depth("Makefile.in");
@ -166,34 +298,21 @@ sub parse_arguments {
# Build the list of makefiles to generate
#
@makefiles = ();
my $makefile;
foreach $makefile (@args) {
$makefile =~ s/\.in$//;
$makefile =~ s/\/$//;
$makefile =~ /Makefile$/
or $makefile =~ /^\.\//
or $makefile .= "/Makefile";
while (@args)
{
next unless my $makefile = shift @args;
$makefile =~ s/\.in$//;
$makefile =~ s/\/$//;
$makefile =~ /Makefile$/
or $makefile =~ /^\.\//
or $makefile .= "/Makefile";
push @makefiles, "$makefile";
}
@makefiles = "Makefile" unless @args;
@makefiles = "Makefile" unless @makefiles;
return ($topsrcdir, $ptopsrcdir, $depth, @makefiles);
}
# Create all the directories at once.
# This can be much faster than calling mkdir() for each one.
sub create_directories {
my @makefiles = @_;
my @dirs = ();
my $ac_file;
foreach $ac_file (@makefiles) {
push @dirs, dirname($ac_file);
}
# Call mkdir with the directories sorted by subdir count (how many /'s)
system "mkdir -p ". join(' ', map("\"$_\"", @dirs)) if @dirs;
}
# Find the top of the source directory
# (Assuming that the executable is in $top_srcdir/build/autoconf)
sub find_srcdir {
@ -214,111 +333,146 @@ sub find_srcdir {
return $ac_given_srcdir;
}
# Output the makefiles.
#
sub update_makefiles {
my ($ac_given_srcdir, $pac_given_srcdir, @makefiles) = @_;
my @unhandled=();
1;
###########################################################################
## perldoc
###########################################################################
__END__
my $ac_file;
foreach $ac_file (@makefiles) {
my $ac_file_in = "$ac_given_srcdir/${ac_file}.in";
my $ac_dir = dirname($ac_file);
my $ac_dots = '';
my $ac_dir_suffix = '';
my $srcdir = '.';
my $top_srcdir = '.';
=head1 NAME
# Determine $srcdir and $top_srcdir
#
if ($ac_dir ne '.') {
$ac_dir_suffix = "/$ac_dir";
$ac_dir_suffix =~ s%^/\./%/%;
$ac_dots = $ac_dir_suffix;
# Remove .. components from the provided dir suffix, and
# also the forward path components they were reversing.
my $backtracks = $ac_dots =~ s%\.\.(/|$)%%g;
while ($backtracks--) {
$ac_dots =~ s%/[^/]*%%;
}
$ac_dots =~ s%/[^/]*%../%g;
}
if ($ac_given_srcdir eq '.') {
if ($ac_dots ne '') {
$top_srcdir = $ac_dots;
$top_srcdir =~ s%/$%%;
}
} elsif ($pac_given_srcdir =~ m%^/% or $pac_given_srcdir =~ m%^.:/%) {
$srcdir = "$pac_given_srcdir$ac_dir_suffix";
$top_srcdir = "$pac_given_srcdir";
} else {
if ($debug) {
print "ac_dots = $ac_dots\n";
print "ac_dir_suffix = $ac_dir_suffix\n";
}
$srcdir = "$ac_dots$ac_given_srcdir$ac_dir_suffix";
$top_srcdir = "$ac_dots$ac_given_srcdir";
}
make-makefile - Generate a Makefile from a F<Makefile.in> template
if ($debug) {
print "ac_dir = $ac_dir\n";
print "ac_file = $ac_file\n";
print "ac_file_in = $ac_file_in\n";
print "srcdir = $srcdir\n";
print "top_srcdir = $top_srcdir\n";
print "cwd = " . `$pwdcmd` . "\n";
}
=head1 SYNOPSIS
# Copy the file and make substitutions.
# @srcdir@ -> value of $srcdir
# @top_srcdir@ -> value of $top_srcdir
#
if (-e $ac_file) {
next if -M _ < -M $ac_file_in; # Next if Makefile is up-to-date.
warn "updating $ac_file\n";
} else {
warn "creating $ac_file\n";
}
make-makefile [--top t] [--obj o] [--depth d] foo/bar/Makefile.in tans/fans/Makefile foo/bar
open INFILE, "<$ac_file_in" or do {
warn "$0: Cannot read $ac_file_in: No such file or directory\n";
next;
};
open OUTFILE, ">$ac_file" or do {
warn "$0: Unable to create $ac_file\n";
next;
};
=head1 DESCRIPTION
while (<INFILE>) {
#if (/\@[_a-zA-Z]*\@.*\@[_a-zA-Z]*\@/) {
# #warn "Two defines on a line:$ac_file:$.:$_";
# push @unhandled, $ac_file;
# last;
#}
Given options and makefile path arguments determine path to the template
F<Makefile.in> beneath a source directory and path to generated F<Makefile>
beneath $MOZ_OBJDIR. DEPTH from destination directory to the 'root' will
also be determined. F<Makefile.in> will be read in, template strings of the
gorm @token@ will be replaced with derived values and a generated makefile
will be written out as F<Makefile>.
s/\@srcdir\@/$srcdir/g;
s/\@top_srcdir\@/$top_srcdir/g;
Makefile DEPTH= can be determined in a few different ways:
o The string C<DEPTH=../../..> may be embedded within F<Makefile.in>.
o Search parent directories for F<Makefile.in> and use it to assign the child.
if (/\@[_a-zA-Z]*\@/) {
#warn "Unknown variable:$ac_file:$.:$_";
push @unhandled, $ac_file;
last;
}
print OUTFILE;
}
close INFILE;
close OUTFILE;
}
return @unhandled;
}
sub run_config_status {
my @unhandled = @_;
=head2 Option List
# Run config.status with any unhandled files.
#
if (@unhandled) {
$ENV{CONFIG_FILES}= join ' ', @unhandled;
system "./config.status";
}
}
=over 4
=item --chdir
Move to this directory before doing anything else
=item -d, --depth
Explicitly specify the relative path from directory containing Makefile.in
to the top sandbox directory. memory/makefile, DEPTH=../.., js/src/config, DEPTH=..
=item --enhanced
Use alternate/simplified path construction when options --top and --obj are
passed. This feature will be used by container makefiles to support makefile
generation while cd'd into the sandbox top directory.
=item -t, --top
Path the root of a development sandbox.
=item --obj
Path to object directory where generated makefile will be written ($MOZ_OBJDIR).
=item --ptop
Print top source dir
=back
=head2 Options List DEBUG
=over 4
=item --bench
Enable script benchmarking, report elapsed runtime.
=item --debug
Enable script debug mode.
=back
=head2 Options List --NO-
=over 4
=item --no-badtokens (wip)
Handle unexpanded @token@ makefile tokens as an error condition.
Do not rely on system(config.status) to externally supply values.
=item --no-excludes
Ignore file entries on the exclusion list, generate everything.
=item --no-warnings
Warnings are handled as an error condition.
=back
=head2 Examples
=over 4
=item * make-makefile -t /mozilla/nightly -d . memory/mozalloc
cd $MOZ_OBJDIR;
--top and --depth are explicitly set for generting memory/mozalloc/Makefile.
=item * make-makefile -t /mozilla/nightly -d ../../../.. html5lib_tree_construction/Makefile
cd $MOZ_OBJDIR/parser/htmlparser/tests/mochitest
--top and --depth are explicitly set for generting a makefile from within
a subdirectory of $MOZ_OBJDIR
=item * make-makefile --top /mozilla/nightly --obj /mozilla/nightly/obj memory/mozalloc
With --top and --obj explicitly set generate $MOZ_OBJDIR/memory/mozalloc/Makefile
while sitting in the sandbox root.
=back
=head2 Work In Progress
=over 4
=item --no-badtokens
Fail on unexpanded @foo@ makefile tokens. Any tokens that can be expanded
directly by make-makefile will avoid config.status shell overhead.
=item Depth from delta(--obj, --top)
If DEPTH= has not been embedded within a makefile the value could
be set directly if --top and --obj are specified and the paths overlap.
=back
=head1 SEE ALSO
L<config/rules.mk>
=cut

View File

@ -0,0 +1,5 @@
###########################################################################
## Intent: Exclusion list for container make builds
###########################################################################
# EOF

View File

@ -0,0 +1,745 @@
package makemakefile;
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is
# Netscape Communications Corporation.
# Portions created by the Initial Developer are Copyright (C) 1999-2011
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Steve Lamm <slamm@netscape.com>
# Joey Armstrong <joey@mozilla.com>
#
# Alternatively, the contents of this file may be used under the terms of
# either of the GNU General Public License Version 2 or later (the "GPL"),
# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
##----------------------------##
##---] CORE/CPAN INCLUDES [---##
##----------------------------##
use strict;
use warnings;
# use feature 'state'; 5.10+ not available everywhere
##-------------------##
##---] EXPORTS [---##
##-------------------##
our $VERSION = qw(2.0);
use Exporter;
our @ISA = qw(Exporter);
our @EXPORT = qw(dirname_legacy
getConfig getDepth getRelPath getObjDir getTopDir mkdirr
getExclusions
run_config_status
updateMakefiles
update_makefiles_legacy
);
##--------------------##
##---] INCLUDES [---##
##--------------------##
use Cwd;
use Cwd qw{abs_path};
use FindBin;
use File::Basename;
use File::Copy;
##-------------------##
##---] GLOBALS [---##
##-------------------##
umask 0;
my $cwd = Cwd::abs_path('.');
my %argv;
###########################################################################
## Intent: Helper function, retrieve contents of a file with error checking
## -----------------------------------------------------------------------
## Args:
## scalar path to input file
## Returns:
## array contents of the given file
## $@ set on error
###########################################################################
sub cat
{
my $fyl = shift || '';
$@ = '';
my @data;
local *FYL;
if (!open(FYL, $fyl))
{
$@ = "open($fyl) failed: $!";
}
else
{
@data = <FYL>;
close(FYL);
}
return @data;
} # cat
###########################################################################
## Intent: Return directory path for a given argument
## -----------------------------------------------------------------------
## -----------------------------------------------------------------------
## Todo:
## o Check if function can be replaced by File::Basename::dirname()
###########################################################################
sub dirname_legacy
{
my $str = (@_ && defined($_[0])) ? shift : '';
return $str =~ /(.*)\/.*/ ? "$1" : '.';
}
###########################################################################
## Intent: Given a list of makefile paths recursively create all
## directories between file and the root
## -----------------------------------------------------------------------
## Args:
## array A list of makefiles
## fargs Function arguments
## mode Filesystem mode used for directory creation
## Returns:
## $@ Set on error
## 0 on success
## -----------------------------------------------------------------------
## Note:
## Reporting directory creation can be enabled by the --verbose
## command line argument.
###########################################################################
sub mkdirr
{
my %fargs = (@_ && ref($_[$#_])) ? %{ (pop) } : ();
my $mode = $fargs{mode} || 0755;
my $verbose = $main::argv{verbose} || 0;
$@ = '' unless ($fargs{recursive});
$fargs{recursive} = 1;
my @errors;
push(@errors, $@) if ($@);
foreach my $path (@_)
{
(my $dir = $path) =~ s%/?Makefile[^/]*$%%o;
next unless (length($dir));
next if (-e $dir);
mkdirr( dirname($dir), \%fargs);
eval{ File::Path::mkpath($dir, $verbose, 0755); };
push(@errors, $@) if ($@);
}
$@ = join("\n", @errors);
return $@ ? 0 : 1;
} # mkdirr
###########################################################################
## Intent: Read in configure values and return a hash of key/value pairs
## -----------------------------------------------------------------------
## Args:
## fargs Function arguments
## reset clear value storage and repopulate
## Returns:
## hash configure data to use for makefile substitutions
## -----------------------------------------------------------------------
## Todo: wrapper for reading config* and run_config_status
###########################################################################
my %_CONFIG_; # todo: state %config; w/5.10
sub getConfig
{
my %fargs = (@_ && ref($_[$#_]) eq 'HASH') ? %{ (pop) } : ();
if ($fargs{reset})
{
%_CONFIG_ = ();
shift;
}
#my $ac_file_in = "$ac_given_srcdir/${ac_file}.in";
#my $ac_dir = dirname_legacy($ac_file);
#my $ac_dots = '';
#my $ac_dir_suffix = '';
#my $srcdir = '.';
#my $top_srcdir = '.';
unless (%_CONFIG_)
{
while (@_)
{
my ($k, $v) = splice(@_, 0, 2);
$_CONFIG_{$k} = $v;
}
}
return %_CONFIG_;
} # getConfig
###########################################################################
## Intent: Determine path depth between leaf and root directory.
## o DEPTH= may be set by makefile content
## o DEPTH= may be set by Makefile in a parent
## o Manually determine by relpath form leaf to sandbox top
## -----------------------------------------------------------------------
## Args:
## scalar Path to makefile or directory to determine DEPTH for
## Returns:
## scalar Relative path from leaf to root directory
## -----------------------------------------------------------------------
###########################################################################
sub getDepth($)
{
my $fyl = shift || '';
my @path = split(m%/%o, $fyl);
pop(@path) if ('Makefile' eq substr($path[$#path], 0, 8));
my $depth;
my @depth;
my $top = getTopDir();
my @top = split(m%/%o, $top);
my @pathNoTop = @path;
splice(@pathNoTop, 0, scalar(@top));
SEARCH:
while (@path)
{
## Search for a file containing DEPTH=../..
foreach my $fyl ( qw{Makefile.in Makefile} )
{
my $path = join('/', @path, $fyl);
local *FYL;
if (!open(FYL, $path)) {} # NOP
elsif (my @tmp = map{ /^\s*DEPTH\s*=\s*([\.\/]+)/o ? $1 : () } <FYL>)
{
$depth = join('/', @depth, shift @tmp);
last SEARCH;
}
close(FYL);
}
pop @path;
pop @pathNoTop;
if (0 == scalar(@pathNoTop))
{
$depth = join('/', @depth);
last;
}
## Construct path manually
push(@depth, '..');
}
return $depth;
} # getDepth
###########################################################################
## Intent: Read in the exclusion file
###########################################################################
sub getExclusions
{
my $file = shift || '';
return () if ($main::argv{'no-exclusions'});
my %exclude;
if ($file)
{
my @data = cat($file);
foreach (@data)
{
next unless ($_);
next if (/^\s*\#/o);
next unless (m%/%);
chomp;
$exclude{$_}++;
}
}
return %exclude;
} # getExclusions
###########################################################################
## Intent: Given the path to a makefile beneath either src or obj
## derive the relative path prefix between makefile and root.
###########################################################################
sub getRelPath
{
my $path0 = shift;
my $abspath;
# Determine type and orientation
my $name = basename($path0);
my $haveMF = ($name eq 'Makefile.in') ? 1
: ($name eq 'Makefile') ? -1
: 0
;
####################################################
## Prep work: form a relative path with ../ removed
####################################################
my $top = getTopDir();
my $obj = getObjDir();
## If the same Makefile will be created alongside Makefile.in
my $topQM = quotemeta($top);
my $objQM = quotemeta($obj);
if ('..' eq substr($path0, 0, 2))
{
my @cwd = split(m%/%, $cwd);
my @pth = split(m%/%, $path0);
while (@pth && $pth[0] eq '..')
{
pop(@cwd);
shift @pth;
}
$path0 = join('/', @cwd, @pth);
$abspath = $path0;
}
if ('/' eq substr($path0, 0, 1))
{
$path0 =~ s%^$objQM\/?%%;
$path0 =~ s%^$topQM\/?%%;
}
#######################################################################
## Build a list of directories to search. Input source will be one
## of path to Makefile.in, path to Makefile, directory, file within
## a directory or relative path from cwd.
#######################################################################
my @subdirs;
my $path = (0 == $haveMF) ? $path0 : dirname($path0);
push(@subdirs, $path); # containing directory
push(@subdirs, dirname($path)) if (0 == $haveMF && -f $path); # Arg is file within a directory
push(@subdirs, $cwd); # relative to pwd
# obj - path to generated makefile
# top - path to Makefile.in source template
my @prefixes = ('/' ne substr($path0, 0, 1))
? (&getTopDir, &getObjDir)
: ()
;
ON_SAFARI:
for my $prefix (@prefixes)
{
next unless ($prefix); # no command line not passed
foreach my $subdir (@subdirs)
{
foreach my $mf ('Makefile.in', 'Makefile')
{
my $path = join('/', $prefix, $subdir, $mf);
if (-e $path)
{
$name = $mf;
$haveMF = ($mf eq 'Makefile.in') ? 1 : -1;
$abspath = $path;
last ON_SAFARI;
}
}
}
}
#######################################################################
## Generated makefile does not yet exist or path is invalid.
## Should this conditon be handled to detect non-existent Makefile.in:
## Makefile.am => Makefile.in => Makefile but Makefile.in
#######################################################################
if (!$abspath && -1 == $haveMF && $obj)
{
$abspath = ('/' eq substr($path0, 0, 1))
? $path0
: join('/', $obj, $path0)
;
}
########################################################
## If --top and/or --obj specified extract relative path
########################################################
my $relpath;
if (! $abspath)
{
# Error, fall through
}
elsif (1 == $haveMF) # Makefile.in
{
## err w/o --top
(my $tmp = $abspath) =~ s%^$topQM/?%%;
$relpath = dirname($tmp) unless ($tmp eq $abspath);
}
elsif (-1 == $haveMF) # Makefile
{
## err w/o --obj
(my $tmp = $abspath) =~ s%^$objQM/?%%;
$relpath = dirname($tmp) unless ($tmp eq $abspath);
}
$relpath ||= '';
$relpath =~ s%/./%/%og; # filter ./
$@ = ($relpath) ? '' : "ERROR($path0): Unable to locate sources";
return $relpath || '';
} # getRelPath
###########################################################################
## Intent: Determine sandbox root from script startup directory
## -----------------------------------------------------------------------
## Args:
## _set_ optional, if passed use the given value as path
## _reset_ clear cached directory path to reassign
## Returns:
## scalar - absolute path to the sandbox root directory
## -----------------------------------------------------------------------
###########################################################################
my $gtd_dir;
sub getTopDir
{
if (@_) # testing override
{
$gtd_dir = abs_path($_[1] || '.') if ($_[0] eq '_set_');
$gtd_dir = '' if ($_[0] eq '_reset_');
}
unless ($gtd_dir)
{
## Set by command line
if ($main::argv{top})
{
$gtd_dir = $main::argv{top};
}
else
{
my $path = abs_path($FindBin::RealBin);
my @path = split(m%/%o, $path);
## --2 memory/mozalloc/Makefile.in
## --3 was this for FindBin::Script ?
splice(@path, -2);
$gtd_dir = join('/', @path);
}
}
return $gtd_dir;
} # getTopDir
###########################################################################
## Intent: Determine path to MOZ_OBJDIR/object directory
## -----------------------------------------------------------------------
## Args:
## _set_ optional testing arg, if passed re-compute cached value
## Returns:
## scalar - absolute path to the sandbox object directory
## -----------------------------------------------------------------------
###########################################################################
my $god_dir;
sub getObjDir
{
if (@_) # testing override
{
if ($_[0] eq '_reset_')
{
$god_dir = '';
shift;
}
elsif ($_[0] eq '_set_')
{
shift;
my $path = $_[0] || '.';
$god_dir = abs_path($path);
shift;
}
}
## extract $obj from given path
unless ($god_dir)
{
if ($main::argv{obj})
{
$god_dir = $main::argv{obj};
}
elsif (@_ && 'Makefile' eq substr($_, -8))
{
$god_dir = abs_path(shift);
}
else # assume we are sitting in moz_objdir
{
$god_dir = abs_path('.');
}
}
return $god_dir;
} # getObjDir
###########################################################################
## Intent: Generate Makefile from a given Makefile.in template
## -----------------------------------------------------------------------
## Args:
## scalar Relative path to a directory containing a makefile
## fargs Hash ref of function arguments.
## obj Absolute path to MOZ_OBJ/a destination directory
## top Absolute path to the sandbox root
## Returns:
## $@ Set on error
## scalar
## 1 True if the makefile was updated
## 0 Otherwise
## badtokens - If the makefile contains unexpandable @token@ strings
## -----------------------------------------------------------------------
###########################################################################
sub updateMakefiles
{
my %fargs = (@_ && ref($_[$#_])) ? %{ (pop) } : ();
local $_;
$@ = '';
my $top = $fargs{top};
my $obj = $fargs{obj};
my $relpath = shift || '';
my $src = join('/', $top, $relpath, 'Makefile.in');
my $depth = getDepth($src);
my @src = cat($src);
return 0 if ($@);
my $dst = join('/', $obj, $relpath, 'Makefile');
my @dst = cat($dst);
$@ = '';
my $dstD = dirname($dst);
mkdirr($dstD);
return 0 if ($@);
my %data =
( getConfig(),
depth => $depth,
srcdir => join('/', $top, $relpath),
top_srcdir => $top,
);
my $line = 0;
my @data;
while (scalar @src)
{
$line++;
$_ = shift(@src);
## Expand embedded @foo@
while (/\@[^\@\s\$]+\@/go)
{
my $end = pos($_);
my $val = $&;
my $len = length($val);
$val =~ s/^\@\s*//o;
$val =~ s/\s*\@$//o;
## Identify expansions to see if we can avoid shell overhead
if (!defined $data{$val} && !$argv{'no-badtokens'})
{
if (1) # warnings
{
print STDERR "WARNING: token $val not defined\n";
print STDERR " line $line, src: $src\n";
}
return 'badtokens';
}
# Insert $(error txt) makefile macros for invalid tokens
my $val1 = defined($data{$val})
? $data{$val}
: "\$(error $FindBin::Script: variable ${val} is undefined)"
;
substr($_, ($end-$len), $len, $val1);
}
push(@data, $_);
}
if (("@data" eq "@dst") && scalar(@data))
{
print "Skipping up2date makefile: $dst\n" if ($argv{verbose});
}
else
{
my $action = (scalar @dst) ? 'Updating' : 'Creating';
print "$action makefile: $dst\n";
my $tmp = join('.', $dst, "tmp_$$");
if (!open(FYL, "> $tmp"))
{
$@ = "open($tmp) failed: $!";
}
else
{
print FYL @data;
close(FYL);
## Install the new makefile
File::Copy::move($tmp, $dst)
|| ($@ = "move($tmp, $dst) failed: $!");
}
}
return $@ ? 0 : 1;
} # updateMakefiles
# Output the makefiles.
#
sub update_makefiles_legacy {
my ($ac_given_srcdir, $pac_given_srcdir, @makefiles) = @_;
my $debug = $main::argv{debug} || 0;
my $pwdcmd = ($^O eq 'msys') ? 'pwd -W' : 'pwd';
my @unhandled=();
my @warn;
my $ac_file;
foreach $ac_file (@makefiles) {
my $ac_file_in = "$ac_given_srcdir/${ac_file}.in";
my $ac_dir = dirname_legacy($ac_file);
my $ac_dots = '';
my $ac_dir_suffix = '';
my $srcdir = '.';
my $top_srcdir = '.';
# Determine $srcdir and $top_srcdir
#
if ($ac_dir ne '.') {
$ac_dir_suffix = "/$ac_dir";
$ac_dir_suffix =~ s%^/\./%/%;
$ac_dots = $ac_dir_suffix;
# Remove .. components from the provided dir suffix, and
# also the forward path components they were reversing.
my $backtracks = $ac_dots =~ s%\.\.(/|$)%%g;
while ($backtracks--) {
$ac_dots =~ s%/[^/]*%%;
}
$ac_dots =~ s%/[^/]*%../%g;
}
if ($ac_given_srcdir eq '.') {
if ($ac_dots ne '') {
$top_srcdir = $ac_dots;
$top_srcdir =~ s%/$%%;
}
} elsif ($pac_given_srcdir =~ m%^/% or $pac_given_srcdir =~ m%^.:/%) {
$srcdir = "$pac_given_srcdir$ac_dir_suffix";
$top_srcdir = "$pac_given_srcdir";
} else {
if ($debug) {
print "ac_dots = $ac_dots\n";
print "ac_dir_suffix = $ac_dir_suffix\n";
}
$srcdir = "$ac_dots$ac_given_srcdir$ac_dir_suffix";
$top_srcdir = "$ac_dots$ac_given_srcdir";
}
if ($debug) {
print "ac_dir = $ac_dir\n";
print "ac_file = $ac_file\n";
print "ac_file_in = $ac_file_in\n";
print "srcdir = $srcdir\n";
print "top_srcdir = $top_srcdir\n";
print "cwd = " . `$pwdcmd` . "\n";
}
# Copy the file and make substitutions.
# @srcdir@ -> value of $srcdir
# @top_srcdir@ -> value of $top_srcdir
#
if (-e $ac_file) {
next if -M _ < -M $ac_file_in; # Next if Makefile is up-to-date.
warn "updating $ac_file\n";
} else {
warn "creating $ac_file\n";
}
mkdirr(dirname($ac_file));
open INFILE, "<$ac_file_in" or do {
warn "$0: Cannot read $ac_file_in: No such file or directory\n";
next;
};
open OUTFILE, ">$ac_file" or do {
warn "$0: Unable to create $ac_file\n";
next;
};
while (<INFILE>) {
s/\@srcdir\@/$srcdir/g;
s/\@top_srcdir\@/$top_srcdir/g;
if (/\@[_a-zA-Z]*\@/) {
#warn "Unknown variable:$ac_file:$.:$_";
push @unhandled, $ac_file;
last;
}
print OUTFILE;
}
close INFILE;
close OUTFILE;
}
return @unhandled;
} # update_makefiles_legacy
###########################################################################
## Intent: Invoke config.status for unknown makefiles to create
## directory hierarchy for the tree.
## -----------------------------------------------------------------------
## Args:
## array an optional list of makefiles to process
## Returns:
## 0 on success
## $# set on error
## -----------------------------------------------------------------------
## Note: Is this function needed anymore ? Undefined tokens should fail
## at time of expansion rather than having to source config.status.
## Also config.status could be parsed to define values and avoide the
## shell overhead altogether.
###########################################################################
sub run_config_status {
my @unhandled = @_;
# Run config.status with any unhandled files.
#
my @errors;
if (@unhandled) {
local $ENV{CONFIG_FILES}= join ' ', @unhandled;
my $conf = 'config.status';
if (! -e $conf) # legacy behavior, warn rather than err
{
my $cwd = cwd();
my $err = "$FindBin::Script ERROR: Config file $conf does not exist, cwd=$cwd";
push(@errors, $err);
}
elsif (0 != system("./config.status"))
{
my $cwd = cwd();
push(@errors, "config.status failed \$?=$?, \$!=$!, cwd: $cwd");
}
}
$@ = join("\n", @errors);
## Legacy behavior: config.status problems are not fatal {yet}.
## Display warning since caller will not be calling die.
warn $@ if ($@ && $argv{'no-warnings'});
return $@ ? 1 : 0;
}
1;

View File

@ -0,0 +1,94 @@
# -*- makefile -*-
#
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Mozilla Foundation.
# Portions created by the Initial Developer are Copyright (C) 2011
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Joey Armstrong <joey@mozilla.com>
#
# Alternatively, the contents of this file may be used under the terms of
# either of the GNU General Public License Version 2 or later (the "GPL"),
# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/rules.mk
##################################################
## Gather a list of tests, generate timestamp deps
##################################################
TS=.ts
ifneq (,$(findstring check,$(MAKECMDGOALS)))
allsrc = $(wildcard $(srcdir)/*)
tests2run = $(notdir $(filter %.tpl,$(allsrc)))
tests2run += $(notdir $(filter %.tpm,$(allsrc)))
check_targets += $(addprefix $(TS)/,$(tests2run))
endif
all_nop: # export, libs and tools are not needed
check:: $(TS) $(check_targets)
#############################################
# Only invoke tests when sources have changed
#############################################
$(TS)/%: $(srcdir)/%
$(PERL) $(srcdir)/runtest $<
@touch $@
parent = $(patsubst %/,%,$(dir $(srcdir)))
$(TS)/make-makefile.tpl: \
$(srcdir)/make-makefile.tpl\
$(parent)/makemakefile.pm\
$(NULL)
$(PERL) $(srcdir)/runtest $<
@touch $@
$(TS)/makemakefile.tpm: \
$(srcdir)/makemakefile.tpm \
$(parent)/makemakefile.pm \
$(NULL)
$(PERL) $(srcdir)/runtest $<
@touch $@
#####################################################
## Extra dep needed to synchronize parallel execution
#####################################################
$(TS): $(TS)/.done
$(TS)/.done:
$(MKDIR) -p $(dir $@)
touch $@
GARBAGE_DIRS += $(TS)
# EOF

View File

@ -0,0 +1,4 @@
jsautocfg.h: jscpucfg$(HOST_BIN_SUFFIX)
@$(RM) $@ jsautocfg.tmp
./jscpucfg > jsautocfg.tmp
mv jsautocfg.tmp $@

View File

@ -0,0 +1,4 @@
jsautocfg.h: jscpucfg$(HOST_BIN_SUFFIX)
@$(RM) $@ jsautocfg.tmp
./jscpucfg > jsautocfg.tmp
mv jsautocfg.tmp $@

View File

@ -0,0 +1,8 @@
###########################################################################
## Intent: Exclusion list for container make builds
###########################################################################
/dev/null
/foo/bar
/a/b/c
/a/b/d

View File

@ -0,0 +1,436 @@
#!/usr/bin/env perl
###########################################################################
## Intent: Unit test to verify make-makefile.tpl
###########################################################################
##----------------------------##
##---] CORE/CPAN INCLUDES [---##
##----------------------------##
use strict;
use warnings;
#use feature 'state'; # 5.10+ not installed everywhere
use Getopt::Long;
use Cwd;
use Cwd qw{abs_path};
use File::Basename;
use File::Copy;
use File::Path;
use File::Temp qw{ tempdir };
use Test;
sub BEGIN { plan tests => 4 };
my @workdirs;
sub END { system("/bin/rm -fr @workdirs"); } # cleanup behind interrupts
##-------------------##
##---] EXPORTS [---##
##-------------------##
use FindBin;
our $VERSION = qw(1.0);
##------------------##
##---] INCLUDES [---##
##------------------##
use FindBin;
use lib "$FindBin::RealBin/..";
use makemakefile;
##-------------------##
##---] GLOBALS [---##
##-------------------##
my %argv;
###########################################################################
## Intent: Create a temp sandbox populated with sources
## -----------------------------------------------------------------------
## Args:
## array a list of file paths to copy
## Returns:
## $@ set on error
## scalar path to scratch sandbox
## -----------------------------------------------------------------------
###########################################################################
my $root; # state $root not available
sub createSandbox
{
my @errors;
unless ($root)
{
my @tmp = split(m%/%, $FindBin::RealBin);
splice(@tmp, -3);
$root = join('/', @tmp);
}
my $work = tempdir();
push(@workdirs, $work);
my @dirs = map{ join('/', $work, dirname($_)) } @_;
mkdirr(@dirs);
push(@errors, "createSandbox: $@") if ($@);
foreach (@_)
{
## Copy sources into the temp source directory
my $src = join('/', $root, $_);
my $dst = join('/', $work, $_);
unless (copy($src, $dst))
{
push(@errors, "copy($src, $dst) failed: $!");
}
}
print STDERR "createSandbox: $work\n" if ($main::argv{debug});
$@ = join('', map{ "$_\n" } @errors);
$work;
} # createSandbox
###########################################################################
## Intent: wrapper to run the make-makefile command.
## -----------------------------------------------------------------------
## Args:
## array command line arguments passed to make-makefile
## Returns:
## array command output
## $@ set by shell exit status, empty string on success
## $? command shell exit status
###########################################################################
my $mm; # state $mm not available
sub makemakefile
{
my %fargs = (@_ && ref($_[$#_])) ? %{ (pop) } : ();
$mm ||= join('/', dirname($FindBin::Bin), 'make-makefile'); # cmd in parent of test/
my $cmd = join(' ', $mm, @_);
print "RUNNING: $cmd\n" if ($fargs{debug});
my @out = `$cmd 2>&1`;
print STDERR map{ "out> $_" } @out if ($argv{verbose});
$@ = (0 == $?) ? '' : "Command failed: $cmd\n@out";
@out;
} # makemakefile
###########################################################################
## Intent: Helper function, display the contents of a given sandbox
## -----------------------------------------------------------------------
## Args:
## scalar Path to sandbox
## Returns:
## none
## -----------------------------------------------------------------------
###########################################################################
sub find_ls
{
my $path = shift || '';
# Assuming dot contributes to cryptic problems
die "find_ls: a path is required" unless ($path);
my $cmd = "find $path -ls";
print "\nRunning: $cmd\n";
print '=' x 75, "\n";
print `$cmd`;
} # myls
###########################################################################
## Intent: Verify make-makefile is able to digest paths and generate
## makefiles when object directory is a child of top.
###########################################################################
sub check_makemakefile
{
my $work = createSandbox
(
'memory/mozalloc/Makefile.in',
'toolkit/system/windowsproxy/Makefile.in',
'toolkit/crashreporter/google-breakpad/src/client/Makefile.in',
);
my $workdir = createSandbox();
my $top = $workdir;
chdir $top;
my $objA = 'obj-arch-dir';
my $obj = join('/', $top, $objA);
# getTopDir()
local $main::argv{top} = $work;
local $main::argv{obj} = $obj;
getObjDir('_reset_');
my @root = split(m%/%, $FindBin::RealBin);
splice(@root, -3);
my $root = join('/', @root);
my @args =
(
[
banner => "--top and --obj are impled, generate Makefile",
rel => 'memory/mozalloc',
cmd => join(' ',
'--top', $top,
'--obj', $obj,
'memory/mozalloc/Makefile',
),
],
[
banner => "--top and abs(obj) passed",
rel => "toolkit/system/windowsproxy",
cmd => join(' ',
'--top', $top,
"$obj/toolkit/system/windowsproxy/Makefile",
),
exp => "$obj/toolkit/system/windowsproxy/Makefile",
skip => 1, #
],
[
banner => "--obj and abs(top) passed",
rel => "toolkit/crashreporter/google-breakpad/src/client",
cmd => join(' ',
'--obj', $obj,
"$top/toolkit/crashreporter/google-breakpad/src/client/Makefile.in",
),
exp => "$top/toolkit/crashreporter/google-breakpad/src/client/Makefile.in",
skip => 1, #
],
);
foreach (@args)
{
my %rec = @{ $_ };
next if ($rec{skip});
next unless ($rec{rel});
my $srcR = join('/', $top, $rec{rel});
my $dstR = join('/', $obj, $rec{rel});
my $src = join('/', $top, $rec{rel}, 'Makefile.in');
my $dst = join('/', $obj, $rec{rel}, 'Makefile');
# Use distinct sources to avoid cleanup overhead between tests
die "Test source already used: $dstR" if (-d $dstR);
## Copy sources into the temp source directory
my $rootR = join('/', $root, $rec{rel});
my $rootS = join('/', $root, $rec{rel}, 'Makefile.in');
File::Path::mkpath($srcR, 0, 0700);
copy($rootS, $src) or die "copy($rootS, $src) failed: $!";
die "source does not exist: $src" unless (-e $src);
######################
## Generate and verify
######################
print STDERR "RUNNING: $rec{banner}\n" if ($argv{debug});
my @errs;
makemakefile('--enhanced', $rec{cmd}, {verbose=>1});
if ($@)
{
push(@errs, "\$@ should not be set: $@\n");
}
elsif (! -e $dst)
{
push(@errs, "Generated makefile does not exist: $dst, banner: $rec{banner}\n");
}
ok(scalar(@errs), 0, "Errors detected:\n" . join(" $_", @errs));
find_ls($top) if (@errs);
}
} # check_makemakefile
###########################################################################
## Intent: Verify make-makefile is able to digest paths and generate
## makefiles when top/MOZ_OBJDIR are not parent/child directories
## ---------------------------------------------------------------------------
## Args:
## none
## Returns:
## none
## ---------------------------------------------------------------------------
###########################################################################
sub check_makemakefile_distinct
{
my $workdir = createSandbox();
# my $workdir = tempdir();
###############################################
## Now update when top/obj are not parent/child
###############################################
my $top = join('/', $workdir, 'top');
my $obj = join('/', $workdir, 'obj');
$main::argv{top} = $top;
$main::argv{obj} = $obj; # test afterward, using undef ?
my @sbxroot = split(m%/%, $FindBin::RealBin);
splice(@sbxroot, -2);
my $sbxroot = join('/', @sbxroot);
## Copy in a makefile template to to convert
File::Path::mkpath(["$top/memory/mozalloc"], 0, 0700);
copy("$sbxroot/memory/mozalloc/Makefile.in", "$top/memory/mozalloc/Makefile.in");
# work/memory/mozalloc/Makefile.in
my @args =
(
[
banner => '--top and --obj are distinct [1]',
cmd => "--obj $obj memory/mozalloc/Makefile",
exp => "$obj/memory/mozalloc/Makefile",
],
[
banner => "--top and --obj are distinct [2]",
cmd => "--top $top memory/mozalloc/Makefile.in",
exp => "$obj/memory/mozalloc/Makefile",
skip => 1, # test problem: top != obj
],
[
banner => "--top and --obj are distinct [3]",
cmd => join(' ',
"--top $top",
"--obj $obj",
"memory/mozalloc/Makefile.in",
),
exp => "$obj/memory/mozalloc/Makefile",
skip => 1, # test problem: top != obj
],
);
foreach (@args)
{
my %rec = @{ $_ };
print STDERR "banner: $rec{banner}\n" if ($argv{debug});
next if $rec{skip};
unlink $rec{exp};
makemakefile('--enhanced', $rec{cmd});
my @errs;
if ($@)
{
push(@errs, "\$@ should not be set: $@\n");
}
elsif (! -e $rec{exp})
{
push(@errs, "Makefile does not exist: $rec{exp}\n");
}
ok(scalar(@errs), 0, "Errors detected:\n" . join(" $_", @errs));
}
} # check_makemakefile_distinct
###########################################################################
## Intent: Verify legacy behavior, invoke make-makefile when cwd is
## a subdirectory beneath MOZ_OBJDIR.
## -----------------------------------------------------------------------
## Args:
## none
## Returns:
## none
## -----------------------------------------------------------------------
###########################################################################
sub check_makemakefile_legacy
{
my $work = createSandbox
(
'memory/mozalloc/Makefile.in',
'parser/htmlparser/tests/mochitest/html5lib_tree_construction/Makefile.in',
);
my $obj = join('/', $work, 'obj');
mkdir $obj;
my @args =
(
{
banner => '-t path -d dot',
cwd => $obj,
cmd => "-t $work -d . memory/mozalloc/Makefile",
exp => "$obj/memory/mozalloc/Makefile",
skip => 0,
},
{
banner => '-t path -d relpath',
cwd => join('/', $obj, 'parser/htmlparser/tests/mochitest'),
cmd => "-t $work -d ../../../.. html5lib_tree_construction/Makefile",
exp => "$obj/parser/htmlparser/tests/mochitest/html5lib_tree_construction/Makefile",
skip => 0,
},
);
foreach (@args)
{
my %rec = %{ $_ };
next if ($rec{skip});
## make-make while sitting in $objdir
mkdirr($rec{cwd});
chdir $rec{cwd} || die "chdir $rec{cwd} failed; $!";
makemakefile($rec{cmd});
my @errs;
if ($@)
{
push(@errs, "make-makefile $rec{cmd} failed: $@");
}
elsif (! -e $rec{exp})
{
push(@errs, "generated makefile does not exist: $rec{exp}");
}
ok(scalar(@errs), 0, "Errors detected: @errs");
find_ls($work) if (@errs);
}
chdir $FindBin::RealBin;
} # check_makemakefile_legacy
###########################################################################
## Intent: Smoke tests for the unittests module
###########################################################################
sub smoke
{
print STDERR "Running test: smoke()\n" if ($argv{debug});
} # smoke()
###########################################################################
## Intent: Intitialize global test objects and consts
###########################################################################
sub init
{
print "Running: init()\n" if ($argv{debug});
# testplan(24, 0);
} # init()
##----------------##
##---] MAIN [---##
##----------------##
unless(GetOptions(\%argv,
qw(
debug|d
manual
test=s@
verbose
)))
{
print "USAGE: $0\n";
print " --debug Enable script debug mode\n";
print " --manual Also run disabled tests\n";
print " --smoke Run smoke tests then exit\n";
print " --test Run a list of tests by function name\n";
print " --verbose Enable script verbose mode\n";
exit 1;
}
init();
smoke();
check_makemakefile();
check_makemakefile_distinct();
check_makemakefile_legacy();

View File

@ -0,0 +1,519 @@
#!/usr/bin/env perl
###########################################################################
## Intent: Unit test to verify the makemakefile.pm module
###########################################################################
##----------------------------##
##---] CORE/CPAN INCLUDES [---##
##----------------------------##
use strict;
use warnings;
#use feature 'state';
use Getopt::Long;
use FindBin;
use Cwd qw{abs_path};
use File::Basename;
use File::Compare;
use File::Copy;
use File::Temp qw{tempdir};
use Test;
sub BEGIN { plan tests => 36 };
my @workdirs;
sub END { system("/bin/rm -fr @workdirs"); } # cleanup behind interrupts
##-------------------##
##---] EXPORTS [---##
##-------------------##
our $VERSION = qw(1.0);
##------------------##
##---] INCLUDES [---##
##------------------##
use FindBin;
use lib "$FindBin::RealBin/..";
use makemakefile;
##-------------------##
##---] GLOBALS [---##
##-------------------##
my %argv;
###########################################################################
## Intent: Create a temp sandbox populated with sources
## -----------------------------------------------------------------------
## Args:
## array files to copy into the temporary sandbox
## Returns:
## $@ set on error
## array
## top - path to temp sandbox root
## obj - path to temp sandbox moz_obj directory
## -----------------------------------------------------------------------
###########################################################################
my $_root_; # state $root
sub createSandbox
{
# state $root;
my @errors;
unless ($_root_)
{
my @tmp = split(m%/%, $FindBin::RealBin);
splice(@tmp, -3);
$_root_ = join('/', @tmp);
}
my $work = tempdir(CLEANUP=>1);
push(@workdirs, $work);
my @dirs = map{ join('/', $work, dirname($_)) } @_;
mkdirr(@dirs);
push(@errors, "createSandbox: $@") if ($@);
foreach (@_)
{
## Copy sources into the temp source directory
my $src = join('/', $_root_, $_);
my $dst = join('/', $work, $_);
unless (copy($src, $dst))
{
push(@errors, "copy($src, $dst) failed: $!");
}
}
print STDERR "createSandbox: $work\n" if ($main::argv{debug});
$@ = join('', map{ "$_\n" } @errors);
$work;
} # createSandbox
###########################################################################
## Intent: Verify legacy dirname function
###########################################################################
sub check_dirname_legacy
{
print "Running: check_dirname_legacy\n" if ($main::argv{debug});
foreach (
['/dev/null', '/dev'],
['/foo/bar/Makefile', '/foo/bar'],
)
{
my ($src, $exp) = @{ $_ };
my $dir = dirname_legacy($src);
ok($dir, $exp, "dirname_legacy($src) failed");
}
my $path = dirname_legacy(undef);
ok($path ? 1 : 0, 1, "dirname('') should expand to cwd");
} # check_dirname_legacy
###########################################################################
## Intent: Verify topdir lookup function
###########################################################################
sub check_getTopDir
{
print "Running: check_getTopDir\n" if ($main::argv{debug});
my $path = getTopDir();
## Unit test is special, cmd not invoked from the same directory
## as the makemakefile.pm module.
ok($path ? 1 : 0, 1, "getTopDir failed");
ok(-d $path ? 1 : 0, 1, "getTopDir: directory $path does not exist");
ok($FindBin::RealBin =~ m%$path/% ? 1 : 0, 1, 'Invalid topdir path');
ok(-e "$path/client.mk" ? 1 : 0, 1, "client.mk not found in $path");
} # check_getTopDir
###########################################################################
## Intent: Verify objdir lookup function
###########################################################################
sub check_getObjDir
{
print "Running: check_getObjDir\n" if ($main::argv{debug});
local $main::argv{obj} = '/bin';
my $path = getObjDir('_reset_');
ok($path ? 1 : 0, 1, "getObjDir failed");
ok(-d $path ? 1 : 0, 1, "getObjDir: directory $path does not exist");
my $top = getTopDir();
$main::argv{obj} = join('/', $top, 'browser'); # use existing path so file can be resolved
my $obj = getObjDir('_reset_');
ok($top ne $obj ? 1 : 0, 1, "top and object directory paths should not match");
## If we fail for /bin use here getObjDir() was not reset
my $client = join('/', $obj, '..', 'client.mk');
ok(-e $client ? 1 : 0, 1, "client.mk not found in parent of $path, $client");
getObjDir('_set_'); # clear cached value and recompute
foreach my $file ("$top/memory/mozalloc/Makefile")
{
my $obj = getObjDir('_reset_', $file);
ok($obj ne $file ? 1 : 0, 1, "getObjDir($file) failed")
}
} # check_getObjDir
###########################################################################
## Intent: Verify rel-path-to-root/getdepth function
###########################################################################
sub check_getDepth
{
my @tmp = split(m%/%o, $FindBin::Bin);
splice(@tmp, -3);
my $root = abs_path( join('/', @tmp) );
my %data =
(
$root => '.',
join('/', $root, 'netwerk/Makefile.in') => '..',
join('/', $root, 'browser/components/privatebrowsing/test/browser/Makefile.in') => '../../../../..',
join('/', $root, 'browser/components/privatebrowsing/test/browser/') => '../../../../..',
join('/', $root, 'browser/components/privatebrowsing/test/browser') => '../../../../..',
join('/', $root, 'browser/components/privatebrowsing/test') => '../../../..',
);
while (my($k, $v) = each %data)
{
my $depth = makemakefile::getDepth($k);
ok($depth, $v, "getDepth($k) failed");
}
} # check_getDepth
###########################################################################
## Intent: Verify reading the exclusion file
###########################################################################
sub check_getExclusions
{
my $cfg = join('/', $FindBin::RealBin, 'make-makefile.excl');
my %excl = getExclusions($cfg);
ok($@, '', '$@ should not be set');
my @excl = sort keys %excl;
ok(scalar @excl, 4, "Exclusion file is invalid: \@excl=@excl");
} # check_getExclusions
###########################################################################
## Intent: Verify rel-path-to-root function
## -----------------------------------------------------------------------
## Args:
## none
## Returns:
## none
## -----------------------------------------------------------------------
## Note:
## String test only, top and obj paths are bogus for this test
###########################################################################
sub check_getRelPath
{
my @tmp = split(m%/%o, $FindBin::Bin);
splice(@tmp, -3);
my $root = abs_path( join('/', @tmp) );
my $obj0 = 'obj-arch';
my $obj = join('/', $root, $obj0);
local $main::argv{top} = $root;
local $main::argv{obj} = $obj;
getTopDir('_reset_');
getObjDir('_set_', $obj);
## Cannot test relative paths with objdir beneath /tmp
## Commented paths are needed for full test coverage
## but are not currently supported by all module functions.
my %data =
(
# Relative - path correct for build directory but
'profile/dirserviceprovider/public/Makefile.in' => 'profile/dirserviceprovider/public',
join('/', $root, 'profile/dirserviceprovider/public/Makefile.in') => 'profile/dirserviceprovider/public',
# File search
'profile/dirserviceprovider/public' => 'profile/dirserviceprovider/public',
# cwd + cleanup
# '../../../profile/dirserviceprovider/public/Makefile.in' => 'profile/dirserviceprovider/public',
# "../../../${obj0}/profile/dirserviceprovider/public/Makefile.in" => 'profile/dirserviceprovider/public',
## Special case: This could be handled but permutations of non-existent files, non-overlapping paths
## and relative paths containing partial subdirectories will compilicate the logic. Wait until needed.
## Relative path: $root + obj + subdir
# "${obj0}/profile/dirserviceprovider/public/Makefile" => 'profile/dirserviceprovider/public',
join('/', $obj, 'profile/dirserviceprovider/public/Makefile') => 'profile/dirserviceprovider/public',
# $RealBin, -d ../../..
# top and obj not subdirectories of each other: /foo/x, /bar/y
);
while (my($k, $v) = each %data)
{
my $dir = getRelPath($k);
ok($@, '', '$@ should not be set');
ok($dir, $v, "ERROR[$k]: exp[$v] != found=[$dir]");
}
my $top = '/tmp/foo';
my $tmp = '/tmp/bar';
local $main::argv{top} = $tmp;
local $main::argv{obj} = $obj;
%data =
(
# "$top/profile/dirserviceprovider/public/Makefile.in" => 'profile/dirserviceprovider/public',
"$obj/profile/dirserviceprovider/public/Makefile" => 'profile/dirserviceprovider/public',
);
while (my($k, $v) = each %data)
{
my $dir = getRelPath($k);
ok($dir, $v, "ERROR[$k]: exp[$v] != found=[$dir]");
}
} # check_getRelPath
###########################################################################
## Intent: Verify rel-path-to-root directory creation
###########################################################################
sub check_mkdirr
{
if (-w '/bin') # cygwin may be writable
{
ok(1, 1, 'bogus test to maintain count');
} else {
mkdirr('/bin/invalid/Makefile');
ok($@ ? 1 : 0, 1, '$@ should be set');
}
my $work = createSandbox();
my @paths = map{ join('/', $work, $_, 'Makefile.in') } qw (xyz/abc foo/bar a/b/c/d/e);
mkdirr(@paths);
ok($@ ? 1 : 0, 0, '$@ should not be set');
push(@paths, '/bin');
my @errors;
foreach (@paths)
{
my $dir = dirname($_);
next if (-d $dir);
push(@errors, "mkdirr($dir) failed\n");
}
ok(scalar @errors, 0, "Errors detected: @errors");
} # check_mkdirr
###########################################################################
## Intent: Verify permutations for system("config.status")
###########################################################################
sub check_run_config_status
{
print STDERR "Running: check_run_config_status()\n"
if ($main::argv{debug});
my $work = createSandbox();
chdir $work;
run_config_status();
ok($@ ? 1 : 0, '$@ should be set, config.status does not exist');
my $cfg = join('/', $work, 'config.status');
local *CFG;
open(CFG, "> $cfg") && close(CFG);
run_config_status();
ok($@, qr/config.status failed/, '$@ should be set, config.status is not executabl');
open(CFG, "> $cfg");
print CFG join("\n",
'#!/bin/sh',
'',
'true',
'');
close(CFG);
chmod 0555, $cfg;
run_config_status();
ok($@, qr/config.status failed/, '$@ should not be set');
} # check_run_config_status
###########################################################################
## Intent: Verify makefile generation by legacy make-makefile functions
## o make-makefile -t /x/y -d ..
###########################################################################
sub check_update_makefiles_legacy
{
print STDERR "Running: check_update_makefiles_legacy()\n"
if ($main::argv{debug});
return unless ($argv{legacy});
print STDERR "check_update_makefiles_legacy: not yet implemented\n";
} # check_update_makefiles_legacy
###########################################################################
## Intent: Verify updateMakefiles()
## o a makefile is generated when none exists.
## o a makefile will only be updated when the templates changes.
## o existing makefiles will be updated when the template changes.
## o @foo@ tokens have been expanded
###########################################################################
sub check_updateMakefiles
{
my @errors;
print STDERR "Running: check_updateMakefiles()\n"
if ($main::argv{debug});
my $mf = 'memory/mozalloc/Makefile.in';
my $work = createSandbox($mf);
my $obj = join('/', $work, 'obj');
my %args =
(
top => $work,
obj => $obj,
);
my $mf_src = join('/', $work, 'memory/mozalloc/Makefile.in');
my $mf_dst = join('/', $obj, 'memory/mozalloc/Makefile');
updateMakefiles('memory/mozalloc', \%args);
my $tlm0 = (stat $mf_dst)[9] || 0;
ok(-e $mf_dst ? 1 : 0, 1, "failed to generate makefile: $mf_dst");
#############################
## Regeneration will be a nop
#############################
updateMakefiles('memory/mozalloc', \%args);
my $tlm1 = (stat $mf_dst)[9] || -1;
ok($tlm1, $tlm0, "makefile should not have been modified");
#####################################################
## Modify template to verify makefile will regenerate
#####################################################
local *MF;
if (open(MF, ">> $mf_src"))
{
print MF map{ "# MODIFIED MAKEFILE\n" } 0..4;
close(MF);
}
updateMakefiles('memory/mozalloc', \%args);
my @data = makemakefile::cat($mf_dst);
## Check content to avoid a silly 'sleep [n]' call here
ok(grep(/^\# MODIFIED MAKEFILE/o, @data) ? 1 : 0,
1,
"template modified, makefile should have regenerated");
## VERIFY template expansion
my @gen = makemakefile::cat($mf_dst);
push(@errors, $@) if ($@);
foreach (@gen)
{
if (/\@[^\@]+\@/o)
{
push(@errors, join("\n",
"Unexpanded template string detected [$_]",
"Makefile: $mf_src",
));
last;
}
}
ok(scalar(@errors), 0, "Errors detected: @errors");
} # check_updateMakefiles
###########################################################################
## Intent: Verify makefile generation by updateMakefiles() when
## command line arguments --top and --obj were passed.
###########################################################################
sub check_updateMakefilesByTopObj
{
my @errors;
print STDERR "Running: check_updateMakefilesByTopObj()\n"
if ($main::argv{debug});
my $work = createSandbox();
my %args =
(
top => $work,
obj => $work,
);
## Grab a list of makefile templates to generate
my @all = glob('data/mf.*');
my @src = map{ /\.exp$/o ? () : $_ } @all;
foreach my $src (@src)
{
my $dst = join('/', $work, 'Makefile');
unlink $dst;
copy($src, "$work/Makefile.in");
updateMakefiles('.', \%args);
ok($@, '', '$@ should not be set');
my @dst = makemakefile::cat($dst);
my $exp = join('.', $src, 'exp');
my @exp = makemakefile::cat($exp);
ok("@dst", "@exp", "updateMakefile($dst) failed");
}
return;
} # check_updateMakefilesByTopObj
###########################################################################
## Intent: Smoke tests for the unittests module
###########################################################################
sub smoke
{
print STDERR "Running test: smoke()\n" if ($argv{debug});
} # smoke()
###########################################################################
## Intent: Intitialize global test objects and consts
###########################################################################
sub init
{
print "Running: init()\n" if ($argv{debug});
# testplan(24, 0);
my @path = split(m%/%, $FindBin::RealBin);
splice(@path, -3);
my $top = join('/', @path);
## Top set based on make-makefile startup directory so adjust for test/ use
getTopDir('_set_', $top);
} # init()
##----------------##
##---] MAIN [---##
##----------------##
unless(GetOptions(\%argv,
qw(
debug|d
manual
test=s@
verbose
)))
{
print "USAGE: $0\n";
print " --debug Enable script debug mode\n";
print " --manual Also run disabled tests\n";
print " --smoke Run smoke tests then exit\n";
print " --test Run a list of tests by function name\n";
print " --verbose Enable script verbose mode\n";
exit 1;
}
init();
smoke();
check_dirname_legacy();
check_getTopDir();
check_getObjDir();
check_getDepth();
check_getExclusions();
check_getRelPath();
check_mkdirr();
check_updateMakefiles();
check_update_makefiles_legacy();
check_updateMakefilesByTopObj();

View File

@ -0,0 +1,95 @@
#!/usr/bin/env perl
###########################################################################
## Intent:
## Test::Harness is a testing wrapper that will process output
## from Test.pm module tests. Sumarize results, report stats
## and exit with overall status for the testing suites.
##
## Run testing suite:
## % make clean test
## % perl runtest
##
## Run Individual tests
## % perl tUtils0
###########################################################################
##----------------------------##
##---] CORE/CPAN INCLUDES [---##
##----------------------------##
use strict;
use warnings;
use Getopt::Long;
use Test::Harness;
##-------------------##
##---] EXPORTS [---##
##-------------------##
our $VERSION = qw(1.0);
use FindBin;
##-------------------##
##---] GLOBALS [---##
##-------------------##
my %argv;
##----------------##
##---] MAIN [---##
##----------------##
unless(GetOptions(\%argv,
qw(debug|d)
))
{
print "Usage: $0\n";
print " --debug Enable debug mode\n";
exit 1;
}
if (2 > $Test::Harness::VERSION)
{
print "Unit tests will not be run, Test::Harness is too old\n"
if ($argv{debug});
exit 0;
}
my @tests;
########################################
## Gather a list of tests if none passed
########################################
unless (@tests = @ARGV)
{
local *D;
opendir(D, '.');
while($_ = readdir(D)) {
next unless /.t\S+$/;
next if (/\.ts$/);
push(@tests, $_);
}
closedir(D);
}
###############################################
## Glob a list of tests when directories passed
###############################################
my @tmp;
foreach (@tests)
{
local *D;
if (-d $_ && (my $dir = $_))
{
opendir(D, $_) || die "opendir(D) failed: $!";
my @tests = grep(/\.t[^\.\s]+/o, readdir(D));
closedir(D);
push(@tmp, map{ join('/', $dir, $_); } @tests);
} else {
push(@tmp, $_);
}
}
@tests = @tmp;
print "$0: @ARGV\n" if ($argv{debug});
runtests(@tests);
# EOF

View File

@ -340,6 +340,7 @@ user_pref("browser.ui.layout.tablet", 0); // force tablet UI off
user_pref("dom.allow_scripts_to_close_windows", true);
user_pref("dom.disable_open_during_load", false);
user_pref("dom.max_script_run_time", 0); // no slow script dialogs
user_pref("hangmonitor.timeout", 0); // no hang monitor
user_pref("dom.max_chrome_script_run_time", 0);
user_pref("dom.popup_maximum", -1);
user_pref("dom.send_after_paint_to_content", true);

View File

@ -16,5 +16,6 @@
__malloc_hook;
__realloc_hook;
__memalign_hook;
_IO_stdin_used;
local: *;
};

View File

@ -109,3 +109,10 @@ endif
endif # ! MOZ_DEBUG
endif # WIN32_REDIST_DIR
# run the binscope tool to make sure the binary and all libraries
# are using all available Windows OS-level security mechanisms
check::
$(PYTHON) $(srcdir)/autobinscope.py $(DIST)/bin/$(MOZ_APP_NAME)$(BIN_SUFFIX) $(DIST)/crashreporter-symbols/
$(PYTHON) $(srcdir)/autobinscope.py $(DIST)/bin/plugin-container.exe $(DIST)/crashreporter-symbols/

108
build/win32/autobinscope.py Normal file
View File

@ -0,0 +1,108 @@
#!/usr/bin/env python
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is
# the Mozilla Foundation.
# Portions created by the Initial Developer are Copyright (C) 2011
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# imelven@mozilla.com
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
# run Microsoft's Binscope tool (http://www.microsoft.com/download/en/details.aspx?id=11910)
# against a fresh Windows build. output a 'binscope.log' file with full details
# of the run and appropriate strings to integrate with the buildbots
# from the docs : "The error code returned when running under the command line is equal
# to the number of failures the tool reported plus the number of errors. BinScope will return
# 0 only if there are no errors or failures."
# the symbol dir should point to the symbol dir hierarchy created
# via running make buildsymbols in a windows build's objdir
import sys
import subprocess
import os
BINSCOPE_OUTPUT_LOGFILE = r".\binscope_xml_output.log"
# usage
if len(sys.argv) < 3:
print """usage : autobinscope.by path_to_binary path_to_symbols [log_file_path]"
log_file_path is optional, log will be written to .\binscope_xml_output.log by default"""
sys.exit(0)
binary_path = sys.argv[1]
symbol_path = sys.argv[2]
if len(sys.argv) == 4:
log_file_path = sys.argv[3]
else:
log_file_path = BINSCOPE_OUTPUT_LOGFILE
# execute binscope against the binary, using the BINSCOPE environment
# variable as the path to binscope.exe
try:
binscope_path = os.environ['BINSCOPE']
except KeyError:
print "BINSCOPE environment variable is not set, can't check DEP/ASLR etc. status."
sys.exit(0)
try:
proc = subprocess.Popen([binscope_path, "/target", binary_path,
"/output", log_file_path, "/sympath", symbol_path,
"/c", "ATLVersionCheck", "/c", "ATLVulnCheck", "/c", "FunctionPointersCheck",
"/c", "SharedSectionCheck", "/c", "APTCACheck", "/c", "NXCheck",
"/c", "GSCheck", "/c", "GSFunctionSafeBuffersCheck", "/c", "GSFriendlyInitCheck",
"/c", "CompilerVersionCheck", "/c", "SafeSEHCheck", "/c", "SNCheck",
"/c", "DBCheck"], stdout=subprocess.PIPE)
except WindowsError, (errno, strerror):
if errno != 2 and errno != 3:
print "Unexpected error ! \nError " + str(errno) + " : " + strerror + "\nExiting !\n"
sys.exit(0)
else:
print "Could not locate binscope at location : %s\n" % binscope_path
print "Binscope wasn't installed or the BINSCOPE env variable wasn't set correctly, skipping this check and exiting..."
sys.exit(0)
proc.wait()
output = proc.communicate()[0]
# is this a PASS or a FAIL ?
if proc.returncode != 0:
print "TEST-UNEXPECTED-FAIL | autobinscope.py | %s is missing a needed Windows protection, such as /GS or ASLR" % binary_path
else:
print "TEST-PASS | autobinscope.py | %s succeeded" % binary_path

View File

@ -144,6 +144,8 @@ netscape_security_isPrivilegeEnabled(JSContext *cx, uintN argc, jsval *vp)
if (NS_FAILED(rv))
result = JS_FALSE;
}
} else {
return JS_FALSE;
}
JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(result));
return JS_TRUE;

View File

@ -66,6 +66,7 @@ endif
JAVAC_FLAGS = \
-target $(JAVA_VERSION) \
-source $(JAVA_VERSION) \
-classpath $(JAVA_CLASSPATH) \
-bootclasspath $(JAVA_BOOTCLASSPATH) \
-encoding ascii \

View File

@ -52,9 +52,13 @@ MOZ_APP_DISPLAYNAME = @MOZ_APP_DISPLAYNAME@
MOZ_APP_BASENAME = @MOZ_APP_BASENAME@
MOZ_APP_VENDOR = @MOZ_APP_VENDOR@
MOZ_APP_PROFILE = @MOZ_APP_PROFILE@
MOZ_APP_ID = @MOZ_APP_ID@
MOZ_PROFILE_MIGRATOR = @MOZ_PROFILE_MIGRATOR@
MOZ_EXTENSION_MANAGER = @MOZ_EXTENSION_MANAGER@
MOZ_APP_UA_NAME = @MOZ_APP_UA_NAME@
MOZ_APP_VERSION = @MOZ_APP_VERSION@
MOZ_UA_BUILDID = @MOZ_UA_BUILDID@
MOZ_APP_STATIC_INI = @MOZ_APP_STATIC_INI@
MOZ_PKG_SPECIAL = @MOZ_PKG_SPECIAL@

View File

@ -64,8 +64,6 @@ ifdef SDK_HEADERS
EXPORTS += $(SDK_HEADERS)
endif
REPORT_BUILD = @echo $(notdir $<)
ifeq ($(OS_ARCH),OS2)
EXEC =
else
@ -1150,32 +1148,25 @@ endif # MOZ_AUTO_DEPS
# Rules for building native targets must come first because of the host_ prefix
host_%.$(OBJ_SUFFIX): %.c $(GLOBAL_DEPS)
$(REPORT_BUILD)
$(ELOG) $(HOST_CC) $(HOST_OUTOPTION)$@ -c $(HOST_CFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
host_%.$(OBJ_SUFFIX): %.cpp $(GLOBAL_DEPS)
$(REPORT_BUILD)
$(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
host_%.$(OBJ_SUFFIX): %.cc $(GLOBAL_DEPS)
$(REPORT_BUILD)
$(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
host_%.$(OBJ_SUFFIX): %.m $(GLOBAL_DEPS)
$(REPORT_BUILD)
$(ELOG) $(HOST_CC) $(HOST_OUTOPTION)$@ -c $(HOST_CFLAGS) $(HOST_CMFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
host_%.$(OBJ_SUFFIX): %.mm $(GLOBAL_DEPS)
$(REPORT_BUILD)
$(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(HOST_CMMFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
%:: %.c $(GLOBAL_DEPS)
$(REPORT_BUILD)
@$(MAKE_DEPS_AUTO_CC)
$(ELOG) $(CC) $(CFLAGS) $(LDFLAGS) $(OUTOPTION)$@ $(_VPATH_SRCS)
%.$(OBJ_SUFFIX): %.c $(GLOBAL_DEPS)
$(REPORT_BUILD)
@$(MAKE_DEPS_AUTO_CC)
$(ELOG) $(CC) $(OUTOPTION)$@ -c $(COMPILE_CFLAGS) $(_VPATH_SRCS)
@ -1186,7 +1177,6 @@ moc_%.cpp: %.h $(GLOBAL_DEPS)
$(MOC) $(DEFINES) $(ACDEFINES) $< $(OUTOPTION)$@
moc_%.cc: %.cc $(GLOBAL_DEPS)
$(REPORT_BUILD)
$(ELOG) $(MOC) $(DEFINES) $(ACDEFINES) $(_VPATH_SRCS:.cc=.h) $(OUTOPTION)$@
ifdef ASFILES
@ -1207,12 +1197,10 @@ endif
# Please keep the next two rules in sync.
#
%.$(OBJ_SUFFIX): %.cc $(GLOBAL_DEPS)
$(REPORT_BUILD)
@$(MAKE_DEPS_AUTO_CXX)
$(ELOG) $(CCC) $(OUTOPTION)$@ -c $(COMPILE_CXXFLAGS) $(_VPATH_SRCS)
%.$(OBJ_SUFFIX): %.cpp $(GLOBAL_DEPS)
$(REPORT_BUILD)
@$(MAKE_DEPS_AUTO_CXX)
ifdef STRICT_CPLUSPLUS_SUFFIX
echo "#line 1 \"$*.cpp\"" | cat - $*.cpp > t_$*.cc
@ -1223,12 +1211,10 @@ else
endif #STRICT_CPLUSPLUS_SUFFIX
$(OBJ_PREFIX)%.$(OBJ_SUFFIX): %.mm $(GLOBAL_DEPS)
$(REPORT_BUILD)
@$(MAKE_DEPS_AUTO_CXX)
$(ELOG) $(CCC) -o $@ -c $(COMPILE_CXXFLAGS) $(COMPILE_CMMFLAGS) $(_VPATH_SRCS)
$(OBJ_PREFIX)%.$(OBJ_SUFFIX): %.m $(GLOBAL_DEPS)
$(REPORT_BUILD)
@$(MAKE_DEPS_AUTO_CC)
$(ELOG) $(CC) -o $@ -c $(COMPILE_CFLAGS) $(COMPILE_CMFLAGS) $(_VPATH_SRCS)
@ -1478,7 +1464,6 @@ XPIDL_DEPS = \
$(NULL)
$(XPIDL_GEN_DIR)/%.h: %.idl $(XPIDL_DEPS) $(XPIDL_GEN_DIR)/.done
$(REPORT_BUILD)
$(PYTHON_PATH) \
-I$(topsrcdir)/other-licenses/ply \
-I$(topsrcdir)/xpcom/idl-parser \
@ -1490,7 +1475,6 @@ ifndef NO_GEN_XPT
# generate intermediate .xpt files into $(XPIDL_GEN_DIR), then link
# into $(XPIDL_MODULE).xpt and export it to $(FINAL_TARGET)/components.
$(XPIDL_GEN_DIR)/%.xpt: %.idl $(XPIDL_DEPS) $(XPIDL_GEN_DIR)/.done
$(REPORT_BUILD)
$(PYTHON_PATH) \
-I$(topsrcdir)/other-licenses/ply \
-I$(topsrcdir)/xpcom/idl-parser \
@ -1779,15 +1763,12 @@ define MAKE_DEPS_NOAUTO
endef
$(MDDEPDIR)/%.pp: %.c
$(REPORT_BUILD)
@$(MAKE_DEPS_NOAUTO)
$(MDDEPDIR)/%.pp: %.cpp
$(REPORT_BUILD)
@$(MAKE_DEPS_NOAUTO)
$(MDDEPDIR)/%.pp: %.s
$(REPORT_BUILD)
@$(MAKE_DEPS_NOAUTO)
ifneq (,$(OBJS)$(XPIDLSRCS)$(SIMPLE_PROGRAMS))

View File

@ -2350,7 +2350,10 @@ case "$target" in
MKCSHLIB='$(CC) $(CFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -o $@'
MOZ_OPTIMIZE_FLAGS="-O3"
_PEDANTIC=
MOZ_MEMORY=1
# Statically disable jemalloc on 10.5 and 32-bit 10.6. See bug 702250.
if test "$HAVE_64BIT_OS"; then
MOZ_MEMORY=1
fi
CFLAGS="$CFLAGS -fno-common"
CXXFLAGS="$CXXFLAGS -fno-common"
DLL_SUFFIX=".dylib"
@ -4684,7 +4687,7 @@ MOZ_USE_NATIVE_POPUP_WINDOWS=
MOZ_ANDROID_HISTORY=
case "${target}" in
*android*|*darwin*)
*darwin*)
ACCESSIBILITY=
;;
*)
@ -8500,10 +8503,15 @@ AC_SUBST(MOZ_POST_PROGRAM_COMMAND)
# - MOZ_APP_DISPLAYNAME: Used in user-visible fields (DLL properties,
# Mac Bundle name, Updater, Installer), it is typically used for nightly
# builds (e.g. Aurora for Firefox).
# - MOZ_APP_VERSION: Defines the application version number.
# - MOZ_APP_NAME: Used for e.g. the binary program file name. If not set,
# defaults to a lowercase form of MOZ_APP_BASENAME.
# - MOZ_APP_PROFILE: When set, used for application.ini's
# "Profile" field, which controls profile location.
# - MOZ_APP_ID: When set, used for application.ini's "ID" field, and
# crash reporter server url.
# - MOZ_PROFILE_MIGRATOR: When set, enables profile migrator.
# - MOZ_EXTENSION_MANAGER: When set, enabled extension manager.
if test -z "$MOZ_APP_NAME"; then
MOZ_APP_NAME=`echo $MOZ_APP_BASENAME | tr A-Z a-z`
@ -8514,6 +8522,9 @@ AC_SUBST(MOZ_APP_DISPLAYNAME)
AC_SUBST(MOZ_APP_BASENAME)
AC_SUBST(MOZ_APP_VENDOR)
AC_SUBST(MOZ_APP_PROFILE)
AC_SUBST(MOZ_APP_ID)
AC_SUBST(MOZ_PROFILE_MIGRATOR)
AC_SUBST(MOZ_EXTENSION_MANAGER)
AC_DEFINE_UNQUOTED(MOZ_APP_UA_NAME, "$MOZ_APP_UA_NAME")
AC_SUBST(MOZ_APP_UA_NAME)
AC_DEFINE_UNQUOTED(MOZ_APP_UA_VERSION, "$MOZ_APP_VERSION")
@ -8524,6 +8535,13 @@ AC_SUBST(FIREFOX_VERSION)
AC_DEFINE_UNQUOTED(MOZ_UA_BUILDID, "$MOZ_UA_BUILDID")
AC_SUBST(MOZ_UA_BUILDID)
# We can't use the static application.ini data when building against
# a libxul SDK.
if test -n "$LIBXUL_SDK"; then
MOZ_APP_STATIC_INI=
fi
AC_SUBST(MOZ_APP_STATIC_INI)
AC_SUBST(MOZ_PKG_SPECIAL)
AC_SUBST(MOZILLA_OFFICIAL)

View File

@ -100,3 +100,4 @@ load 693212.xhtml
load 698974-1.html
load 700090-1.html
load 700090-2.html
load xhr_html_nullresponse.html

View File

@ -0,0 +1,5 @@
<!DOCTYPE html>
<html class="reftest-wait">
<script>
var xhr=new XMLHttpRequest();xhr.open("GET",window.location);xhr.overrideMimeType("text/html");xhr.onprogress=function(){if(xhr.readyState!=3)return;xhr.abort();document.documentElement.removeAttribute('class');};xhr.onabort=function(){xhr.responseText;};xhr.send();
</script>

View File

@ -88,6 +88,11 @@ namespace dom {
class Link;
// IID for the dom::Element interface
#define NS_ELEMENT_IID \
{ 0xa1588efb, 0x5a84, 0x49cd, \
{ 0x99, 0x1a, 0xac, 0x84, 0x9d, 0x92, 0x05, 0x0f } }
class Element : public nsIContent
{
public:
@ -98,6 +103,8 @@ public:
{}
#endif // MOZILLA_INTERNAL_API
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ELEMENT_IID)
NS_DECL_AND_IMPL_DOM_MEMORY_REPORTER_SIZEOF(Element, nsIContent)
/**
@ -187,6 +194,8 @@ private:
nsEventStates mState;
};
NS_DEFINE_STATIC_IID_ACCESSOR(Element, NS_ELEMENT_IID)
} // namespace dom
} // namespace mozilla

View File

@ -144,6 +144,7 @@ class nsAutoScriptBlockerSuppressNodeRemoved;
struct nsIntMargin;
class nsPIDOMWindow;
class nsIDocumentLoaderFactory;
class nsIDOMHTMLInputElement;
namespace mozilla {
@ -1109,7 +1110,7 @@ public:
* @param aPrincipal Prinicpal of the document. Must not be null.
* @param aScriptObject The object from which the context for event handling
* can be got.
* @param aSVGDocument Force SVG Document creation.
* @param aFlavor Select the kind of document to create.
* @param aResult [out] The document that was created.
*/
static nsresult CreateDocument(const nsAString& aNamespaceURI,
@ -1119,7 +1120,7 @@ public:
nsIURI* aBaseURI,
nsIPrincipal* aPrincipal,
nsIScriptGlobalObject* aScriptObject,
bool aSVGDocument,
DocumentFlavor aFlavor,
nsIDOMDocument** aResult);
/**
@ -1847,7 +1848,18 @@ public:
static nsresult Atob(const nsAString& aAsciiString,
nsAString& aBinaryData);
/**
* Returns whether the input element passed in parameter has the autocomplete
* functionnality enabled. It is taking into account the form owner.
* NOTE: the caller has to make sure autocomplete makes sense for the
* element's type.
*
* @param aInput the input element to check. NOTE: aInput can't be null.
* @return whether the input element has autocomplete enabled.
*/
static bool IsAutocompleteEnabled(nsIDOMHTMLInputElement* aInput);
private:
static bool InitializeEventTable();

View File

@ -124,12 +124,19 @@ class Element;
} // namespace mozilla
#define NS_IDOCUMENT_IID \
{ 0xc3e40e8e, 0x8b91, 0x424c, \
{ 0xbe, 0x9c, 0x9c, 0xc1, 0x76, 0xa7, 0xf7, 0x24 } }
{ 0x184e0a3c, 0x1899, 0x417d, \
{ 0xbf, 0xf4, 0x5a, 0x15, 0xe6, 0xe8, 0xaa, 0x94 } }
// Flag for AddStyleSheet().
#define NS_STYLESHEET_FROM_CATALOG (1 << 0)
// Enum for requesting a particular type of document when creating a doc
enum DocumentFlavor {
DocumentFlavorLegacyGuess, // compat with old code until made HTML5-compliant
DocumentFlavorHTML, // HTMLDocument with HTMLness bit set to true
DocumentFlavorSVG // SVGDocument
};
// Document states
// RTL locale: specific to the XUL localedir attribute
@ -1555,7 +1562,15 @@ public:
virtual nsresult SetNavigationTiming(nsDOMNavigationTiming* aTiming) = 0;
virtual Element* FindImageMap(const nsAString& aNormalizedMapName) = 0;
// Called to notify the document that a listener on the "mozaudioavailable"
// event has been added. Media elements in the document need to ensure they
// fire the event.
virtual void NotifyAudioAvailableListener() = 0;
// Returns true if the document has "mozaudioavailable" event listeners.
virtual bool HasAudioAvailableListeners() = 0;
// Add aLink to the set of links that need their status resolved.
void RegisterPendingLinkUpdate(mozilla::dom::Link* aLink);
@ -1891,7 +1906,7 @@ NS_NewDOMDocument(nsIDOMDocument** aInstancePtrResult,
nsIPrincipal* aPrincipal,
bool aLoadedAsData,
nsIScriptGlobalObject* aEventObject,
bool aSVGDocument);
DocumentFlavor aFlavor);
// This is used only for xbl documents created from the startup cache.
// Non-cached documents are created in the same manner as xml documents.

View File

@ -819,9 +819,7 @@ nsContentSink::ProcessLink(nsIContent* aElement,
const nsSubstring& aRel, const nsSubstring& aTitle,
const nsSubstring& aType, const nsSubstring& aMedia)
{
// XXX seems overkill to generate this string array
nsTArray<nsString> linkTypes;
nsStyleLinkElement::ParseLinkTypes(aRel, linkTypes);
PRUint32 linkTypes = nsStyleLinkElement::ParseLinkTypes(aRel);
// The link relation may apply to a different resource, specified
// in the anchor parameter. For the link relations supported so far,
@ -831,22 +829,22 @@ nsContentSink::ProcessLink(nsIContent* aElement,
return NS_OK;
}
bool hasPrefetch = linkTypes.Contains(NS_LITERAL_STRING("prefetch"));
bool hasPrefetch = linkTypes & PREFETCH;
// prefetch href if relation is "next" or "prefetch"
if (hasPrefetch || linkTypes.Contains(NS_LITERAL_STRING("next"))) {
if (hasPrefetch || (linkTypes & NEXT)) {
PrefetchHref(aHref, aElement, hasPrefetch);
}
if ((!aHref.IsEmpty()) && linkTypes.Contains(NS_LITERAL_STRING("dns-prefetch"))) {
if (!aHref.IsEmpty() && (linkTypes & DNS_PREFETCH)) {
PrefetchDNS(aHref);
}
// is it a stylesheet link?
if (!linkTypes.Contains(NS_LITERAL_STRING("stylesheet"))) {
if (!(linkTypes & STYLESHEET)) {
return NS_OK;
}
bool isAlternate = linkTypes.Contains(NS_LITERAL_STRING("alternate"));
bool isAlternate = linkTypes & ALTERNATE;
return ProcessStyleLink(aElement, aHref, isAlternate, aTitle, aType,
aMedia);
}

View File

@ -178,6 +178,7 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_XTFSERVICE_CID);
#include "nsICategoryManager.h"
#include "nsIViewManager.h"
#include "nsEventStateManager.h"
#include "nsIDOMHTMLInputElement.h"
#ifdef IBMBIDI
#include "nsIBidiKeyboard.h"
@ -649,6 +650,27 @@ nsContentUtils::Atob(const nsAString& aAsciiBase64String,
return rv;
}
bool
nsContentUtils::IsAutocompleteEnabled(nsIDOMHTMLInputElement* aInput)
{
NS_PRECONDITION(aInput, "aInput should not be null!");
nsAutoString autocomplete;
aInput->GetAutocomplete(autocomplete);
if (autocomplete.IsEmpty()) {
nsCOMPtr<nsIDOMHTMLFormElement> form;
aInput->GetForm(getter_AddRefs(form));
if (!form) {
return true;
}
form->GetAutocomplete(autocomplete);
}
return autocomplete.EqualsLiteral("on");
}
/**
* Access a cached parser service. Don't addref. We need only one
* reference to it and this class has that one.
@ -3706,12 +3728,12 @@ nsContentUtils::CreateDocument(const nsAString& aNamespaceURI,
nsIURI* aDocumentURI, nsIURI* aBaseURI,
nsIPrincipal* aPrincipal,
nsIScriptGlobalObject* aEventObject,
bool aSVGDocument,
DocumentFlavor aFlavor,
nsIDOMDocument** aResult)
{
nsresult rv = NS_NewDOMDocument(aResult, aNamespaceURI, aQualifiedName,
aDoctype, aDocumentURI, aBaseURI, aPrincipal,
true, aEventObject, aSVGDocument);
true, aEventObject, aFlavor);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDocument> document = do_QueryInterface(*aResult);

View File

@ -188,7 +188,9 @@ nsDOMParser::ParseFromStream(nsIInputStream *stream,
rv = nsContentUtils::CreateDocument(EmptyString(), EmptyString(), nsnull,
mDocumentURI, mBaseURI,
mOriginalPrincipal,
scriptHandlingObject, svg,
scriptHandlingObject,
svg ? DocumentFlavorSVG :
DocumentFlavorLegacyGuess,
getter_AddRefs(domDocument));
NS_ENSURE_SUCCESS(rv, rv);

View File

@ -1447,7 +1447,9 @@ nsDOMImplementation::CreateDocument(const nsAString& aNamespaceURI,
return nsContentUtils::CreateDocument(aNamespaceURI, aQualifiedName, aDoctype,
mDocumentURI, mBaseURI,
mOwner->NodePrincipal(),
scriptHandlingObject, false, aReturn);
scriptHandlingObject,
DocumentFlavorLegacyGuess,
aReturn);
}
NS_IMETHODIMP
@ -1479,7 +1481,8 @@ nsDOMImplementation::CreateHTMLDocument(const nsAString& aTitle,
rv = nsContentUtils::CreateDocument(EmptyString(), EmptyString(),
doctype, mDocumentURI, mBaseURI,
mOwner->NodePrincipal(),
scriptHandlingObject, false,
scriptHandlingObject,
DocumentFlavorLegacyGuess,
getter_AddRefs(document));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDocument> doc = do_QueryInterface(document);
@ -1782,31 +1785,38 @@ IdentifierMapEntryTraverse(nsIdentifierMapEntry *aEntry, void *aArg)
}
static const char* kNSURIs[] = {
" ([none])",
" (xmlns)",
" (xml)",
" (xhtml)",
" (XLink)",
" (XSLT)",
" (XBL)",
" (MathML)",
" (RDF)",
" (XUL)"
"([none])",
"(xmlns)",
"(xml)",
"(xhtml)",
"(XLink)",
"(XSLT)",
"(XBL)",
"(MathML)",
"(RDF)",
"(XUL)"
};
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsDocument)
if (NS_UNLIKELY(cb.WantDebugInfo())) {
char name[512];
nsCAutoString loadedAsData;
if (tmp->IsLoadedAsData()) {
loadedAsData.AssignLiteral("data");
} else {
loadedAsData.AssignLiteral("normal");
}
PRUint32 nsid = tmp->GetDefaultNamespaceID();
nsCAutoString uri;
if (tmp->mDocumentURI)
tmp->mDocumentURI->GetSpec(uri);
if (nsid < ArrayLength(kNSURIs)) {
PR_snprintf(name, sizeof(name), "nsDocument%s %s", kNSURIs[nsid],
uri.get());
PR_snprintf(name, sizeof(name), "nsDocument %s %s %s",
loadedAsData.get(), kNSURIs[nsid], uri.get());
}
else {
PR_snprintf(name, sizeof(name), "nsDocument %s", uri.get());
PR_snprintf(name, sizeof(name), "nsDocument %s %s",
loadedAsData.get(), uri.get());
}
cb.DescribeRefCountedNode(tmp->mRefCnt.get(), sizeof(nsDocument), name);
}
@ -8227,6 +8237,25 @@ nsDocument::AddImage(imgIRequest* aImage)
return rv;
}
static void
NotifyAudioAvailableListener(nsIContent *aContent, void *aUnused)
{
#ifdef MOZ_MEDIA
nsCOMPtr<nsIDOMHTMLMediaElement> domMediaElem(do_QueryInterface(aContent));
if (domMediaElem) {
nsHTMLMediaElement* mediaElem = static_cast<nsHTMLMediaElement*>(aContent);
mediaElem->NotifyAudioAvailableListener();
}
#endif
}
void
nsDocument::NotifyAudioAvailableListener()
{
mHasAudioAvailableListener = true;
EnumerateFreezableElements(::NotifyAudioAvailableListener, nsnull);
}
nsresult
nsDocument::RemoveImage(imgIRequest* aImage)
{
@ -8596,6 +8625,8 @@ public:
void
nsDocument::AsyncRequestFullScreen(Element* aElement)
{
NS_ASSERTION(aElement,
"Must pass non-null element to nsDocument::AsyncRequestFullScreen");
if (!aElement) {
return;
}
@ -8604,20 +8635,48 @@ nsDocument::AsyncRequestFullScreen(Element* aElement)
NS_DispatchToCurrentThread(event);
}
static void
LogFullScreenDenied(bool aLogFailure, const char* aMessage, nsIDocument* aDoc)
{
if (!aLogFailure) {
return;
}
nsRefPtr<nsPLDOMEvent> e =
new nsPLDOMEvent(aDoc,
NS_LITERAL_STRING("mozfullscreenerror"),
true,
false);
e->PostDOMEvent();
nsContentUtils::ReportToConsole(nsContentUtils::eDOM_PROPERTIES,
aMessage,
nsnull, 0, nsnull,
EmptyString(), 0, 0,
nsIScriptError::warningFlag,
"DOM", aDoc);
}
void
nsDocument::RequestFullScreen(Element* aElement, bool aWasCallerChrome)
{
if (!aElement ||
!aElement->IsInDoc() ||
aElement->OwnerDoc() != this ||
!IsFullScreenEnabled(aWasCallerChrome) ||
!GetWindow()) {
nsRefPtr<nsPLDOMEvent> e =
new nsPLDOMEvent(this,
NS_LITERAL_STRING("mozfullscreenerror"),
true,
false);
e->PostDOMEvent();
NS_ASSERTION(aElement,
"Must pass non-null element to nsDocument::RequestFullScreen");
if (!aElement) {
return;
}
if (!aElement->IsInDoc()) {
LogFullScreenDenied(true, "FullScreenDeniedNotInDocument", this);
return;
}
if (aElement->OwnerDoc() != this) {
LogFullScreenDenied(true, "FullScreenDeniedMovedDocument", this);
return;
}
if (!GetWindow()) {
LogFullScreenDenied(true, "FullScreenDeniedLostWindow", this);
return;
}
if (!IsFullScreenEnabled(aWasCallerChrome, true)) {
// IsFullScreenEnabled calls LogFullScreenDenied, no need to log.
return;
}
@ -8712,12 +8771,12 @@ NS_IMETHODIMP
nsDocument::GetMozFullScreenEnabled(bool *aFullScreen)
{
NS_ENSURE_ARG_POINTER(aFullScreen);
*aFullScreen = IsFullScreenEnabled(nsContentUtils::IsCallerChrome());
*aFullScreen = IsFullScreenEnabled(nsContentUtils::IsCallerChrome(), false);
return NS_OK;
}
bool
nsDocument::IsFullScreenEnabled(bool aCallerIsChrome)
nsDocument::IsFullScreenEnabled(bool aCallerIsChrome, bool aLogFailure)
{
if (nsContentUtils::IsFullScreenApiEnabled() && aCallerIsChrome) {
// Chrome code can always use the full-screen API, provided it's not
@ -8727,9 +8786,16 @@ nsDocument::IsFullScreenEnabled(bool aCallerIsChrome)
return true;
}
if (!nsContentUtils::IsFullScreenApiEnabled() ||
nsContentUtils::HasPluginWithUncontrolledEventDispatch(this) ||
!IsVisible()) {
if (!nsContentUtils::IsFullScreenApiEnabled()) {
LogFullScreenDenied(aLogFailure, "FullScreenDeniedDisabled", this);
return false;
}
if (nsContentUtils::HasPluginWithUncontrolledEventDispatch(this)) {
LogFullScreenDenied(aLogFailure, "FullScreenDeniedPlugins", this);
return false;
}
if (!IsVisible()) {
LogFullScreenDenied(aLogFailure, "FullScreenDeniedHidden", this);
return false;
}
@ -8743,6 +8809,7 @@ nsDocument::IsFullScreenEnabled(bool aCallerIsChrome)
// The node requesting fullscreen, or one of its crossdoc ancestors,
// is an iframe which doesn't have the "mozalllowfullscreen" attribute.
// This request is not authorized by the parent document.
LogFullScreenDenied(aLogFailure, "FullScreenDeniedIframeDisallowed", this);
return false;
}
node = nsContentUtils::GetCrossDocParentNode(node);

View File

@ -949,6 +949,13 @@ public:
virtual Element* FindImageMap(const nsAString& aNormalizedMapName);
virtual void NotifyAudioAvailableListener();
bool HasAudioAvailableListeners()
{
return mHasAudioAvailableListener;
}
virtual Element* GetFullScreenElement();
virtual void AsyncRequestFullScreen(Element* aElement);
virtual void CancelFullScreen();
@ -978,7 +985,9 @@ protected:
// doc tree, and if the document is visible, and if the api is not
// disabled by pref. aIsCallerChrome must contain the return value of
// nsContentUtils::IsCallerChrome() from the context we're checking.
bool IsFullScreenEnabled(bool aIsCallerChrome);
// If aLogFailure is true, an appropriate warning message is logged to the
// console, and a "mozfullscreenerror" event is dispatched to this document.
bool IsFullScreenEnabled(bool aIsCallerChrome, bool aLogFailure);
/**
* Check that aId is not empty and log a message to the console
@ -1155,6 +1164,10 @@ protected:
// Whether we currently require our images to animate
bool mAnimatingImages:1;
// Whether some node in this document has a listener for the
// "mozaudioavailable" event.
bool mHasAudioAvailableListener:1;
// Whether we are currently in full-screen mode, as per the DOM API.
bool mIsFullScreen:1;

View File

@ -3067,6 +3067,12 @@ nsGenericElement::UnbindFromTree(bool aDeep, bool aNullParent)
if (IsFullScreenAncestor(this)) {
// The element being removed is an ancestor of the full-screen element,
// exit full-screen state.
nsContentUtils::ReportToConsole(nsContentUtils::eDOM_PROPERTIES,
"RemovedFullScreenElement",
nsnull, 0, nsnull,
EmptyString(), 0, 0,
nsIScriptError::warningFlag,
"DOM", OwnerDoc());
OwnerDoc()->CancelFullScreen();
}
if (GetParent()) {
@ -4343,6 +4349,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_INTERFACE_MAP_BEGIN(nsGenericElement)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsGenericElement)
NS_INTERFACE_MAP_ENTRY(Element)
NS_INTERFACE_MAP_ENTRY(nsIContent)
NS_INTERFACE_MAP_ENTRY(nsINode)
NS_INTERFACE_MAP_ENTRY(nsIDOMEventTarget)

View File

@ -259,7 +259,6 @@ GK_ATOM(crop, "crop")
GK_ATOM(crossorigin, "crossorigin")
GK_ATOM(curpos, "curpos")
GK_ATOM(current, "current")
GK_ATOM(currentloop, "currentloop")
GK_ATOM(cycler, "cycler")
GK_ATOM(data, "data")
GK_ATOM(datalist, "datalist")
@ -533,8 +532,6 @@ GK_ATOM(localName, "local-name")
GK_ATOM(longdesc, "longdesc")
#ifdef MOZ_MEDIA
GK_ATOM(loop, "loop")
GK_ATOM(loopend, "loopend")
GK_ATOM(loopstart, "loopstart")
#endif
GK_ATOM(low, "low")
GK_ATOM(lowerFirst, "lower-first")
@ -781,14 +778,10 @@ GK_ATOM(percent, "percent")
GK_ATOM(persist, "persist")
GK_ATOM(phase, "phase")
GK_ATOM(ping, "ping")
#ifdef MOZ_MEDIA
GK_ATOM(pixelratio, "pixelratio")
#endif
GK_ATOM(placeholder, "placeholder")
GK_ATOM(plaintext, "plaintext")
#ifdef MOZ_MEDIA
GK_ATOM(playbackrate, "playbackrate")
GK_ATOM(playcount, "playcount")
#endif
GK_ATOM(pointSize, "point-size")
GK_ATOM(poly, "poly")
@ -1783,6 +1776,10 @@ GK_ATOM(XULLabelFrame, "XULLabelFrame")
GK_ATOM(svgAFrame, "SVGAFrame")
GK_ATOM(svgClipPathFrame, "SVGClipPathFrame")
GK_ATOM(svgDefsFrame, "SVGDefsFrame")
GK_ATOM(svgFEContainerFrame, "SVGFEContainerFrame")
GK_ATOM(svgFEImageFrame, "SVGFEImageFrame")
GK_ATOM(svgFELeafFrame, "SVGFELeafFrame")
GK_ATOM(svgFEUnstyledLeafFrame, "SVGFEUnstyledLeafFrame")
GK_ATOM(svgFilterFrame, "SVGFilterFrame")
GK_ATOM(svgForeignObjectFrame, "SVGForeignObjectFrame")
GK_ATOM(svgGenericContainerFrame, "SVGGenericContainerFrame")

View File

@ -107,6 +107,7 @@ static PRLogModuleInfo* gObjectLog = PR_NewLogModule("objlc");
#ifdef ANDROID
#include "nsXULAppAPI.h"
#include "mozilla/Preferences.h"
#endif
class nsAsyncInstantiateEvent : public nsRunnable {
@ -1066,11 +1067,7 @@ nsObjectLoadingContent::ObjectState() const
case eType_Image:
return ImageState();
case eType_Plugin:
#ifdef ANDROID
if (XRE_GetProcessType() == GeckoProcessType_Content)
return NS_EVENT_STATE_TYPE_CLICK_TO_PLAY;
#endif
case eType_Document:
case eType_Document:
// These are OK. If documents start to load successfully, they display
// something, and are thus not broken in this sense. The same goes for
// plugins.
@ -1966,8 +1963,10 @@ nsObjectLoadingContent::GetPluginSupportState(nsIContent* aContent,
nsObjectLoadingContent::GetPluginDisabledState(const nsCString& aContentType)
{
#ifdef ANDROID
if (XRE_GetProcessType() == GeckoProcessType_Content)
return ePluginClickToPlay;
// if plugins are disabled, don't show the click to play message
if (!mozilla::Preferences::GetBool("plugin.disable", false) &&
XRE_GetProcessType() == GeckoProcessType_Content)
return ePluginClickToPlay;
#endif
nsCOMPtr<nsIPluginHost> pluginHostCOM(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID));
nsPluginHost *pluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());

View File

@ -153,24 +153,40 @@ nsStyleLinkElement::SetLineNumber(PRUint32 aLineNumber)
mLineNumber = aLineNumber;
}
void nsStyleLinkElement::ParseLinkTypes(const nsAString& aTypes,
nsTArray<nsString>& aResult)
PRUint32 ToLinkMask(const nsAString& aLink)
{
if (aLink.EqualsLiteral("prefetch"))
return PREFETCH;
else if (aLink.EqualsLiteral("dns-prefetch"))
return DNS_PREFETCH;
else if (aLink.EqualsLiteral("stylesheet"))
return STYLESHEET;
else if (aLink.EqualsLiteral("next"))
return NEXT;
else if (aLink.EqualsLiteral("alternate"))
return ALTERNATE;
else
return 0;
}
PRUint32 nsStyleLinkElement::ParseLinkTypes(const nsAString& aTypes)
{
PRUint32 linkMask = 0;
nsAString::const_iterator start, done;
aTypes.BeginReading(start);
aTypes.EndReading(done);
if (start == done)
return;
return linkMask;
nsAString::const_iterator current(start);
bool inString = !nsCRT::IsAsciiSpace(*current);
nsAutoString subString;
while (current != done) {
if (nsCRT::IsAsciiSpace(*current)) {
if (inString) {
ToLowerCase(Substring(start, current), subString);
aResult.AppendElement(subString);
linkMask |= ToLinkMask(subString);
inString = false;
}
}
@ -184,8 +200,9 @@ void nsStyleLinkElement::ParseLinkTypes(const nsAString& aTypes,
}
if (inString) {
ToLowerCase(Substring(start, current), subString);
aResult.AppendElement(subString);
linkMask |= ToLinkMask(subString);
}
return linkMask;
}
NS_IMETHODIMP

View File

@ -53,6 +53,12 @@
#include "nsIURI.h"
#include "nsTArray.h"
#define PREFETCH 0x00000001
#define DNS_PREFETCH 0x00000002
#define STYLESHEET 0x00000004
#define NEXT 0x00000008
#define ALTERNATE 0x00000010
class nsIDocument;
class nsStyleLinkElement : public nsIDOMLinkStyle,
@ -80,8 +86,8 @@ public:
virtual void OverrideBaseURI(nsIURI* aNewBaseURI);
virtual void SetLineNumber(PRUint32 aLineNumber);
static void ParseLinkTypes(const nsAString& aTypes, nsTArray<nsString>& aResult);
static PRUint32 ParseLinkTypes(const nsAString& aTypes);
void UpdateStyleSheetInternal() { UpdateStyleSheetInternal(nsnull); }
protected:
/**

View File

@ -43,6 +43,8 @@
#ifndef nsTextFragment_h___
#define nsTextFragment_h___
#include "mozilla/Attributes.h"
#include "nsString.h"
#include "nsReadableUtils.h"
#include "nsTraceRefcnt.h"
@ -80,7 +82,7 @@ class nsCString;
* This class does not have a virtual destructor therefore it is not
* meant to be subclassed.
*/
class NS_FINAL_CLASS nsTextFragment {
class nsTextFragment MOZ_FINAL {
public:
static nsresult Init();
static void Shutdown();

View File

@ -244,8 +244,6 @@ nsIAtom** const kAttributesHTML[] = {
&nsGkAtoms::longdesc,
#ifdef MOZ_MEDIA
&nsGkAtoms::loop,
&nsGkAtoms::loopend,
&nsGkAtoms::loopstart,
#endif
&nsGkAtoms::low,
&nsGkAtoms::max,
@ -263,13 +261,9 @@ nsIAtom** const kAttributesHTML[] = {
&nsGkAtoms::open,
&nsGkAtoms::optimum,
&nsGkAtoms::pattern,
#ifdef MOZ_MEDIA
&nsGkAtoms::pixelratio,
#endif
&nsGkAtoms::placeholder,
#ifdef MOZ_MEDIA
&nsGkAtoms::playbackrate,
&nsGkAtoms::playcount,
#endif
&nsGkAtoms::pointSize,
#ifdef MOZ_MEDIA

View File

@ -164,7 +164,8 @@ nsWebSocket::CloseConnection()
if (mReadyState == nsIMozWebSocket::CONNECTING) {
SetReadyState(nsIMozWebSocket::CLOSED);
mWebSocketChannel->Close(mClientReasonCode, mClientReason);
if (mWebSocketChannel)
mWebSocketChannel->Close(mClientReasonCode, mClientReason);
Disconnect();
return NS_OK;
}

View File

@ -70,7 +70,6 @@
#include "nsCExternalHandlerService.h"
#include "nsIVariant.h"
#include "xpcprivate.h"
#include "nsIParser.h"
#include "XPCQuickStubs.h"
#include "nsStringStream.h"
#include "nsIStreamConverterService.h"
@ -103,6 +102,7 @@
#include "nsStringBuffer.h"
#include "nsDOMFile.h"
#include "nsIFileChannel.h"
#include "mozilla/Telemetry.h"
using namespace mozilla;
@ -155,6 +155,8 @@ using namespace mozilla;
#define NS_PROGRESS_EVENT_INTERVAL 50
NS_IMPL_ISUPPORTS1(nsXHRParseEndListener, nsIDOMEventListener)
class nsResumeTimeoutsEvent : public nsRunnable
{
public:
@ -430,7 +432,11 @@ nsXMLHttpRequest::nsXMLHttpRequest()
mUploadProgress(0), mUploadProgressMax(0),
mErrorLoad(false), mTimerIsActive(false),
mProgressEventWasDelayed(false),
mLoadLengthComputable(false), mLoadTotal(0),
mLoadLengthComputable(false),
mIsHtml(false),
mWarnAboutMultipartHtml(false),
mWarnAboutSyncHtml(false),
mLoadTotal(0),
mFirstStartRequestSeen(false),
mInLoadProgressEvent(false),
mResultJSON(JSVAL_VOID),
@ -720,7 +726,34 @@ nsXMLHttpRequest::GetResponseXML(nsIDOMDocument **aResponseXML)
*aResponseXML = mResponseXML;
NS_ADDREF(*aResponseXML);
}
if (mWarnAboutMultipartHtml) {
mWarnAboutMultipartHtml = false;
nsContentUtils::ReportToConsole(nsContentUtils::eDOM_PROPERTIES,
"HTMLMultipartXHRWarning",
nsnull,
0,
nsnull, // Response URL not kept around
EmptyString(),
0,
0,
nsIScriptError::warningFlag,
"DOM",
mOwner->WindowID());
}
if (mWarnAboutSyncHtml) {
mWarnAboutSyncHtml = false;
nsContentUtils::ReportToConsole(nsContentUtils::eDOM_PROPERTIES,
"HTMLSyncXHRWarning",
nsnull,
0,
nsnull, // Response URL not kept around
EmptyString(),
0,
0,
nsIScriptError::warningFlag,
"DOM",
mOwner->WindowID());
}
return NS_OK;
}
@ -851,7 +884,7 @@ NS_IMETHODIMP nsXMLHttpRequest::GetResponseText(nsAString& aResponseText)
// We only decode text lazily if we're also parsing to a doc.
// Also, if we've decoded all current data already, then no need to decode
// more.
if (!mResponseXML ||
if (IsWaitingForHTMLCharset() || !mResponseXML ||
mResponseBodyDecodedPos == mResponseBody.Length()) {
aResponseText = mResponseText;
return NS_OK;
@ -1181,16 +1214,16 @@ nsXMLHttpRequest::Abort()
XML_HTTP_REQUEST_OPENED |
XML_HTTP_REQUEST_DONE))) {
ChangeState(XML_HTTP_REQUEST_DONE, true);
}
if (!(mState & XML_HTTP_REQUEST_SYNCLOOPING)) {
NS_NAMED_LITERAL_STRING(abortStr, ABORT_STR);
DispatchProgressEvent(this, abortStr, mLoadLengthComputable, responseLength,
mLoadTotal);
if (mUpload && !mUploadComplete) {
mUploadComplete = true;
DispatchProgressEvent(mUpload, abortStr, true, mUploadTransferred,
mUploadTotal);
if (!(mState & XML_HTTP_REQUEST_SYNCLOOPING)) {
NS_NAMED_LITERAL_STRING(abortStr, ABORT_STR);
DispatchProgressEvent(this, abortStr, mLoadLengthComputable, responseLength,
mLoadTotal);
if (mUpload && !mUploadComplete) {
mUploadComplete = true;
DispatchProgressEvent(mUpload, abortStr, true, mUploadTransferred,
mUploadTotal);
}
}
}
@ -1440,6 +1473,16 @@ nsXMLHttpRequest::IsSystemXHR()
return !!nsContentUtils::IsSystemPrincipal(mPrincipal);
}
bool
nsXMLHttpRequest::IsWaitingForHTMLCharset()
{
if (!mIsHtml || !mResponseXML) {
return false;
}
nsCOMPtr<nsIDocument> doc = do_QueryInterface(mResponseXML);
return doc->GetDocumentCharacterSetSource() < kCharsetFromDocTypeDefault;
}
nsresult
nsXMLHttpRequest::CheckChannelForCrossSiteRequest(nsIChannel* aChannel)
{
@ -1485,6 +1528,8 @@ nsXMLHttpRequest::Open(const nsACString& method, const nsACString& url,
// No optional arguments were passed in. Default async to true.
async = true;
}
Telemetry::Accumulate(Telemetry::XMLHTTPREQUEST_ASYNC_OR_SYNC,
async ? 0 : 1);
NS_ENSURE_TRUE(mPrincipal, NS_ERROR_NOT_INITIALIZED);
@ -1872,6 +1917,9 @@ nsXMLHttpRequest::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
parseBody = !method.EqualsLiteral("HEAD");
}
mIsHtml = false;
mWarnAboutMultipartHtml = false;
mWarnAboutSyncHtml = false;
if (parseBody && NS_SUCCEEDED(status)) {
// We can gain a huge performance win by not even trying to
// parse non-XML data. This also protects us from the situation
@ -1880,7 +1928,30 @@ nsXMLHttpRequest::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
nsCAutoString type;
channel->GetContentType(type);
if (type.Find("xml") == kNotFound) {
if (type.EqualsLiteral("text/html")) {
if (!(mState & XML_HTTP_REQUEST_ASYNC)) {
// We don't make cool new features available in the bad synchronous
// mode. The synchronous mode is for legacy only.
mWarnAboutSyncHtml = true;
mState &= ~XML_HTTP_REQUEST_PARSEBODY;
} else if (mState & XML_HTTP_REQUEST_MULTIPART) {
// HTML parsing is supported only for non-multipart responses. The
// multipart implementation assumes that it's OK to start the next part
// immediately after the last part. That doesn't work with the HTML
// parser, because when OnStopRequest for one part has fired, the
// parser thread still hasn't posted back the runnables that make the
// parsing appear finished.
//
// On the other hand, multipart support seems to be a legacy feature,
// so it isn't clear that use cases justify adding support for deferring
// the multipart stream events between parts to accommodate the
// asynchronous nature of the HTML parser.
mWarnAboutMultipartHtml = true;
mState &= ~XML_HTTP_REQUEST_PARSEBODY;
} else {
mIsHtml = true;
}
} else if (type.Find("xml") == kNotFound) {
mState &= ~XML_HTTP_REQUEST_PARSEBODY;
}
} else {
@ -1905,7 +1976,9 @@ nsXMLHttpRequest::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
const nsAString& emptyStr = EmptyString();
nsCOMPtr<nsIScriptGlobalObject> global = do_QueryInterface(mOwner);
rv = nsContentUtils::CreateDocument(emptyStr, emptyStr, nsnull, docURI,
baseURI, mPrincipal, global, false,
baseURI, mPrincipal, global,
mIsHtml ? DocumentFlavorHTML :
DocumentFlavorLegacyGuess,
getter_AddRefs(mResponseXML));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDocument> responseDoc = do_QueryInterface(mResponseXML);
@ -1990,12 +2063,8 @@ nsXMLHttpRequest::OnStopRequest(nsIRequest *request, nsISupports *ctxt, nsresult
return NS_OK;
}
nsCOMPtr<nsIParser> parser;
// Is this good enough here?
if (mState & XML_HTTP_REQUEST_PARSEBODY && mXMLParserStreamListener) {
parser = do_QueryInterface(mXMLParserStreamListener);
NS_ABORT_IF_FALSE(parser, "stream listener was expected to be a parser");
mXMLParserStreamListener->OnStopRequest(request, ctxt, status);
}
@ -2004,8 +2073,11 @@ nsXMLHttpRequest::OnStopRequest(nsIRequest *request, nsISupports *ctxt, nsresult
mContext = nsnull;
// If we're received data since the last progress event, make sure to fire
// an event for it.
MaybeDispatchProgressEvents(true);
// an event for it, except in the HTML case, defer the last progress event
// until the parser is done.
if (!mIsHtml) {
MaybeDispatchProgressEvents(true);
}
nsCOMPtr<nsIChannel> channel(do_QueryInterface(request));
NS_ENSURE_TRUE(channel, NS_ERROR_UNEXPECTED);
@ -2050,9 +2122,6 @@ nsXMLHttpRequest::OnStopRequest(nsIRequest *request, nsISupports *ctxt, nsresult
mResponseXML = nsnull;
}
NS_ASSERTION(!parser || parser->IsParserEnabled(),
"Parser blocked somehow?");
// If we're uninitialized at this point, we encountered an error
// earlier and listeners have already been notified. Also we do
// not want to do this if we already completed.
@ -2061,18 +2130,42 @@ nsXMLHttpRequest::OnStopRequest(nsIRequest *request, nsISupports *ctxt, nsresult
return NS_OK;
}
if (!mResponseXML) {
ChangeStateToDone();
return NS_OK;
}
if (mIsHtml) {
NS_ASSERTION(!(mState & XML_HTTP_REQUEST_SYNCLOOPING),
"We weren't supposed to support HTML parsing with XHR!");
nsCOMPtr<nsIDOMEventTarget> eventTarget = do_QueryInterface(mResponseXML);
nsEventListenerManager* manager = eventTarget->GetListenerManager(true);
manager->AddEventListenerByType(new nsXHRParseEndListener(this),
NS_LITERAL_STRING("DOMContentLoaded"),
NS_EVENT_FLAG_BUBBLE |
NS_EVENT_FLAG_SYSTEM_EVENT);
return NS_OK;
}
// We might have been sent non-XML data. If that was the case,
// we should null out the document member. The idea in this
// check here is that if there is no document element it is not
// an XML document. We might need a fancier check...
if (mResponseXML) {
nsCOMPtr<nsIDOMElement> root;
mResponseXML->GetDocumentElement(getter_AddRefs(root));
if (!root) {
mResponseXML = nsnull;
}
nsCOMPtr<nsIDOMElement> root;
mResponseXML->GetDocumentElement(getter_AddRefs(root));
if (!root) {
mResponseXML = nsnull;
}
ChangeStateToDone();
return NS_OK;
}
void
nsXMLHttpRequest::ChangeStateToDone()
{
if (mIsHtml) {
// In the HTML case, this has to be deferred, because the parser doesn't
// do it's job synchronously.
MaybeDispatchProgressEvents(true);
}
ChangeState(XML_HTTP_REQUEST_DONE, true);
NS_NAMED_LITERAL_STRING(errorStr, ERROR_STR);
@ -2098,8 +2191,6 @@ nsXMLHttpRequest::OnStopRequest(nsIRequest *request, nsISupports *ctxt, nsresult
// We're a multipart request, so we're not done. Reset to opened.
ChangeState(XML_HTTP_REQUEST_OPENED);
}
return NS_OK;
}
NS_IMETHODIMP
@ -3047,11 +3138,13 @@ nsXMLHttpRequest::MaybeDispatchProgressEvents(bool aFinalProgress)
mLoadTotal = mLoadTransferred;
mLoadLengthComputable = true;
}
mInLoadProgressEvent = true;
DispatchProgressEvent(this, NS_LITERAL_STRING(PROGRESS_STR),
true, mLoadLengthComputable, mLoadTransferred,
mLoadTotal, mLoadTransferred, mLoadTotal);
mInLoadProgressEvent = false;
if (aFinalProgress || !IsWaitingForHTMLCharset()) {
mInLoadProgressEvent = true;
DispatchProgressEvent(this, NS_LITERAL_STRING(PROGRESS_STR),
true, mLoadLengthComputable, mLoadTransferred,
mLoadTotal, mLoadTransferred, mLoadTotal);
mInLoadProgressEvent = false;
}
if (mResponseType == XML_HTTP_RESPONSE_TYPE_CHUNKED_TEXT ||
mResponseType == XML_HTTP_RESPONSE_TYPE_CHUNKED_ARRAYBUFFER) {
mResponseBody.Truncate();

View File

@ -123,6 +123,7 @@ class nsXMLHttpRequest : public nsXHREventTarget,
public nsIJSNativeInitializer,
public nsITimerCallback
{
friend class nsXHRParseEndListener;
public:
nsXMLHttpRequest();
virtual ~nsXMLHttpRequest();
@ -235,6 +236,10 @@ protected:
bool IsSystemXHR();
bool IsWaitingForHTMLCharset();
void ChangeStateToDone();
/**
* Check if aChannel is ok for a cross-site request by making sure no
* inappropriate headers are set, and no username/password is set.
@ -347,6 +352,9 @@ protected:
bool mTimerIsActive;
bool mProgressEventWasDelayed;
bool mLoadLengthComputable;
bool mIsHtml;
bool mWarnAboutMultipartHtml;
bool mWarnAboutSyncHtml;
PRUint64 mLoadTotal; // 0 if not known.
PRUint64 mLoadTransferred;
nsCOMPtr<nsITimer> mProgressNotifier;
@ -432,4 +440,24 @@ protected:
PRUint64 mMaxProgress;
};
class nsXHRParseEndListener : public nsIDOMEventListener
{
public:
NS_DECL_ISUPPORTS
NS_IMETHOD HandleEvent(nsIDOMEvent *event)
{
nsCOMPtr<nsIXMLHttpRequest> xhr = do_QueryReferent(mXHR);
if (xhr) {
static_cast<nsXMLHttpRequest*>(xhr.get())->ChangeStateToDone();
}
mXHR = nsnull;
return NS_OK;
}
nsXHRParseEndListener(nsIXMLHttpRequest* aXHR)
: mXHR(do_GetWeakReference(aXHR)) {}
virtual ~nsXHRParseEndListener() {}
private:
nsWeakPtr mXHR;
};
#endif

View File

@ -505,6 +505,12 @@ _TEST_FILES2 = \
somedatas.resource \
somedatas.resource^headers^ \
delayedServerEvents.sjs \
test_html_in_xhr.html \
file_html_in_xhr.html \
file_html_in_xhr2.html \
file_html_in_xhr3.html \
file_html_in_xhr.sjs \
file_html_in_xhr_slow.sjs \
test_bug664916.html \
test_bug666604.html \
test_bug675121.html \
@ -522,6 +528,7 @@ _TEST_FILES2 = \
file_bug692434.xml \
test_bug693875.html \
test_nodelist_holes.html \
test_xhr_abort_after_load.html \
$(NULL)
_CHROME_FILES = \

View File

@ -0,0 +1,16 @@
<!DOCTYPE html>
<html><!-- Þ -->
<meta charset="Windows-1251">
<script>
document.documentElement.setAttribute("data-fail", "FAIL");
</script>
<script src="file_html_in_xhr.sjs"></script>
<script src="file_html_in_xhr.sjs" defer></script>
<script src="file_html_in_xhr.sjs" async></script>
<link type="stylesheet" href="file_html_in_xhr.sjs">
<body onload='document.documentElement.setAttribute("data-fail", "FAIL");'>
<img src="file_html_in_xhr.sjs">
<iframe src="file_html_in_xhr.sjs"></iframe>
<video poster="file_html_in_xhr.sjs" src="file_html_in_xhr.sjs"></video>
<object data="file_html_in_xhr.sjs"></object>
<noscript><div></div></noscript>

View File

@ -0,0 +1,15 @@
function handleRequest(request, response)
{
response.setHeader("Content-Type", "text/javascript", false);
if (request.queryString.indexOf("report") != -1) {
if (getState("loaded") == "loaded") {
response.write("ok(false, 'This script was not supposed to get fetched.'); continueAfterReport();");
} else {
response.write("ok(true, 'This script was not supposed to get fetched.'); continueAfterReport();");
}
} else {
setState("loaded", "loaded");
response.write('document.documentElement.setAttribute("data-fail", "FAIL");');
}
}

View File

@ -0,0 +1 @@
<meta charset="windows-1251">Þ

View File

@ -0,0 +1 @@
SUCCESS

View File

@ -0,0 +1,24 @@
var timer;
function handleRequest(request, response)
{
var converter = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"]
.createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
converter.charset = "windows-1251";
var stream = converter.convertToInputStream("\u042E");
var out = response.bodyOutputStream;
response.setHeader("Cache-Control", "no-cache", false);
response.setHeader("Content-Type", "text/html", false);
out.writeFrom(stream, 1);
var firstPart = "<meta charset='windows";
out.write(firstPart, firstPart.length);
out.flush();
response.processAsync();
timer = Components.classes["@mozilla.org/timer;1"]
.createInstance(Components.interfaces.nsITimer);
timer.initWithCallback(function() {
response.write("-1251'>");
response.finish();
}, 500, Components.interfaces.nsITimer.TYPE_ONE_SHOT);
}

View File

@ -27,32 +27,29 @@ function testCancelInPhase4() {
// First request - should be loaded from server
var xhr = new XMLHttpRequest();
xhr.addEventListener("readystatechange", function(e) {
if (xhr.readyState >= 4) {
xhr.addEventListener("abort", function() {
setTimeout(function() {
// This request was cancelled, so the responseText should be empty string
is(xhr.responseText, "", "Expected empty response to cancelled request");
if (xhr.readyState < xhr.DONE) return;
is(xhr.readyState, xhr.DONE, "wrong readyState");
xhr.abort();
SimpleTest.executeSoon(function() {
// This request was cancelled, so the responseText should be empty string
is(xhr.responseText, "", "Expected empty response to cancelled request");
// Second request - should be found in cache
var xhr2 = new XMLHttpRequest();
// Second request - should be found in cache
var xhr2 = new XMLHttpRequest();
xhr2.addEventListener("load", function() {
is(xhr2.responseText, "0", "Received fresh value for second request");
SimpleTest.finish();
}, false);
xhr2.open("GET", url);
xhr2.setRequestHeader("X-Request", "1", false);
try { xhr2.send(); }
catch(e) {
is(xhr2.status, "200", "Exception!");
}
}, 0);
xhr2.addEventListener("load", function() {
is(xhr2.responseText, "0", "Received fresh value for second request");
SimpleTest.finish();
}, false);
xhr.abort();
}
xhr2.open("GET", url);
xhr2.setRequestHeader("X-Request", "1", false);
try { xhr2.send(); }
catch(e) {
is(xhr2.status, "200", "Exception!");
}
});
}, false);
xhr.open("GET", url, true);

View File

@ -0,0 +1,113 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=651072
-->
<head>
<title>Test for Bug 651072</title>
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body onload=runTest();>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=651072">Mozilla Bug 651072</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
/** Test for Bug 651072 **/
SimpleTest.waitForExplicitFinish();
var xhr = new XMLHttpRequest();
function runTest() {
xhr.onreadystatechange = function() {
if (this.readyState == 4) {
ok(this.responseXML, "Should have gotten responseXML");
is(this.responseXML.characterSet, "windows-1251", "Wrong character encoding");
is(this.responseXML.documentElement.firstChild.data, " \u042E ", "Decoded using the wrong encoding.");
is(this.responseText.indexOf("\u042E"), 27, "Bad responseText");
is(this.responseXML.getElementsByTagName("div").length, 1, "There should be one div.");
ok(!this.responseXML.documentElement.hasAttribute("data-fail"), "Should not have a data-fail attribute.");
var scripts = this.responseXML.getElementsByTagName("script");
is(scripts.length, 4, "Unexpected number of scripts.");
while (scripts.length) {
// These should not run when moved to another doc
document.body.appendChild(scripts[0]);
}
var s = document.createElement("script");
s.src = "file_html_in_xhr.sjs?report=1";
document.body.appendChild(s);
}
}
xhr.open("GET", "file_html_in_xhr.html", true);
xhr.send();
}
function continueAfterReport() {
ok(!document.documentElement.hasAttribute("data-fail"), "Should not have a data-fail attribute on mochitest doc.");
xhr = new XMLHttpRequest();
xhr.onprogress = function() {
ok(this.responseText, "Got falsy responseText");
if (this.responseText) {
ok(this.responseText.length, "Got zero-length responseText");
if (this.responseText.length) {
is(this.responseText.charCodeAt(0), 0x042E, "Wrong character encoding for slow text");
}
}
}
xhr.onreadystatechange = function() {
if (this.readyState == 4) {
testNonParsingText();
}
}
xhr.open("GET", "file_html_in_xhr_slow.sjs");
xhr.send();
}
function testNonParsingText() {
xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (this.readyState == 4) {
is(this.responseText.indexOf("\u042E"), -1, "Honored meta in text mode.");
is(this.responseText.indexOf("\uFFFD"), 29, "Honored meta in text mode 2.");
testChunkedText();
}
}
xhr.open("GET", "file_html_in_xhr2.html");
xhr.responseType = "text";
xhr.send();
}
function testChunkedText() {
xhr = new XMLHttpRequest();
xhr.onprogress = function() {
is(this.responseText.indexOf("\u042E"), -1, "Honored meta in chunked text mode.");
}
xhr.onreadystatechange = function() {
if (this.readyState == 4) {
testSyncXHR();
}
}
xhr.open("GET", "file_html_in_xhr2.html");
xhr.responseType = "moz-chunked-text";
xhr.send();
}
function testSyncXHR() {
xhr = new XMLHttpRequest();
xhr.open("GET", "file_html_in_xhr3.html", false);
xhr.send();
is(xhr.responseText, "SUCCESS\n", "responseText should be ready by now");
is(xhr.responseXML, null, "responseXML should be null in the sync case");
SimpleTest.finish();
}
</script>
</pre>
</body>
</html>

View File

@ -0,0 +1,95 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test bug 482935</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href=" /tests/SimpleTest/test.css" />
</head>
<body onload="onWindowLoad()">
<script class="testbody" type="text/javascript">"use strict";
SimpleTest.waitForExplicitFinish();
var url = "file_XHR_pass1.xml";
function onWindowLoad() {
runTest();
}
function runTest() {
var testFunctions = [
startTest1,
startTest2,
startTest3,
];
function nextTest() {
if (testFunctions.length == 0) {
SimpleTest.finish();
}
(testFunctions.shift())();
}
nextTest();
var xhr;
function startTest1() {
xhr = new XMLHttpRequest();
xhr.onload = onLoad1;
xhr.open("GET", url);
xhr.send();
}
function onLoad1() {
is(xhr.readyState, xhr.DONE, "readyState should be DONE");
xhr.onabort = onAbort1;
xhr.abort();
function onAbort1(e) {
ok(false, e.type + " event should not be fired!");
}
is(xhr.readyState, xhr.UNSENT, "readyState should be UNSENT");
nextTest();
}
function startTest2() {
xhr = new XMLHttpRequest();
xhr.onloadstart = onAfterSend;
xhr.open("GET", url);
xhr.send();
}
function startTest3() {
xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.send();
onAfterSend();
}
function onAfterSend() {
is(xhr.readyState, xhr.OPENED, "readyState should be OPENED");
var sent = false;
try {
xhr.send();
} catch (e) {
sent = true;
}
ok(sent, "send() flag should be set");
var aborted = false;
xhr.onabort = onAbort2;
xhr.abort();
function onAbort2() {
is(xhr.readyState, xhr.DONE, "readyState should be DONE");
aborted = true;
}
ok(aborted, "abort event should be fired");
is(xhr.readyState, xhr.UNSENT, "readyState should be UNSENT");
nextTest();
}
}
</script>
</body>
</html>

View File

@ -301,16 +301,17 @@ WebGLContext::WebGLContext()
mContextLost = false;
mAllowRestore = false;
mRobustnessTimerRunning = false;
mDrawSinceRobustnessTimerSet = false;
mContextRestorer = do_CreateInstance("@mozilla.org/timer;1");
}
WebGLContext::~WebGLContext()
{
DestroyResourcesAndContext();
WebGLMemoryReporter::RemoveWebGLContext(this);
if (mContextRestorer) {
mContextRestorer->Cancel();
mContextRestorer = NULL;
}
TerminateRobustnessTimer();
mContextRestorer = nsnull;
}
static PLDHashOperator
@ -613,7 +614,8 @@ WebGLContext::SetDimensions(PRInt32 width, PRInt32 height)
PRInt32 status;
nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
if (mOptions.antialias &&
if (mOptions.antialias &&
gfxInfo &&
NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_WEBGL_MSAA, &status))) {
if (status == nsIGfxInfo::FEATURE_NO_INFO || forceMSAA) {
PRUint32 msaaLevel = Preferences::GetUint("webgl.msaa-level", 2);
@ -709,6 +711,8 @@ WebGLContext::SetDimensions(PRInt32 width, PRInt32 height)
mResetLayer = true;
mOptionsFrozen = true;
mHasRobustness = gl->HasRobustness();
// increment the generation number
++mGeneration;
@ -1147,13 +1151,8 @@ WebGLContext::EnsureBackbufferClearedAsNeeded()
NS_IMETHODIMP
WebGLContext::Notify(nsITimer* timer)
{
TerminateRobustnessTimer();
MaybeRestoreContext();
if (mContextRestorer) {
mContextRestorer->Cancel();
mContextRestorer = NULL;
}
return NS_OK;
}
@ -1163,6 +1162,7 @@ WebGLContext::MaybeRestoreContext()
if (mContextLost || mAllowRestore)
return;
gl->MakeCurrent();
GLContext::ContextResetARB resetStatus =
(GLContext::ContextResetARB) gl->fGetGraphicsResetStatus();
@ -1174,6 +1174,11 @@ WebGLContext::MaybeRestoreContext()
switch (resetStatus) {
case GLContext::CONTEXT_NO_ERROR:
// If there has been activity since the timer was set, it's possible
// that we did or are going to miss something, so clear this flag and
// run it again some time later.
if (mDrawSinceRobustnessTimerSet)
SetupRobustnessTimer();
return;
case GLContext::CONTEXT_GUILTY_CONTEXT_RESET_ARB:
NS_WARNING("WebGL content on the page caused the graphics card to reset; not restoring the context");
@ -1191,10 +1196,7 @@ WebGLContext::MaybeRestoreContext()
void
WebGLContext::ForceLoseContext()
{
if (mContextRestorer) {
mContextRestorer->Cancel();
mContextRestorer = NULL;
}
TerminateRobustnessTimer();
mWebGLError = LOCAL_GL_CONTEXT_LOST;

View File

@ -449,17 +449,30 @@ public:
// Sets up the GL_ARB_robustness timer if it isn't already, so that if the
// driver gets restarted, the context may get reset with it.
void SetupRobustnessTimer() {
if (mContextLost)
if (mContextLost || !mHasRobustness)
return;
if (!mContextRestorer)
mContextRestorer = do_CreateInstance("@mozilla.org/timer;1");
// If the timer was already running, don't restart it here. Instead,
// wait until the previous call is done, then fire it one more time.
// This is an optimization to prevent unnecessary cross-communication
// between threads.
if (mRobustnessTimerRunning) {
mDrawSinceRobustnessTimerSet = true;
return;
}
// As long as there's still activity, we reset the timer each time that
// this function gets called.
mContextRestorer->InitWithCallback(static_cast<nsITimerCallback*>(this),
PR_MillisecondsToInterval(1000),
nsITimer::TYPE_ONE_SHOT);
mRobustnessTimerRunning = true;
mDrawSinceRobustnessTimerSet = false;
}
void TerminateRobustnessTimer() {
if (mRobustnessTimerRunning) {
mContextRestorer->Cancel();
mRobustnessTimerRunning = false;
}
}
protected:
@ -504,6 +517,7 @@ protected:
bool mOptionsFrozen;
bool mMinCapability;
bool mDisableExtensions;
bool mHasRobustness;
WebGLuint mActiveTexture;
WebGLenum mWebGLError;
@ -723,6 +737,8 @@ protected:
nsCOMPtr<nsITimer> mContextRestorer;
bool mContextLost;
bool mAllowRestore;
bool mRobustnessTimerRunning;
bool mDrawSinceRobustnessTimerSet;
public:
// console logging helpers

View File

@ -1622,8 +1622,6 @@ WebGLContext::DrawArrays(GLenum mode, WebGLint first, WebGLsizei count)
if (!ValidateBuffers(&maxAllowedCount, "drawArrays"))
return NS_OK;
SetupRobustnessTimer();
CheckedInt32 checked_firstPlusCount = CheckedInt32(first) + count;
if (!checked_firstPlusCount.valid())
@ -1645,6 +1643,7 @@ WebGLContext::DrawArrays(GLenum mode, WebGLint first, WebGLsizei count)
if (!DoFakeVertexAttrib0(checked_firstPlusCount.value()))
return NS_OK;
SetupRobustnessTimer();
gl->fDrawArrays(mode, first, count);
UndoFakeVertexAttrib0();
@ -1675,8 +1674,6 @@ WebGLContext::DrawElements(WebGLenum mode, WebGLsizei count, WebGLenum type, Web
if (count == 0)
return NS_OK;
SetupRobustnessTimer();
CheckedUint32 checked_byteCount;
if (type == LOCAL_GL_UNSIGNED_SHORT) {
@ -1757,6 +1754,7 @@ WebGLContext::DrawElements(WebGLenum mode, WebGLsizei count, WebGLenum type, Web
if (!DoFakeVertexAttrib0(checked_maxIndexPlusOne.value()))
return NS_OK;
SetupRobustnessTimer();
gl->fDrawElements(mode, count, type, (GLvoid*) (byteOffset));
UndoFakeVertexAttrib0();

View File

@ -61,7 +61,7 @@ NS_IMETHODIMP
WebGLExtensionLoseContext::LoseContext()
{
if (!mContext->LoseContext())
return mContext->mWebGLError = LOCAL_GL_INVALID_OPERATION;
mContext->mWebGLError = LOCAL_GL_INVALID_OPERATION;
return NS_OK;
}
@ -70,7 +70,7 @@ NS_IMETHODIMP
WebGLExtensionLoseContext::RestoreContext()
{
if (!mContext->RestoreContext())
return mContext->mWebGLError = LOCAL_GL_INVALID_OPERATION;
mContext->mWebGLError = LOCAL_GL_INVALID_OPERATION;
return NS_OK;
}

View File

@ -3650,8 +3650,8 @@ nsCanvasRenderingContext2DAzure::DrawImage(nsIDOMElement *imgElt, float a1,
return res.mIsStillLoading ? NS_OK : NS_ERROR_NOT_AVAILABLE;
}
// Ignore nsnull cairo surfaces! See bug 666312.
if (!res.mSurface->CairoSurface()) {
// Ignore cairo surfaces that are bad! See bug 666312.
if (res.mSurface->CairoStatus()) {
return NS_OK;
}

View File

@ -134,10 +134,9 @@ function testFailedRender(msg, ref, test, width, height)
testFailed(msg);
var data = 'REFTEST TEST-KNOWN-FAIL | ' + msg + ' | image comparison (==)\n' +
var data = 'REFTEST TEST-DEBUG-INFO | ' + msg + ' | image comparison (==)\n' +
'REFTEST IMAGE 1 (TEST): ' + testData + '\n' +
'REFTEST IMAGE 2 (REFERENCE): ' + refData;
dump('The following information is for debugging purposes only. It will always print TEST-KNOWN-FAIL, even if it is unexpected.');
dump('FAIL: ' + data + '\n');
dump('To view the differences between these image renderings, go to the following link: https://hg.mozilla.org/mozilla-central/raw-file/tip/layout/tools/reftest/reftest-analyzer.xhtml#log=' +
encodeURIComponent(encodeURIComponent(data)) + '\n');

View File

@ -68,8 +68,6 @@
#include "nsIDOMXULControlElement.h"
#include "nsINameSpaceManager.h"
#include "nsIBaseWindow.h"
#include "nsIView.h"
#include "nsIViewManager.h"
#include "nsISelection.h"
#include "nsFrameSelection.h"
#include "nsIPrivateDOMEvent.h"
@ -1030,8 +1028,7 @@ nsresult
nsEventStateManager::PreHandleEvent(nsPresContext* aPresContext,
nsEvent *aEvent,
nsIFrame* aTargetFrame,
nsEventStatus* aStatus,
nsIView* aView)
nsEventStatus* aStatus)
{
NS_ENSURE_ARG_POINTER(aStatus);
NS_ENSURE_ARG(aPresContext);
@ -3029,8 +3026,7 @@ nsresult
nsEventStateManager::PostHandleEvent(nsPresContext* aPresContext,
nsEvent *aEvent,
nsIFrame* aTargetFrame,
nsEventStatus* aStatus,
nsIView* aView)
nsEventStatus* aStatus)
{
NS_ENSURE_ARG(aPresContext);
NS_ENSURE_ARG_POINTER(aStatus);

View File

@ -106,8 +106,7 @@ public:
nsresult PreHandleEvent(nsPresContext* aPresContext,
nsEvent *aEvent,
nsIFrame* aTargetFrame,
nsEventStatus* aStatus,
nsIView* aView);
nsEventStatus* aStatus);
/* The PostHandleEvent method should contain all system processing which
* should occur conditionally based on DOM or frame processing. It should
@ -117,8 +116,7 @@ public:
nsresult PostHandleEvent(nsPresContext* aPresContext,
nsEvent *aEvent,
nsIFrame* aTargetFrame,
nsEventStatus* aStatus,
nsIView* aView);
nsEventStatus* aStatus);
void NotifyDestroyPresContext(nsPresContext* aPresContext);
void SetPresContext(nsPresContext* aPresContext);

View File

@ -42,7 +42,6 @@
#include "nsCOMPtr.h"
#include "nsIWidget.h"
#include "nsIViewManager.h"
#include "nsIViewObserver.h"
#include "nsIPresShell.h"
#include "nsISupports.h"
#include "nsPIDOMWindow.h"
@ -331,7 +330,9 @@ nsIMEStateManager::SetIMEState(PRUint32 aState,
context.mActionHint.Assign(willSubmit ? control->GetType() == NS_FORM_INPUT_SEARCH
? NS_LITERAL_STRING("search")
: NS_LITERAL_STRING("go")
: NS_LITERAL_STRING("next"));
: formElement
? NS_LITERAL_STRING("next")
: EmptyString());
}
}

Some files were not shown because too many files have changed in this diff Show More