mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 19:35:51 +00:00
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:
commit
902c694467
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)) {
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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++
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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++
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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"];
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
});
|
||||
}
|
||||
|
@ -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()
|
||||
|
@ -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() {
|
||||
|
@ -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);
|
||||
|
@ -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>→ " + command.description + "</td>");
|
||||
output.push("</tr>");
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -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 '»' (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
|
||||
: '»';
|
||||
? options.completionPrompt
|
||||
: '»';
|
||||
|
||||
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 += '  <span class="gcliCompl">⇥ ' +
|
||||
completion += '  <span class="gcli-in-ontab">⇥ ' +
|
||||
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" +
|
||||
"");
|
||||
|
||||
/*
|
||||
|
@ -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");
|
||||
|
@ -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();
|
||||
|
@ -21,7 +21,7 @@ function testFilterButtons() {
|
||||
testMenuFilterButton("net");
|
||||
testMenuFilterButton("css");
|
||||
testMenuFilterButton("js");
|
||||
testMenuFilterButton("webdev");
|
||||
testMenuFilterButton("logging");
|
||||
|
||||
finishTest();
|
||||
}
|
||||
|
@ -14,6 +14,7 @@
|
||||
@DLL_PREFIX@mozjs@DLL_SUFFIX@
|
||||
#endif
|
||||
LICENSE
|
||||
update.locale
|
||||
browserconfig.properties
|
||||
chrome/US.jar
|
||||
chrome/app-chrome.manifest
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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. -->
|
||||
|
@ -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
|
||||
|
@ -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">
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
86
build/appini_header.py
Normal 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]
|
@ -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@
|
@ -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
|
||||
|
5
build/autoconf/make-makefile.excl
Normal file
5
build/autoconf/make-makefile.excl
Normal file
@ -0,0 +1,5 @@
|
||||
###########################################################################
|
||||
## Intent: Exclusion list for container make builds
|
||||
###########################################################################
|
||||
|
||||
# EOF
|
745
build/autoconf/makemakefile.pm
Normal file
745
build/autoconf/makemakefile.pm
Normal 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;
|
94
build/autoconf/test/Makefile.in
Normal file
94
build/autoconf/test/Makefile.in
Normal 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
|
4
build/autoconf/test/data/mf.notokens
Normal file
4
build/autoconf/test/data/mf.notokens
Normal file
@ -0,0 +1,4 @@
|
||||
jsautocfg.h: jscpucfg$(HOST_BIN_SUFFIX)
|
||||
@$(RM) $@ jsautocfg.tmp
|
||||
./jscpucfg > jsautocfg.tmp
|
||||
mv jsautocfg.tmp $@
|
4
build/autoconf/test/data/mf.notokens.exp
Normal file
4
build/autoconf/test/data/mf.notokens.exp
Normal file
@ -0,0 +1,4 @@
|
||||
jsautocfg.h: jscpucfg$(HOST_BIN_SUFFIX)
|
||||
@$(RM) $@ jsautocfg.tmp
|
||||
./jscpucfg > jsautocfg.tmp
|
||||
mv jsautocfg.tmp $@
|
8
build/autoconf/test/make-makefile.excl
Normal file
8
build/autoconf/test/make-makefile.excl
Normal file
@ -0,0 +1,8 @@
|
||||
###########################################################################
|
||||
## Intent: Exclusion list for container make builds
|
||||
###########################################################################
|
||||
|
||||
/dev/null
|
||||
/foo/bar
|
||||
/a/b/c
|
||||
/a/b/d
|
436
build/autoconf/test/make-makefile.tpl
Normal file
436
build/autoconf/test/make-makefile.tpl
Normal 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();
|
519
build/autoconf/test/makemakefile.tpm
Normal file
519
build/autoconf/test/makemakefile.tpm
Normal 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();
|
95
build/autoconf/test/runtest
Normal file
95
build/autoconf/test/runtest
Normal 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
|
@ -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);
|
||||
|
@ -16,5 +16,6 @@
|
||||
__malloc_hook;
|
||||
__realloc_hook;
|
||||
__memalign_hook;
|
||||
_IO_stdin_used;
|
||||
local: *;
|
||||
};
|
||||
|
@ -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
108
build/win32/autobinscope.py
Normal 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
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
@ -66,6 +66,7 @@ endif
|
||||
|
||||
JAVAC_FLAGS = \
|
||||
-target $(JAVA_VERSION) \
|
||||
-source $(JAVA_VERSION) \
|
||||
-classpath $(JAVA_CLASSPATH) \
|
||||
-bootclasspath $(JAVA_BOOTCLASSPATH) \
|
||||
-encoding ascii \
|
||||
|
@ -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@
|
||||
|
||||
|
@ -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))
|
||||
|
22
configure.in
22
configure.in
@ -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)
|
||||
|
@ -100,3 +100,4 @@ load 693212.xhtml
|
||||
load 698974-1.html
|
||||
load 700090-1.html
|
||||
load 700090-2.html
|
||||
load xhr_html_nullresponse.html
|
||||
|
5
content/base/crashtests/xhr_html_nullresponse.html
Normal file
5
content/base/crashtests/xhr_html_nullresponse.html
Normal 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>
|
@ -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
|
||||
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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")
|
||||
|
@ -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());
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
/**
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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 = \
|
||||
|
16
content/base/test/file_html_in_xhr.html
Normal file
16
content/base/test/file_html_in_xhr.html
Normal 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>
|
15
content/base/test/file_html_in_xhr.sjs
Normal file
15
content/base/test/file_html_in_xhr.sjs
Normal 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");');
|
||||
}
|
||||
}
|
||||
|
1
content/base/test/file_html_in_xhr2.html
Normal file
1
content/base/test/file_html_in_xhr2.html
Normal file
@ -0,0 +1 @@
|
||||
<meta charset="windows-1251">Þ
|
1
content/base/test/file_html_in_xhr3.html
Normal file
1
content/base/test/file_html_in_xhr3.html
Normal file
@ -0,0 +1 @@
|
||||
SUCCESS
|
24
content/base/test/file_html_in_xhr_slow.sjs
Normal file
24
content/base/test/file_html_in_xhr_slow.sjs
Normal 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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
113
content/base/test/test_html_in_xhr.html
Normal file
113
content/base/test/test_html_in_xhr.html
Normal 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>
|
||||
|
95
content/base/test/test_xhr_abort_after_load.html
Normal file
95
content/base/test/test_xhr_abort_after_load.html
Normal 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>
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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');
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user