Merge mozilla-central to tracemonkey.
13
Makefile.in
@ -40,6 +40,15 @@ topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
ifndef .PYMAKE
|
||||
ifeq (,$(MAKE_VERSION))
|
||||
$(error GNU Make is required)
|
||||
endif
|
||||
ifeq (,$(filter-out 3.78 3.79,$(MAKE_VERSION)))
|
||||
$(error GNU Make 3.80 or higher is required)
|
||||
endif
|
||||
endif
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
default::
|
||||
@ -183,12 +192,12 @@ ifdef MOZ_CRASHREPORTER
|
||||
echo packing symbols
|
||||
mkdir -p $(topsrcdir)/../$(BUILDID)
|
||||
cd $(DIST)/crashreporter-symbols && \
|
||||
zip -r9D ../$(SYMBOL_ARCHIVE_BASENAME).zip .
|
||||
zip -r9D ../"$(SYMBOL_ARCHIVE_BASENAME).zip" .
|
||||
endif # MOZ_CRASHREPORTER
|
||||
|
||||
uploadsymbols:
|
||||
ifdef MOZ_CRASHREPORTER
|
||||
$(topsrcdir)/toolkit/crashreporter/tools/upload_symbols.sh $(DIST)/$(SYMBOL_ARCHIVE_BASENAME).zip
|
||||
$(SHELL) $(topsrcdir)/toolkit/crashreporter/tools/upload_symbols.sh "$(DIST)/$(SYMBOL_ARCHIVE_BASENAME).zip"
|
||||
endif
|
||||
|
||||
ifeq ($(OS_ARCH),WINNT)
|
||||
|
@ -51,7 +51,8 @@
|
||||
#include "nsISelection2.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsIViewManager.h"
|
||||
#include "nsIWidget.h"
|
||||
|
||||
class nsIWidget;
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsCaretAccessible, nsISelectionListener)
|
||||
|
||||
|
@ -49,7 +49,6 @@
|
||||
#include "nsIURI.h"
|
||||
#include "nsIViewManager.h"
|
||||
#include "nsIWebNavigation.h"
|
||||
#include "nsIWidget.h"
|
||||
|
||||
/* For documentation of the accessibility architecture,
|
||||
* see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html
|
||||
|
@ -45,7 +45,6 @@
|
||||
#include "nsPresContext.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsIRenderingContext.h"
|
||||
#include "nsIWidget.h"
|
||||
#include "nsIComponentManager.h"
|
||||
|
||||
// --------------------------------------------------------
|
||||
@ -212,9 +211,6 @@ nsresult nsTextAccessibleWrap::GetCharacterExtents(PRInt32 aStartOffset, PRInt32
|
||||
nsIFrame *frame = GetFrame();
|
||||
NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
|
||||
|
||||
nsIWidget *widget = frame->GetWindow();
|
||||
NS_ENSURE_TRUE(widget, NS_ERROR_FAILURE);
|
||||
|
||||
nsPoint startPoint, endPoint;
|
||||
nsIFrame *startFrame = GetPointFromOffset(frame, aStartOffset, PR_TRUE, startPoint);
|
||||
nsIFrame *endFrame = GetPointFromOffset(frame, aEndOffset, PR_FALSE, endPoint);
|
||||
|
@ -65,7 +65,7 @@ _TEST_FILES =\
|
||||
role.js \
|
||||
test_accessnode_invalidation.html \
|
||||
test_actions_aria.html \
|
||||
test_actions_inputs.html \
|
||||
$(warning test_actions_inputs.html temporarily disabled) \
|
||||
test_actions.xul \
|
||||
test_aria_activedescendant.html \
|
||||
test_aria_role_article.html \
|
||||
|
@ -434,8 +434,13 @@ pref("browser.gesture.swipe.left", "Browser:BackOrBackDuplicate");
|
||||
pref("browser.gesture.swipe.right", "Browser:ForwardOrForwardDuplicate");
|
||||
pref("browser.gesture.swipe.up", "cmd_scrollTop");
|
||||
pref("browser.gesture.swipe.down", "cmd_scrollBottom");
|
||||
#ifdef XP_MACOSX
|
||||
pref("browser.gesture.pinch.latched", true);
|
||||
pref("browser.gesture.pinch.threshold", 150);
|
||||
#else
|
||||
pref("browser.gesture.pinch.latched", false);
|
||||
pref("browser.gesture.pinch.threshold", 25);
|
||||
#endif
|
||||
pref("browser.gesture.pinch.out", "cmd_fullZoomEnlarge");
|
||||
pref("browser.gesture.pinch.in", "cmd_fullZoomReduce");
|
||||
pref("browser.gesture.pinch.out.shift", "cmd_fullZoomReset");
|
||||
@ -444,6 +449,7 @@ pref("browser.gesture.twist.latched", false);
|
||||
pref("browser.gesture.twist.threshold", 25);
|
||||
pref("browser.gesture.twist.right", "Browser:NextTab");
|
||||
pref("browser.gesture.twist.left", "Browser:PrevTab");
|
||||
pref("browser.gesture.tap", "cmd_fullZoomReset");
|
||||
|
||||
// 0=lines, 1=pages, 2=history , 3=text size
|
||||
#ifdef XP_MACOSX
|
||||
|
@ -95,7 +95,7 @@
|
||||
<menuitem id="releaseNotes"
|
||||
accesskey="&helpReleaseNotes.accesskey;"
|
||||
label="&helpReleaseNotes.label;"
|
||||
oncommand="openReleaseNotes(event)"
|
||||
oncommand="openReleaseNotes()"
|
||||
onclick="checkForMiddleClick(this, event);"/>
|
||||
<menuseparator id="updateSeparator"/>
|
||||
#ifdef MOZ_UPDATER
|
||||
|
@ -688,7 +688,8 @@ let gGestureSupport = {
|
||||
init: function GS_init(aAddListener) {
|
||||
const gestureEvents = ["SwipeGesture",
|
||||
"MagnifyGestureStart", "MagnifyGestureUpdate", "MagnifyGesture",
|
||||
"RotateGestureStart", "RotateGestureUpdate", "RotateGesture"];
|
||||
"RotateGestureStart", "RotateGestureUpdate", "RotateGesture",
|
||||
"TapGesture", "PressTapGesture"];
|
||||
|
||||
let addRemove = aAddListener ? window.addEventListener :
|
||||
window.removeEventListener;
|
||||
@ -714,14 +715,28 @@ let gGestureSupport = {
|
||||
|
||||
switch (aEvent.type) {
|
||||
case "MozSwipeGesture":
|
||||
aEvent.preventDefault();
|
||||
return this.onSwipe(aEvent);
|
||||
case "MozMagnifyGestureStart":
|
||||
aEvent.preventDefault();
|
||||
#ifdef XP_WIN
|
||||
return this._setupGesture(aEvent, "pinch", def(25, 0), "out", "in");
|
||||
#else
|
||||
return this._setupGesture(aEvent, "pinch", def(150, 1), "out", "in");
|
||||
#endif
|
||||
case "MozRotateGestureStart":
|
||||
aEvent.preventDefault();
|
||||
return this._setupGesture(aEvent, "twist", def(25, 0), "right", "left");
|
||||
case "MozMagnifyGestureUpdate":
|
||||
case "MozRotateGestureUpdate":
|
||||
aEvent.preventDefault();
|
||||
return this._doUpdate(aEvent);
|
||||
case "MozTapGesture":
|
||||
aEvent.preventDefault();
|
||||
return this._doAction(aEvent, ["tap"]);
|
||||
case "MozPressTapGesture":
|
||||
// Fall through to default behavior
|
||||
return;
|
||||
}
|
||||
},
|
||||
|
||||
@ -3260,7 +3275,7 @@ function BrowserCustomizeToolbar()
|
||||
#else
|
||||
return window.openDialog(customizeURL,
|
||||
"CustomizeToolbar",
|
||||
"chrome,titlebar,toolbar,resizable,dependent",
|
||||
"chrome,titlebar,toolbar,location,resizable,dependent",
|
||||
gNavToolbox);
|
||||
#endif
|
||||
}
|
||||
@ -6935,7 +6950,15 @@ let gPrivateBrowsingUI = {
|
||||
|
||||
this._privateBrowsingAutoStarted = this._privateBrowsingService.autoStarted;
|
||||
|
||||
if (!this._privateBrowsingAutoStarted) {
|
||||
if (this._privateBrowsingAutoStarted) {
|
||||
// Disable the menu item in auto-start mode
|
||||
let pbMenuItem = document.getElementById("privateBrowsingItem");
|
||||
if (pbMenuItem)
|
||||
pbMenuItem.setAttribute("disabled", "true");
|
||||
document.getElementById("Tools:PrivateBrowsing")
|
||||
.setAttribute("disabled", "true");
|
||||
}
|
||||
else if (window.location.href == getBrowserURL()) {
|
||||
// Adjust the window's title
|
||||
let docElement = document.documentElement;
|
||||
docElement.setAttribute("title",
|
||||
@ -6944,14 +6967,6 @@ let gPrivateBrowsingUI = {
|
||||
docElement.getAttribute("titlemodifier_privatebrowsing"));
|
||||
docElement.setAttribute("browsingmode", "private");
|
||||
}
|
||||
else {
|
||||
// Disable the menu item in auto-start mode
|
||||
let pbMenuItem = document.getElementById("privateBrowsingItem");
|
||||
if (pbMenuItem)
|
||||
pbMenuItem.setAttribute("disabled", "true");
|
||||
document.getElementById("Tools:PrivateBrowsing")
|
||||
.setAttribute("disabled", "true");
|
||||
}
|
||||
},
|
||||
|
||||
onExitPrivateBrowsing: function PBUI_onExitPrivateBrowsing() {
|
||||
@ -6969,7 +6984,7 @@ let gPrivateBrowsingUI = {
|
||||
|
||||
this._setPBMenuTitle("start");
|
||||
|
||||
if (!this._privateBrowsingAutoStarted) {
|
||||
if (window.location.href == getBrowserURL()) {
|
||||
// Adjust the window's title
|
||||
let docElement = document.documentElement;
|
||||
docElement.setAttribute("title",
|
||||
@ -6978,8 +6993,8 @@ let gPrivateBrowsingUI = {
|
||||
docElement.getAttribute("titlemodifier_normal"));
|
||||
docElement.setAttribute("browsingmode", "normal");
|
||||
}
|
||||
else
|
||||
this._privateBrowsingAutoStarted = false;
|
||||
|
||||
this._privateBrowsingAutoStarted = false;
|
||||
},
|
||||
|
||||
_setPBMenuTitle: function PBUI__setPBMenuTitle(aMode) {
|
||||
|
@ -865,7 +865,7 @@ function makePreview(row)
|
||||
item instanceof HTMLLinkElement)
|
||||
mimeType = item.type;
|
||||
|
||||
if (!mimeType && item instanceof nsIImageLoadingContent) {
|
||||
if (!mimeType && !isBG && item instanceof nsIImageLoadingContent) {
|
||||
var imageRequest = item.getRequest(nsIImageLoadingContent.CURRENT_REQUEST);
|
||||
if (imageRequest) {
|
||||
mimeType = imageRequest.mimeType;
|
||||
@ -877,23 +877,28 @@ function makePreview(row)
|
||||
if (!mimeType)
|
||||
mimeType = getContentTypeFromHeaders(cacheEntryDescriptor);
|
||||
|
||||
var imageType;
|
||||
if (mimeType) {
|
||||
// We found the type, try to display it nicely
|
||||
var imageMimeType = /^image\/(.*)/.exec(mimeType);
|
||||
if (imageMimeType) {
|
||||
mimeType = imageMimeType[1].toUpperCase();
|
||||
imageType = imageMimeType[1].toUpperCase();
|
||||
if (numFrames > 1)
|
||||
mimeType = gBundle.getFormattedString("mediaAnimatedImageType",
|
||||
[mimeType, numFrames]);
|
||||
imageType = gBundle.getFormattedString("mediaAnimatedImageType",
|
||||
[imageType, numFrames]);
|
||||
else
|
||||
mimeType = gBundle.getFormattedString("mediaImageType", [mimeType]);
|
||||
imageType = gBundle.getFormattedString("mediaImageType", [imageType]);
|
||||
}
|
||||
else {
|
||||
// the MIME type doesn't begin with image/, display the raw type
|
||||
imageType = mimeType;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// We couldn't find the type, fall back to the value in the treeview
|
||||
mimeType = gImageView.data[row][COL_IMAGE_TYPE];
|
||||
imageType = gImageView.data[row][COL_IMAGE_TYPE];
|
||||
}
|
||||
setItemValue("imagetypetext", mimeType);
|
||||
setItemValue("imagetypetext", imageType);
|
||||
|
||||
var imageContainer = document.getElementById("theimagecontainer");
|
||||
var oldImage = document.getElementById("thepreviewimage");
|
||||
|
@ -1510,7 +1510,7 @@
|
||||
<parameter name="aTab"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
this._endRemoveTab(this._beginRemoveTab(aTab, true));
|
||||
this._endRemoveTab(this._beginRemoveTab(aTab, true, null, true));
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
@ -1526,6 +1526,7 @@
|
||||
<parameter name="aTab"/>
|
||||
<parameter name="aFireBeforeUnload"/>
|
||||
<parameter name="aCloseWindowWithLastTab"/>
|
||||
<parameter name="aCloseWindowFastpath"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (this._removingTabs.indexOf(aTab) > -1 || this._windowIsClosing)
|
||||
@ -1547,6 +1548,15 @@
|
||||
aCloseWindowWithLastTab :
|
||||
this.mPrefs.getBoolPref("browser.tabs.closeWindowWithLastTab");
|
||||
|
||||
// Closing the tab and replacing it with a blank one is notably slower
|
||||
// than closing the window right away. If the caller opts in, take
|
||||
// the fast path.
|
||||
if (closeWindow &&
|
||||
aCloseWindowFastpath &&
|
||||
this._removingTabs.length == 0 &&
|
||||
(this._windowIsClosing = window.closeWindow(true)))
|
||||
return null;
|
||||
|
||||
newTab = this.addTab("about:blank");
|
||||
newTab.collapsed = true;
|
||||
l++;
|
||||
|
@ -74,6 +74,7 @@ _BROWSER_FILES = browser_sanitize-timespans.js \
|
||||
browser_bug441778.js \
|
||||
browser_bug455852.js \
|
||||
browser_bug462673.js \
|
||||
browser_bug481560.js \
|
||||
browser_discovery.js \
|
||||
discovery.html \
|
||||
moz.png \
|
||||
|
19
browser/base/content/test/browser_bug481560.js
Normal file
@ -0,0 +1,19 @@
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
var win = openDialog(getBrowserURL(), "_blank", "chrome,all,dialog=no");
|
||||
|
||||
win.addEventListener("load", function () {
|
||||
win.removeEventListener("load", arguments.callee, false);
|
||||
|
||||
win.gBrowser.selectedTab.addEventListener("TabClose", function () {
|
||||
ok(false, "shouldn't have gotten the TabClose event for the last tab");
|
||||
}, false);
|
||||
|
||||
EventUtils.synthesizeKey("w", { accelKey: true }, win);
|
||||
|
||||
ok(win.closed, "accel+w closed the window immediately");
|
||||
|
||||
finish();
|
||||
}, false);
|
||||
}
|
@ -153,10 +153,14 @@ function test_TestEventListeners()
|
||||
e("MozMagnifyGesture", 0, 30.0, 0);
|
||||
|
||||
// rotate gesture events
|
||||
e("MozRotateGestureStart", SimpleGestureEvent.DIRECTION_RIGHT, 33.0, 0);
|
||||
e("MozRotateGestureUpdate", SimpleGestureEvent.DIRECTION_LEFT, -13.0, 0);
|
||||
e("MozRotateGestureUpdate", SimpleGestureEvent.DIRECTION_RIGHT, 13.0, 0);
|
||||
e("MozRotateGesture", SimpleGestureEvent.DIRECTION_RIGHT, 33.0, 0);
|
||||
e("MozRotateGestureStart", SimpleGestureEvent.ROTATION_CLOCKWISE, 33.0, 0);
|
||||
e("MozRotateGestureUpdate", SimpleGestureEvent.ROTATION_COUNTERCLOCKWISE, -13.0, 0);
|
||||
e("MozRotateGestureUpdate", SimpleGestureEvent.ROTATION_CLOCKWISE, 13.0, 0);
|
||||
e("MozRotateGesture", SimpleGestureEvent.ROTATION_CLOCKWISE, 33.0, 0);
|
||||
|
||||
// Tap and presstap gesture events
|
||||
e("MozTapGesture", 0, 0.0, 0);
|
||||
e("MozPressTapGesture", 0, 0.0, 0);
|
||||
|
||||
// event.shiftKey
|
||||
let modifier = Components.interfaces.nsIDOMNSEvent.SHIFT_MASK;
|
||||
@ -249,12 +253,16 @@ function test_EnsureConstantsAreDisjoint()
|
||||
let left = SimpleGestureEvent.DIRECTION_LEFT;
|
||||
let right = SimpleGestureEvent.DIRECTION_RIGHT;
|
||||
|
||||
let clockwise = SimpleGestureEvent.ROTATION_CLOCKWISE;
|
||||
let cclockwise = SimpleGestureEvent.ROTATION_COUNTERCLOCKWISE;
|
||||
|
||||
ok(up ^ down, "DIRECTION_UP and DIRECTION_DOWN are not bitwise disjoint");
|
||||
ok(up ^ left, "DIRECTION_UP and DIRECTION_LEFT are not bitwise disjoint");
|
||||
ok(up ^ right, "DIRECTION_UP and DIRECTION_RIGHT are not bitwise disjoint");
|
||||
ok(down ^ left, "DIRECTION_DOWN and DIRECTION_LEFT are not bitwise disjoint");
|
||||
ok(down ^ right, "DIRECTION_DOWN and DIRECTION_RIGHT are not bitwise disjoint");
|
||||
ok(left ^ right, "DIRECTION_LEFT and DIRECTION_RIGHT are not bitwise disjoint");
|
||||
ok(clockwise ^ cclockwise, "ROTATION_CLOCKWISE and ROTATION_COUNTERCLOCKWISE are not bitwise disjoint");
|
||||
}
|
||||
|
||||
// Helper for test of latched event processing. Emits the actual
|
||||
|
@ -436,18 +436,14 @@ function openAdvancedPreferences(tabID)
|
||||
|
||||
/**
|
||||
* Opens the release notes page for this version of the application.
|
||||
* @param event
|
||||
* The DOM Event that caused this function to be called, used to
|
||||
* determine where the release notes page should be displayed based
|
||||
* on modifiers (e.g. Ctrl = new tab)
|
||||
*/
|
||||
function openReleaseNotes(event)
|
||||
function openReleaseNotes()
|
||||
{
|
||||
var formatter = Components.classes["@mozilla.org/toolkit/URLFormatterService;1"]
|
||||
.getService(Components.interfaces.nsIURLFormatter);
|
||||
var relnotesURL = formatter.formatURLPref("app.releaseNotesURL");
|
||||
|
||||
openUILink(relnotesURL, event, false, true);
|
||||
openUILinkIn(relnotesURL, "tab");
|
||||
}
|
||||
|
||||
#ifdef MOZ_UPDATER
|
||||
|
@ -161,17 +161,7 @@ FeedConverter.prototype = {
|
||||
* Records if the feed was sniffed
|
||||
*/
|
||||
_sniffed: false,
|
||||
|
||||
/**
|
||||
* See nsIStreamConverter.idl
|
||||
*/
|
||||
canConvert: function FC_canConvert(sourceType, destinationType) {
|
||||
// We only support one conversion.
|
||||
return destinationType == TYPE_ANY && ((sourceType == TYPE_MAYBE_FEED) ||
|
||||
(sourceType == TYPE_MAYBE_VIDEO) ||
|
||||
(sourceType == TYPE_MAYBE_AUDIO));
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* See nsIStreamConverter.idl
|
||||
*/
|
||||
@ -362,7 +352,7 @@ FeedConverter.prototype = {
|
||||
/**
|
||||
* See nsIRequestObserver.idl
|
||||
*/
|
||||
onStopRequest: function FC_onStopReqeust(request, context, status) {
|
||||
onStopRequest: function FC_onStopRequest(request, context, status) {
|
||||
if (this._processor)
|
||||
this._processor.onStopRequest(request, context, status);
|
||||
},
|
||||
|
@ -130,7 +130,8 @@ PlacesController.prototype = {
|
||||
case "cmd_delete":
|
||||
return this._hasRemovableSelection(false);
|
||||
case "placesCmd_deleteDataHost":
|
||||
return this._hasRemovableSelection(false);
|
||||
return this._hasRemovableSelection(false) &&
|
||||
!PlacesUIUtils.privateBrowsing.privateBrowsingEnabled;
|
||||
case "placesCmd_moveBookmarks":
|
||||
return this._hasRemovableSelection(true);
|
||||
case "cmd_copy":
|
||||
@ -230,10 +231,8 @@ PlacesController.prototype = {
|
||||
this.remove("Remove Selection");
|
||||
break;
|
||||
case "placesCmd_deleteDataHost":
|
||||
let pb = Cc["@mozilla.org/privatebrowsing;1"].
|
||||
getService(Ci.nsIPrivateBrowsingService);
|
||||
let uri = PlacesUtils._uri(this._view.selectedNode.uri);
|
||||
pb.removeDataFromDomain(uri.host);
|
||||
PlacesUIUtils.privateBrowsing.removeDataFromDomain(uri.host);
|
||||
break;
|
||||
case "cmd_selectAll":
|
||||
this.selectAll();
|
||||
@ -581,6 +580,8 @@ PlacesController.prototype = {
|
||||
* attribute are set.
|
||||
* 7) These attributes should not be set on separators for which the
|
||||
* visibility state is "auto-detected."
|
||||
* 8) The "hideifprivatebrowsing" attribute may be set on a menu-item to
|
||||
* true if it should be hidden inside the private browsing mode
|
||||
* @param aPopup
|
||||
* The menupopup to build children into.
|
||||
* @return true if at least one item is visible, false otherwise.
|
||||
@ -597,8 +598,11 @@ PlacesController.prototype = {
|
||||
var item = aPopup.childNodes[i];
|
||||
if (item.localName != "menuseparator") {
|
||||
// We allow pasting into tag containers, so special case that.
|
||||
item.hidden = (item.getAttribute("hideifnoinsertionpoint") == "true" &&
|
||||
noIp && !(ip && ip.isTag && item.id == "placesContext_paste")) ||
|
||||
var hideIfNoIP = item.getAttribute("hideifnoinsertionpoint") == "true" &&
|
||||
noIp && !(ip && ip.isTag && item.id == "placesContext_paste");
|
||||
var hideIfPB = item.getAttribute("hideifprivatebrowsing") == "true" &&
|
||||
PlacesUIUtils.privateBrowsing.privateBrowsingEnabled;
|
||||
item.hidden = hideIfNoIP || hideIfPB ||
|
||||
!this._shouldShowMenuItem(item, metadata);
|
||||
|
||||
if (!item.hidden) {
|
||||
|
@ -228,7 +228,6 @@ var gEditItemOverlay = {
|
||||
|
||||
// tags selector
|
||||
this._rebuildTagsSelectorList();
|
||||
this._initialized = true;
|
||||
}
|
||||
|
||||
// name picker
|
||||
@ -243,6 +242,8 @@ var gEditItemOverlay = {
|
||||
window.addEventListener("unload", this, false);
|
||||
this._observersAdded = true;
|
||||
}
|
||||
|
||||
this._initialized = true;
|
||||
},
|
||||
|
||||
_getCommonTags: function(aArrIndex) {
|
||||
@ -809,7 +810,7 @@ var gEditItemOverlay = {
|
||||
// breaks the view.
|
||||
const FOLDER_TREE_PLACE_URI =
|
||||
"place:excludeItems=1&excludeQueries=1&excludeReadOnlyFolders=1&folder=" +
|
||||
window.top.PlacesUIUtils.allBookmarksFolderId;
|
||||
PlacesUIUtils.allBookmarksFolderId;
|
||||
this._folderTree.place = FOLDER_TREE_PLACE_URI;
|
||||
|
||||
this._element("chooseFolderSeparator").hidden =
|
||||
|
@ -688,6 +688,16 @@ var PlacesOrganizer = {
|
||||
gEditItemOverlay.initPanel(itemId, { hiddenRows: ["folderPicker"],
|
||||
forceReadOnly: readOnly });
|
||||
|
||||
// Dynamically generated queries, like history date containers, have
|
||||
// itemId !=0 and do not exist in history. For them the panel is
|
||||
// read-only, but empty, since it can't get a valid title for the object.
|
||||
// In such a case we force the title using the selectedNode one, for UI
|
||||
// polishness.
|
||||
if (aSelectedNode.itemId == -1 &&
|
||||
(PlacesUtils.nodeIsDay(aSelectedNode) ||
|
||||
PlacesUtils.nodeIsHost(aSelectedNode)))
|
||||
gEditItemOverlay._element("namePicker").value = aSelectedNode.title;
|
||||
|
||||
this._detectAndSetDetailsPaneMinimalState(aSelectedNode);
|
||||
}
|
||||
else if (!aSelectedNode && aNodeList[0]) {
|
||||
|
@ -191,14 +191,12 @@
|
||||
<toolbarbutton id="back-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
|
||||
command="OrganizerCommand:Back"
|
||||
tooltiptext="&backButton.tooltip;"
|
||||
accesskey="&backCmd.accesskey;"
|
||||
chromedir="&locale.dir;"
|
||||
disabled="true"/>
|
||||
|
||||
<toolbarbutton id="forward-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
|
||||
command="OrganizerCommand:Forward"
|
||||
tooltiptext="&forwardButton.tooltip;"
|
||||
accesskey="&forwardCmd.accesskey;"
|
||||
chromedir="&locale.dir;"
|
||||
disabled="true"/>
|
||||
|
||||
|
@ -195,6 +195,8 @@
|
||||
accesskey="&cmd.deleteDomainData.accesskey;"
|
||||
closemenu="single"
|
||||
selection="link"
|
||||
selectiontype="single"
|
||||
hideifprivatebrowsing="true"
|
||||
forcehideselection="bookmark"/>
|
||||
<menuseparator id="placesContext_deleteSeparator"/>
|
||||
<menuitem id="placesContext_reload"
|
||||
|
@ -62,7 +62,7 @@ const LMANNO_FEEDURI = "livemark/feedURI";
|
||||
const LMANNO_SITEURI = "livemark/siteURI";
|
||||
const ORGANIZER_FOLDER_ANNO = "PlacesOrganizer/OrganizerFolder";
|
||||
const ORGANIZER_QUERY_ANNO = "PlacesOrganizer/OrganizerQuery";
|
||||
const ORGANIZER_LEFTPANE_VERSION = 5;
|
||||
const ORGANIZER_LEFTPANE_VERSION = 6;
|
||||
const EXCLUDE_FROM_BACKUP_ANNO = "places/excludeFromBackup";
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
@ -129,6 +129,12 @@ var PlacesUIUtils = {
|
||||
Ci.nsIPrefLocalizedString).data;
|
||||
},
|
||||
|
||||
get privateBrowsing() {
|
||||
delete this.privateBrowsing;
|
||||
return this.privateBrowsing = Cc["@mozilla.org/privatebrowsing;1"].
|
||||
getService(Ci.nsIPrivateBrowsingService);
|
||||
},
|
||||
|
||||
/**
|
||||
* Makes a URI from a spec, and do fixup
|
||||
* @param aSpec
|
||||
@ -1195,7 +1201,9 @@ var PlacesUIUtils = {
|
||||
PlacesUtils.bookmarks.setFolderReadonly(leftPaneRoot, true);
|
||||
|
||||
// History Query
|
||||
let uri = PlacesUtils._uri("place:sort=4&");
|
||||
let uri = PlacesUtils._uri("place:type=" +
|
||||
Ci.nsINavHistoryQueryOptions.RESULTS_AS_DATE_QUERY +
|
||||
"&sort=4");
|
||||
let title = self.getString("OrganizerQueryHistory");
|
||||
let itemId = PlacesUtils.bookmarks.insertBookmark(leftPaneRoot, uri, -1, title);
|
||||
PlacesUtils.annotations.setItemAnnotation(itemId, ORGANIZER_QUERY_ANNO,
|
||||
|
@ -44,6 +44,7 @@ include $(DEPTH)/config/autoconf.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
_BROWSER_TEST_FILES = \
|
||||
browser_0_library_left_pane_migration.js \
|
||||
browser_425884.js \
|
||||
browser_423515.js \
|
||||
browser_410196_paste_into_tags.js \
|
||||
@ -53,6 +54,8 @@ _BROWSER_TEST_FILES = \
|
||||
browser_library_panel_leak.js \
|
||||
browser_library_search.js \
|
||||
browser_history_sidebar_search.js \
|
||||
browser_bookmarksProperties.js \
|
||||
browser_forgetthissite_single.js \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_BROWSER_TEST_FILES)
|
||||
|
@ -0,0 +1,144 @@
|
||||
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* ***** 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 Places test code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Corp.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Marco Bonardo <mak77@bonardo.net> (Original Author)
|
||||
*
|
||||
* 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 devaring the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not devare
|
||||
* 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 ***** */
|
||||
|
||||
/**
|
||||
* Test we correctly migrate Library left pane to the latest version.
|
||||
* Note: this test MUST be the first between browser chrome tests, or results
|
||||
* of next tests could be unexpected due to PlacesUIUtils getters.
|
||||
*/
|
||||
|
||||
const TEST_URI = "http://www.mozilla.org/";
|
||||
|
||||
var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
|
||||
getService(Ci.nsIWindowWatcher);
|
||||
|
||||
var windowObserver = {
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
if (aTopic === "domwindowopened") {
|
||||
ww.unregisterNotification(this);
|
||||
var organizer = aSubject.QueryInterface(Ci.nsIDOMWindow);
|
||||
organizer.addEventListener("load", function onLoad(event) {
|
||||
organizer.removeEventListener("load", onLoad, false);
|
||||
executeSoon(function () {
|
||||
// Check left pane.
|
||||
ok(PlacesUIUtils.leftPaneFolderId > 0,
|
||||
"Left pane folder correctly created");
|
||||
var leftPaneItems =
|
||||
PlacesUtils.annotations
|
||||
.getItemsWithAnnotation(ORGANIZER_FOLDER_ANNO, {});
|
||||
is(leftPaneItems.length, 1,
|
||||
"We correctly have only 1 left pane folder");
|
||||
var leftPaneRoot = leftPaneItems[0];
|
||||
is(leftPaneRoot, PlacesUIUtils.leftPaneFolderId,
|
||||
"leftPaneFolderId getter has correct value");
|
||||
// Check version has been upgraded.
|
||||
var version =
|
||||
PlacesUtils.annotations.getItemAnnotation(leftPaneRoot,
|
||||
ORGANIZER_FOLDER_ANNO);
|
||||
is(version, ORGANIZER_LEFTPANE_VERSION,
|
||||
"Left pane version has been correctly upgraded");
|
||||
|
||||
// Check left pane is populated.
|
||||
organizer.PlacesOrganizer.selectLeftPaneQuery('History');
|
||||
is(organizer.PlacesOrganizer._places.selectedNode.itemId,
|
||||
PlacesUIUtils.leftPaneQueries["History"],
|
||||
"Library left pane is populated and working");
|
||||
|
||||
// Close Library window.
|
||||
organizer.close();
|
||||
// No need to cleanup anything, we have a correct left pane now.
|
||||
finish();
|
||||
});
|
||||
}, false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
// Sanity checks.
|
||||
ok(PlacesUtils, "PlacesUtils is running in chrome context");
|
||||
ok(PlacesUIUtils, "PlacesUIUtils is running in chrome context");
|
||||
ok(ORGANIZER_LEFTPANE_VERSION > 0,
|
||||
"Left pane version in chrome context, current version is: " + ORGANIZER_LEFTPANE_VERSION );
|
||||
|
||||
// Check if we have any left pane folder already set, remove it eventually.
|
||||
var leftPaneItems = PlacesUtils.annotations
|
||||
.getItemsWithAnnotation(ORGANIZER_FOLDER_ANNO, {});
|
||||
if (leftPaneItems.length > 0) {
|
||||
// The left pane has already been created, touching it now would cause
|
||||
// next tests to rely on wrong values (and possibly crash)
|
||||
is(leftPaneItems.length, 1, "We correctly have only 1 left pane folder");
|
||||
// Check version.
|
||||
var version = PlacesUtils.annotations.getItemAnnotation(leftPaneItems[0],
|
||||
ORGANIZER_FOLDER_ANNO);
|
||||
is(version, ORGANIZER_LEFTPANE_VERSION, "Left pane version is actual");
|
||||
ok(true, "left pane has already been created, skipping test");
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a fake left pane folder with an old version (current version - 1).
|
||||
var fakeLeftPaneRoot =
|
||||
PlacesUtils.bookmarks.createFolder(PlacesUtils.placesRootId, "",
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX);
|
||||
PlacesUtils.annotations.setItemAnnotation(fakeLeftPaneRoot,
|
||||
ORGANIZER_FOLDER_ANNO,
|
||||
ORGANIZER_LEFTPANE_VERSION - 1,
|
||||
0,
|
||||
PlacesUtils.annotations.EXPIRE_NEVER);
|
||||
|
||||
// Check fake left pane root has been correctly created.
|
||||
var leftPaneItems =
|
||||
PlacesUtils.annotations.getItemsWithAnnotation(ORGANIZER_FOLDER_ANNO, {});
|
||||
is(leftPaneItems.length, 1, "We correctly have only 1 left pane folder");
|
||||
is(leftPaneItems[0], fakeLeftPaneRoot, "left pane root itemId is correct");
|
||||
|
||||
// Check version.
|
||||
var version = PlacesUtils.annotations.getItemAnnotation(fakeLeftPaneRoot,
|
||||
ORGANIZER_FOLDER_ANNO);
|
||||
is(version, ORGANIZER_LEFTPANE_VERSION - 1, "Left pane version correctly set");
|
||||
|
||||
// Open Library, this will upgrade our left pane version.
|
||||
ww.registerNotification(windowObserver);
|
||||
ww.openWindow(null,
|
||||
"chrome://browser/content/places/places.xul",
|
||||
"",
|
||||
"chrome,toolbar=yes,dialog=no,resizable",
|
||||
null);
|
||||
}
|
@ -127,6 +127,9 @@ function test() {
|
||||
copyHistNode: function (){
|
||||
// focus the history object
|
||||
PO.selectLeftPaneQuery("History");
|
||||
var histContainer = PO._places.selectedNode.QueryInterface(Ci.nsINavHistoryContainerResultNode);
|
||||
histContainer.containerOpen = true;
|
||||
PO._places.selectNode(histContainer.getChild(0));
|
||||
this.histNode = PO._content.view.nodeForTreeIndex(0);
|
||||
PO._content.selectNode(this.histNode);
|
||||
is(this.histNode.uri, MOZURISPEC,
|
||||
@ -159,6 +162,9 @@ function test() {
|
||||
historyNode: function (){
|
||||
// re-focus the history again
|
||||
PO.selectLeftPaneQuery("History");
|
||||
var histContainer = PO._places.selectedNode.QueryInterface(Ci.nsINavHistoryContainerResultNode);
|
||||
histContainer.containerOpen = true;
|
||||
PO._places.selectNode(histContainer.getChild(0));
|
||||
var histNode = PO._content.view.nodeForTreeIndex(0);
|
||||
ok(histNode, "histNode exists: " + histNode.title);
|
||||
// check to see if the history node is tagged!
|
||||
|
@ -0,0 +1,468 @@
|
||||
/* ***** 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 Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Marco Bonardo <mak77@bonardo.net>
|
||||
*
|
||||
* 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 ***** */
|
||||
|
||||
/**
|
||||
* Tests the bookmarks Properties dialog.
|
||||
*/
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
// DOM ids of Places sidebar trees.
|
||||
const SIDEBAR_HISTORY_ID = "historyTree";
|
||||
const SIDEBAR_BOOKMARKS_ID = "bookmarks-view";
|
||||
|
||||
// Action to execute on the current node.
|
||||
const ACTION_EDIT = 0;
|
||||
const ACTION_ADD = 1;
|
||||
|
||||
// If action is ACTION_ADD, set type to one of those, to define what do you
|
||||
// want to create.
|
||||
const TYPE_FOLDER = 0;
|
||||
const TYPE_BOOKMARK = 1;
|
||||
|
||||
const TEST_URL = "http://www.mozilla.org/";
|
||||
|
||||
var wm = Cc["@mozilla.org/appshell/window-mediator;1"].
|
||||
getService(Ci.nsIWindowMediator);
|
||||
var win = wm.getMostRecentWindow("navigator:browser");
|
||||
var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
|
||||
getService(Ci.nsIWindowWatcher);
|
||||
|
||||
function add_visit(aURI, aDate) {
|
||||
var visitId = PlacesUtils.history
|
||||
.addVisit(aURI,
|
||||
aDate,
|
||||
null, // no referrer
|
||||
PlacesUtils.history.TRANSITION_TYPED,
|
||||
false, // not redirect
|
||||
0);
|
||||
return visitId;
|
||||
}
|
||||
|
||||
function add_bookmark(aURI) {
|
||||
var bId = PlacesUtils.bookmarks
|
||||
.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
|
||||
aURI,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
"bookmark/" + aURI.spec);
|
||||
return bId;
|
||||
}
|
||||
|
||||
// Each test is an obj w/ a desc property and run method.
|
||||
var gTests = [];
|
||||
var gCurrentTest = null;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// TEST SKELETON: use this template to add new tests.
|
||||
/*
|
||||
gTests.push({
|
||||
desc: "Bug Description",
|
||||
sidebar: SIDEBAR_BOOKMARKS_ID, // See SIDEBAR_ constants above.
|
||||
action: ACTION_EDIT, // See ACTION_ constants above.
|
||||
itemType: null, // See TYPE_ constants above, required for ACTION_ADD.
|
||||
window: null, // Will contain handle of dialog window
|
||||
|
||||
setup: function() {
|
||||
// Setup everything needed for this test, runs before everything else.
|
||||
},
|
||||
|
||||
selectNode: function(tree) {
|
||||
// Select the node to edit or to add to, runs when sidebar tree is visible.
|
||||
},
|
||||
|
||||
run: function() {
|
||||
// Actual test, runs when dialog is open.
|
||||
},
|
||||
|
||||
finish: function() {
|
||||
// Close window, toggle sidebar and goto next test.
|
||||
this.window.document.documentElement.cancelDialog();
|
||||
toggleSidebar("viewBookmarksSidebar", false);
|
||||
runNextTest();
|
||||
},
|
||||
|
||||
cleanup: function() {
|
||||
// Undo everything added during setup, runs after dialog has been closed.
|
||||
}
|
||||
});
|
||||
*/
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Bug 479348 - Properties on a root should be read-only
|
||||
|
||||
gTests.push({
|
||||
desc: "Bug 479348 - Properties on a root should be read-only",
|
||||
sidebar: SIDEBAR_BOOKMARKS_ID,
|
||||
action: ACTION_EDIT,
|
||||
itemType: null,
|
||||
window: null,
|
||||
|
||||
setup: function() {
|
||||
// Nothing to do.
|
||||
},
|
||||
|
||||
selectNode: function(tree) {
|
||||
// Select Unfiled Bookmarks root.
|
||||
var itemId = PlacesUIUtils.leftPaneQueries["UnfiledBookmarks"];
|
||||
tree.selectItems([itemId]);
|
||||
this.selectedNode = tree.selectedNode;
|
||||
},
|
||||
|
||||
run: function() {
|
||||
// Check that the dialog is read-only.
|
||||
ok(this.window.BookmarkPropertiesPanel._readOnly, "Dialog is read-only");
|
||||
|
||||
// Check that accept button is disabled
|
||||
var acceptButton = this.window.document.documentElement.getButton("accept");
|
||||
ok(acceptButton.disabled, "Accept button is disabled");
|
||||
|
||||
// Check that name picker is read only
|
||||
var namepicker = this.window.document.getElementById("editBMPanel_namePicker");
|
||||
ok(namepicker.readOnly, "Name field is disabled");
|
||||
is(namepicker.value,
|
||||
PlacesUtils.bookmarks.getItemTitle(PlacesUtils.unfiledBookmarksFolderId),
|
||||
"Node title is correct");
|
||||
// Blur the field and ensure root's name has not been changed.
|
||||
this.window.gEditItemOverlay.onNamePickerChange();
|
||||
is(namepicker.value,
|
||||
PlacesUtils.bookmarks.getItemTitle(PlacesUtils.unfiledBookmarksFolderId),
|
||||
"Root title is correct");
|
||||
// Check the shortcut's title.
|
||||
is(PlacesUtils.bookmarks.getItemTitle(this.selectedNode.itemId), null,
|
||||
"Shortcut title is null");
|
||||
this.finish();
|
||||
},
|
||||
|
||||
finish: function() {
|
||||
this.window.document.documentElement.cancelDialog();
|
||||
toggleSidebar("viewBookmarksSidebar", false);
|
||||
runNextTest();
|
||||
},
|
||||
|
||||
cleanup: function() {
|
||||
// Nothing to do.
|
||||
}
|
||||
});
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Bug 462662 - Pressing Enter to select tag from autocomplete closes bookmarks properties dialog
|
||||
|
||||
gTests.push({
|
||||
desc: "Bug 462662 - Pressing Enter to select tag from autocomplete closes bookmarks properties dialog",
|
||||
sidebar: SIDEBAR_BOOKMARKS_ID,
|
||||
action: ACTION_EDIT,
|
||||
itemType: null,
|
||||
window: null,
|
||||
_itemId: null,
|
||||
|
||||
setup: function() {
|
||||
// Add a bookmark in unsorted bookmarks folder.
|
||||
this._itemId = add_bookmark(PlacesUtils._uri(TEST_URL));
|
||||
ok(this._itemId > 0, "Correctly added a bookmark");
|
||||
// Add a tag to this bookmark.
|
||||
PlacesUtils.tagging.tagURI(PlacesUtils._uri(TEST_URL),
|
||||
["testTag"]);
|
||||
var tags = PlacesUtils.tagging.getTagsForURI(PlacesUtils._uri(TEST_URL), {});
|
||||
is(tags[0], "testTag", "Correctly added a tag");
|
||||
},
|
||||
|
||||
selectNode: function(tree) {
|
||||
tree.selectItems([this._itemId]);
|
||||
is(tree.selectedNode.itemId, this._itemId, "Bookmark has been selected");
|
||||
},
|
||||
|
||||
run: function() {
|
||||
// open tags autocomplete and press enter
|
||||
var tagsField = this.window.document.getElementById("editBMPanel_tagsField");
|
||||
var self = this;
|
||||
tagsField.popup.addEventListener("popupshown", function (aEvent) {
|
||||
tagsField.popup.removeEventListener("popupshown", arguments.callee, true);
|
||||
tagsField.popup.focus();
|
||||
EventUtils.synthesizeKey("VK_RETURN", {}, self.window);
|
||||
}, true);
|
||||
tagsField.popup.addEventListener("popuphidden", function (aEvent) {
|
||||
tagsField.popup.removeEventListener("popuphidden", arguments.callee, true);
|
||||
self.finish();
|
||||
}, true);
|
||||
tagsField.focus();
|
||||
tagsField.value = "";
|
||||
EventUtils.synthesizeKey("t", {}, this.window);
|
||||
},
|
||||
|
||||
finish: function() {
|
||||
isnot(this.window, null, "Window is still open");
|
||||
this.window.document.documentElement.cancelDialog();
|
||||
toggleSidebar("viewBookmarksSidebar", false);
|
||||
runNextTest();
|
||||
},
|
||||
|
||||
cleanup: function() {
|
||||
// Check tags have not changed.
|
||||
var tags = PlacesUtils.tagging.getTagsForURI(PlacesUtils._uri(TEST_URL), {});
|
||||
is(tags[0], "testTag", "Tag on node has not changed");
|
||||
|
||||
// Cleanup.
|
||||
PlacesUtils.tagging.untagURI(PlacesUtils._uri(TEST_URL), ["testTag"]);
|
||||
PlacesUtils.bookmarks.removeItem(this._itemId);
|
||||
}
|
||||
});
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Bug 475529 - Add button in new folder dialog not default anymore
|
||||
|
||||
gTests.push({
|
||||
desc: "Bug 475529 - Add button in new folder dialog not default anymore",
|
||||
sidebar: SIDEBAR_BOOKMARKS_ID,
|
||||
action: ACTION_ADD,
|
||||
itemType: TYPE_FOLDER,
|
||||
window: null,
|
||||
_itemId: null,
|
||||
|
||||
setup: function() {
|
||||
// Nothing to do.
|
||||
},
|
||||
|
||||
selectNode: function(tree) {
|
||||
// Select Unfiled Bookmarks root.
|
||||
var itemId = PlacesUIUtils.leftPaneQueries["UnfiledBookmarks"];
|
||||
tree.selectItems([itemId]);
|
||||
this.selectedNode = tree.selectedNode;
|
||||
},
|
||||
|
||||
run: function() {
|
||||
this._itemId = this.window.gEditItemOverlay._itemId;
|
||||
// Change folder name
|
||||
var namePicker = this.window.document.getElementById("editBMPanel_namePicker");
|
||||
namePicker.value = "";
|
||||
var self = this;
|
||||
this.window.addEventListener("unload", function(event) {
|
||||
this.window.removeEventListener("unload", arguments.callee, false);
|
||||
executeSoon(function() {
|
||||
self.finish();
|
||||
});
|
||||
}, false);
|
||||
namePicker.focus();
|
||||
EventUtils.synthesizeKey("n", {}, this.window);
|
||||
EventUtils.synthesizeKey("VK_RETURN", {}, this.window);
|
||||
},
|
||||
|
||||
finish: function() {
|
||||
// Window is already closed.
|
||||
toggleSidebar("viewBookmarksSidebar", false);
|
||||
runNextTest();
|
||||
},
|
||||
|
||||
cleanup: function() {
|
||||
// Check that folder name has been changed.
|
||||
is(PlacesUtils.bookmarks.getItemTitle(this._itemId), "n",
|
||||
"Folder name has been edited");
|
||||
|
||||
// Cleanup.
|
||||
PlacesUtils.bookmarks.removeItem(this._itemId);
|
||||
}
|
||||
});
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Bug 476020 - Pressing Esc while having the tag autocomplete open closes the bookmarks panel
|
||||
|
||||
gTests.push({
|
||||
desc: "Bug 476020 - Pressing Esc while having the tag autocomplete open closes the bookmarks panel",
|
||||
sidebar: SIDEBAR_BOOKMARKS_ID,
|
||||
action: ACTION_EDIT,
|
||||
itemType: null,
|
||||
window: null,
|
||||
_itemId: null,
|
||||
|
||||
setup: function() {
|
||||
// Add a bookmark in unsorted bookmarks folder.
|
||||
this._itemId = add_bookmark(PlacesUtils._uri(TEST_URL));
|
||||
ok(this._itemId > 0, "Correctly added a bookmark");
|
||||
// Add a tag to this bookmark.
|
||||
PlacesUtils.tagging.tagURI(PlacesUtils._uri(TEST_URL),
|
||||
["testTag"]);
|
||||
var tags = PlacesUtils.tagging.getTagsForURI(PlacesUtils._uri(TEST_URL), {});
|
||||
is(tags[0], "testTag", "Correctly added a tag");
|
||||
},
|
||||
|
||||
selectNode: function(tree) {
|
||||
tree.selectItems([this._itemId]);
|
||||
is(tree.selectedNode.itemId, this._itemId, "Bookmark has been selected");
|
||||
},
|
||||
|
||||
run: function() {
|
||||
// open tags autocomplete and press enter
|
||||
var tagsField = this.window.document.getElementById("editBMPanel_tagsField");
|
||||
var self = this;
|
||||
tagsField.popup.addEventListener("popupshown", function (aEvent) {
|
||||
tagsField.popup.removeEventListener("popupshown", arguments.callee, true);
|
||||
tagsField.popup.focus();
|
||||
EventUtils.synthesizeKey("VK_ESCAPE", {}, self.window);
|
||||
}, true);
|
||||
tagsField.popup.addEventListener("popuphidden", function (aEvent) {
|
||||
tagsField.popup.removeEventListener("popuphidden", arguments.callee, true);
|
||||
self.finish();
|
||||
}, true);
|
||||
tagsField.focus();
|
||||
tagsField.value = "";
|
||||
EventUtils.synthesizeKey("t", {}, this.window);
|
||||
},
|
||||
|
||||
finish: function() {
|
||||
isnot(this.window, null, "Window is still open");
|
||||
this.window.document.documentElement.cancelDialog();
|
||||
toggleSidebar("viewBookmarksSidebar", false);
|
||||
runNextTest();
|
||||
},
|
||||
|
||||
cleanup: function() {
|
||||
// Check tags have not changed.
|
||||
var tags = PlacesUtils.tagging.getTagsForURI(PlacesUtils._uri(TEST_URL), {});
|
||||
is(tags[0], "testTag", "Tag on node has not changed");
|
||||
|
||||
// Cleanup.
|
||||
PlacesUtils.tagging.untagURI(PlacesUtils._uri(TEST_URL),
|
||||
["testTag"]);
|
||||
PlacesUtils.bookmarks.removeItem(this._itemId);
|
||||
}
|
||||
});
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
// Sanity checks.
|
||||
ok(PlacesUtils, "PlacesUtils in context");
|
||||
ok(PlacesUIUtils, "PlacesUIUtils in context");
|
||||
|
||||
// kick off tests
|
||||
runNextTest();
|
||||
}
|
||||
|
||||
function runNextTest() {
|
||||
// Cleanup from previous test.
|
||||
if (gCurrentTest) {
|
||||
gCurrentTest.cleanup();
|
||||
ok(true, "*** FINISHED TEST ***");
|
||||
}
|
||||
|
||||
if (gTests.length > 0) {
|
||||
// Goto next tests.
|
||||
gCurrentTest = gTests.shift();
|
||||
ok(true, "*** TEST: " + gCurrentTest.desc);
|
||||
gCurrentTest.setup();
|
||||
execute_test_in_sidebar();
|
||||
}
|
||||
else {
|
||||
// Finished all tests.
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Global functions to run a test in Properties dialog context.
|
||||
*/
|
||||
|
||||
function execute_test_in_sidebar() {
|
||||
var sidebar = document.getElementById("sidebar");
|
||||
sidebar.addEventListener("load", function() {
|
||||
sidebar.removeEventListener("load", arguments.callee, true);
|
||||
sidebar.focus();
|
||||
// Need to executeSoon since the tree is initialized on sidebar load.
|
||||
executeSoon(open_properties_dialog);
|
||||
}, true);
|
||||
toggleSidebar("viewBookmarksSidebar", true);
|
||||
}
|
||||
|
||||
function open_properties_dialog() {
|
||||
var sidebar = document.getElementById("sidebar");
|
||||
// Get sidebar's Places tree.
|
||||
var tree = sidebar.contentDocument.getElementById(gCurrentTest.sidebar);
|
||||
ok(tree, "Sidebar tree has been loaded");
|
||||
// Ask current test to select the node to edit.
|
||||
gCurrentTest.selectNode(tree);
|
||||
ok(tree.selectedNode,
|
||||
"We have a places node selected: " + tree.selectedNode.title);
|
||||
|
||||
// Wait for the Properties dialog.
|
||||
var windowObserver = {
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
if (aTopic === "domwindowopened") {
|
||||
ww.unregisterNotification(this);
|
||||
var win = aSubject.QueryInterface(Ci.nsIDOMWindow);
|
||||
win.addEventListener("load", function onLoad(event) {
|
||||
win.removeEventListener("load", onLoad, false);
|
||||
// Windows has been loaded, execute our test now.
|
||||
executeSoon(function () {
|
||||
// Ensure overlay is loaded
|
||||
ok(win.gEditItemOverlay._initialized, "EditItemOverlay is initialized");
|
||||
gCurrentTest.window = win;
|
||||
try {
|
||||
gCurrentTest.run();
|
||||
} catch (ex) {
|
||||
ok(false, "An error occured during test run: " + ex.message);
|
||||
}
|
||||
});
|
||||
}, false);
|
||||
}
|
||||
}
|
||||
};
|
||||
ww.registerNotification(windowObserver);
|
||||
|
||||
var command = null;
|
||||
switch(gCurrentTest.action) {
|
||||
case ACTION_EDIT:
|
||||
command = "placesCmd_show:info";
|
||||
break;
|
||||
case ACTION_ADD:
|
||||
if (gCurrentTest.itemType == TYPE_FOLDER)
|
||||
command = "placesCmd_new:folder";
|
||||
else if (gCurrentTest.itemType == TYPE_BOOKMARK)
|
||||
command = "placesCmd_new:bookmark";
|
||||
else
|
||||
ok(false, "You didn't set a valid itemType for adding an item");
|
||||
break;
|
||||
default:
|
||||
ok(false, "You didn't set a valid action for this test");
|
||||
}
|
||||
// Ensure command is enabled for this node.
|
||||
ok(tree.controller.isCommandEnabled(command),
|
||||
"Properties command on current selected node is enabled");
|
||||
|
||||
// This will open the dialog.
|
||||
tree.controller.doCommand(command);
|
||||
}
|
@ -0,0 +1,123 @@
|
||||
/* ***** 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 Places test code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Ehsan Akhgari.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ehsan Akhgari <ehsan.akhgari@gmail.com> (Original Author)
|
||||
*
|
||||
* 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 ***** */
|
||||
|
||||
// This test makes sure that the Forget This Site command is hidden for multiple
|
||||
// selections.
|
||||
|
||||
function test() {
|
||||
// initialization
|
||||
let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
|
||||
getService(Ci.nsIWindowWatcher);
|
||||
waitForExplicitFinish();
|
||||
|
||||
// Add a history entry.
|
||||
let TEST_URIs = ["http://www.mozilla.org/test1", "http://www.mozilla.org/test2"];
|
||||
ok(PlacesUtils, "checking PlacesUtils, running in chrome context?");
|
||||
let history = PlacesUtils.history;
|
||||
TEST_URIs.forEach(function(TEST_URI) {
|
||||
let visidId = history.addVisit(PlacesUtils._uri(TEST_URI), Date.now() * 1000,
|
||||
null, PlacesUtils.history.TRANSITION_TYPED, false, 0);
|
||||
ok(visitId > 0, TEST_URI + " successfully marked visited");
|
||||
});
|
||||
|
||||
function testForgetThisSiteVisibility(selectionCount, funcNext) {
|
||||
let observer = {
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
if (aTopic === "domwindowopened") {
|
||||
ww.unregisterNotification(this);
|
||||
let organizer = aSubject.QueryInterface(Ci.nsIDOMWindow);
|
||||
organizer.addEventListener("load", function onLoad(event) {
|
||||
organizer.removeEventListener("load", onLoad, false);
|
||||
executeSoon(function () {
|
||||
// Select History in the left pane.
|
||||
organizer.PlacesOrganizer.selectLeftPaneQuery('History');
|
||||
let PO = organizer.PlacesOrganizer;
|
||||
let histContainer = PO._places.selectedNode.QueryInterface(Ci.nsINavHistoryContainerResultNode);
|
||||
histContainer.containerOpen = true;
|
||||
PO._places.selectNode(histContainer.getChild(0));
|
||||
// Select the first history entry.
|
||||
let doc = organizer.document;
|
||||
let tree = PO._content;
|
||||
let selection = tree.view.selection;
|
||||
selection.clearSelection();
|
||||
selection.rangedSelect(0, selectionCount - 1, true);
|
||||
is(selection.count, selectionCount,
|
||||
"The selected range is as big as expected");
|
||||
// Open the context menu
|
||||
let contextmenu = doc.getElementById("placesContext");
|
||||
contextmenu.addEventListener("popupshown", function() {
|
||||
contextmenu.removeEventListener("popupshown", arguments.callee, false);
|
||||
let forgetThisSite = doc.getElementById("placesContext_deleteHost");
|
||||
let hideForgetThisSite = (selectionCount != 1);
|
||||
is(forgetThisSite.hidden, hideForgetThisSite,
|
||||
"The Forget this site menu item should " + (hideForgetThisSite ? "" : "not ") +
|
||||
"be hidden with " + selectionCount + " items selected");
|
||||
// Close the context menu
|
||||
contextmenu.hidePopup();
|
||||
// Close Library window.
|
||||
organizer.close();
|
||||
// Proceed
|
||||
funcNext();
|
||||
}, false);
|
||||
let event = document.createEvent("MouseEvents");
|
||||
event.initMouseEvent("contextmenu", true, true, organizer, 0,
|
||||
0, 0, 0, 0, false, false, false, false,
|
||||
0, null);
|
||||
tree.dispatchEvent(event);
|
||||
});
|
||||
}, false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ww.registerNotification(observer);
|
||||
ww.openWindow(null,
|
||||
"chrome://browser/content/places/places.xul",
|
||||
"",
|
||||
"chrome,toolbar=yes,dialog=no,resizable",
|
||||
null);
|
||||
}
|
||||
|
||||
testForgetThisSiteVisibility(1, function() {
|
||||
testForgetThisSiteVisibility(2, function() {
|
||||
// Cleanup
|
||||
history.QueryInterface(Ci.nsIBrowserHistory)
|
||||
.removeAllPages();
|
||||
finish();
|
||||
});
|
||||
});
|
||||
}
|
@ -46,6 +46,7 @@ include $(topsrcdir)/config/rules.mk
|
||||
_CHROME_TEST_FILES = \
|
||||
test_treeview_date.xul \
|
||||
test_bug485100-change-case-loses-tag.xul \
|
||||
test_bug427633_no_newfolder_if_noip.xul \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_CHROME_TEST_FILES)
|
||||
|
@ -0,0 +1,123 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<!-- ***** 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 the Places test code.
|
||||
-
|
||||
- The Initial Developer of the Original Code is Mozilla Corp.
|
||||
- Portions created by the Initial Developer are Copyright (C) 2009
|
||||
- the Initial Developer. All Rights Reserved.
|
||||
-
|
||||
- Contributor(s):
|
||||
- Marco Bonardo <mak77@bonardo.net> (Original Author)
|
||||
-
|
||||
- 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 ***** -->
|
||||
|
||||
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
|
||||
type="text/css"?>
|
||||
|
||||
<?xml-stylesheet href="chrome://browser/skin/places/editBookmarkOverlay.css"?>
|
||||
<?xml-stylesheet href="chrome://browser/content/places/places.css"?>
|
||||
<?xml-stylesheet href="chrome://browser/skin/places/places.css"?>
|
||||
|
||||
<?xul-overlay href="chrome://browser/content/places/placesOverlay.xul"?>
|
||||
<?xul-overlay href="chrome://browser/content/places/editBookmarkOverlay.xul"?>
|
||||
|
||||
<!DOCTYPE window [
|
||||
<!ENTITY % editBookmarkOverlayDTD SYSTEM "chrome://browser/locale/places/editBookmarkOverlay.dtd">
|
||||
%editBookmarkOverlayDTD;
|
||||
]>
|
||||
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
title="Bug 427633 - Disable creating a New Folder in the bookmarks dialogs if insertionPoint is invalid"
|
||||
onload="runTest();">
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/MochiKit/packed.js" />
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
|
||||
<script type="application/javascript"
|
||||
src="chrome://browser/content/places/editBookmarkOverlay.js"/>
|
||||
|
||||
<body xmlns="http://www.w3.org/1999/xhtml" />
|
||||
|
||||
<vbox id="editBookmarkPanelContent"/>
|
||||
|
||||
<script type="application/javascript">
|
||||
<![CDATA[
|
||||
|
||||
/**
|
||||
* Bug 427633 - Disable creating a New Folder in the bookmarks dialogs if
|
||||
* insertionPoint is invalid.
|
||||
*/
|
||||
|
||||
function runTest() {
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
var bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
|
||||
getService(Ci.nsINavBookmarksService);
|
||||
var ios = Cc["@mozilla.org/network/io-service;1"].
|
||||
getService(Ci.nsIIOService);
|
||||
function uri(spec) {
|
||||
return ios.newURI(spec, null, null);
|
||||
}
|
||||
|
||||
// Add a bookmark.
|
||||
var itemId = bs.insertBookmark(bs.toolbarFolder,
|
||||
uri("http://www.mozilla.org/"),
|
||||
bs.DEFAULT_INDEX,
|
||||
"mozilla");
|
||||
|
||||
// Init panel.
|
||||
ok(gEditItemOverlay, "gEditItemOverlay is in context");
|
||||
gEditItemOverlay.initPanel(itemId);
|
||||
ok(gEditItemOverlay._initialized, "gEditItemOverlay is initialized");
|
||||
// We must be sure tree is initialized, so we wait for place to be set.
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
var tree = gEditItemOverlay._element("folderTree");
|
||||
tree.addEventListener("DOMAttrModified", function(event) {
|
||||
if (event.attrName != "place")
|
||||
return;
|
||||
tree.removeEventListener("DOMAttrModified", arguments.callee, false);
|
||||
SimpleTest.executeSoon(function() {
|
||||
tree.view.selection.clearSelection();
|
||||
ok(document.getElementById("editBMPanel_newFolderButton").disabled,
|
||||
"New folder button is disabled if there's no selection");
|
||||
|
||||
// Cleanup.
|
||||
bs.removeItem(itemId);
|
||||
SimpleTest.finish();
|
||||
});
|
||||
}, false);
|
||||
// Open the folder tree.
|
||||
document.getElementById("editBMPanel_foldersExpander").doCommand();
|
||||
}
|
||||
]]>
|
||||
</script>
|
||||
|
||||
</window>
|
@ -187,6 +187,8 @@ const SMART_BOOKMARKS_ON_MENU = 2;
|
||||
* @return nsIFile object for the file.
|
||||
*/
|
||||
function create_bookmarks_html(aFilename) {
|
||||
if (!aFilename)
|
||||
do_throw("you must pass a filename to create_bookmarks_html function");
|
||||
remove_bookmarks_html();
|
||||
let bookmarksHTMLFile = gTestDir.clone();
|
||||
bookmarksHTMLFile.append(aFilename);
|
||||
@ -232,6 +234,8 @@ function check_bookmarks_html() {
|
||||
* @return nsIFile object for the file.
|
||||
*/
|
||||
function create_JSON_backup(aFilename) {
|
||||
if (!aFilename)
|
||||
do_throw("you must pass a filename to create_JSON_backup function");
|
||||
remove_all_JSON_backups();
|
||||
let bookmarksBackupDir = gProfD.clone();
|
||||
bookmarksBackupDir.append("bookmarkbackups");
|
||||
@ -273,3 +277,56 @@ function check_JSON_backup() {
|
||||
do_check_true(profileBookmarksJSONFile.exists());
|
||||
return profileBookmarksJSONFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dumps the rows of a table out to the console.
|
||||
*
|
||||
* @param aName
|
||||
* The name of the table or view to output.
|
||||
*/
|
||||
function dump_table(aName)
|
||||
{
|
||||
let db = Cc["@mozilla.org/browser/nav-history-service;1"].
|
||||
getService(Ci.nsPIPlacesDatabase).
|
||||
DBConnection;
|
||||
let stmt = db.createStatement("SELECT * FROM " + aName);
|
||||
|
||||
dump("\n*** Printing data from " + aName + ":\n");
|
||||
let count = 0;
|
||||
while (stmt.executeStep()) {
|
||||
let columns = stmt.numEntries;
|
||||
|
||||
if (count == 0) {
|
||||
// print the column names
|
||||
for (let i = 0; i < columns; i++)
|
||||
dump(stmt.getColumnName(i) + "\t");
|
||||
dump("\n");
|
||||
}
|
||||
|
||||
// print the row
|
||||
for (let i = 0; i < columns; i++) {
|
||||
switch (stmt.getTypeOfIndex(i)) {
|
||||
case Ci.mozIStorageValueArray.VALUE_TYPE_NULL:
|
||||
dump("NULL\t");
|
||||
break;
|
||||
case Ci.mozIStorageValueArray.VALUE_TYPE_INTEGER:
|
||||
dump(stmt.getInt64(i) + "\t");
|
||||
break;
|
||||
case Ci.mozIStorageValueArray.VALUE_TYPE_FLOAT:
|
||||
dump(stmt.getDouble(i) + "\t");
|
||||
break;
|
||||
case Ci.mozIStorageValueArray.VALUE_TYPE_TEXT:
|
||||
dump(stmt.getString(i) + "\t");
|
||||
break;
|
||||
}
|
||||
}
|
||||
dump("\n");
|
||||
|
||||
count++;
|
||||
}
|
||||
dump("*** There were a total of " + count + " rows of data.\n\n");
|
||||
|
||||
stmt.reset();
|
||||
stmt.finalize();
|
||||
stmt = null;
|
||||
}
|
||||
|
@ -41,14 +41,42 @@
|
||||
* is corrupt but a JSON backup is not available.
|
||||
*/
|
||||
|
||||
const NS_PLACES_INIT_COMPLETE_TOPIC = "places-init-complete";
|
||||
|
||||
// Create an observer for the Places notifications
|
||||
var os = Cc["@mozilla.org/observer-service;1"].
|
||||
getService(Ci.nsIObserverService);
|
||||
var observer = {
|
||||
observe: function thn_observe(aSubject, aTopic, aData) {
|
||||
if (aTopic == NS_PLACES_INIT_COMPLETE_TOPIC) {
|
||||
os.removeObserver(this, NS_PLACES_INIT_COMPLETE_TOPIC);
|
||||
var hs = Cc["@mozilla.org/browser/nav-history-service;1"].
|
||||
getService(Ci.nsINavHistoryService);
|
||||
// Check the database was corrupt.
|
||||
// nsBrowserGlue uses databaseStatus to manage initialization.
|
||||
do_check_eq(hs.databaseStatus, hs.DATABASE_STATUS_CORRUPT);
|
||||
|
||||
// Enqueue next part of the test.
|
||||
var tm = Cc["@mozilla.org/thread-manager;1"].
|
||||
getService(Ci.nsIThreadManager);
|
||||
tm.mainThread.dispatch({
|
||||
run: function() {
|
||||
continue_test();
|
||||
}
|
||||
}, Ci.nsIThread.DISPATCH_NORMAL);
|
||||
}
|
||||
}
|
||||
};
|
||||
os.addObserver(observer, NS_PLACES_INIT_COMPLETE_TOPIC, false);
|
||||
|
||||
function run_test() {
|
||||
// Create bookmarks.html in the profile.
|
||||
create_bookmarks_html();
|
||||
create_bookmarks_html("bookmarks.glue.html");
|
||||
// Remove JSON backup from profile.
|
||||
remove_all_JSON_backups();
|
||||
|
||||
// Remove current database file.
|
||||
let db = gProfD.clone();
|
||||
var db = gProfD.clone();
|
||||
db.append("places.sqlite");
|
||||
if (db.exists()) {
|
||||
db.remove(false);
|
||||
@ -64,30 +92,19 @@ function run_test() {
|
||||
Cc["@mozilla.org/browser/browserglue;1"].getService(Ci.nsIBrowserGlue);
|
||||
|
||||
// Initialize Places through the History Service.
|
||||
let hs = Cc["@mozilla.org/browser/nav-history-service;1"].
|
||||
var hs = Cc["@mozilla.org/browser/nav-history-service;1"].
|
||||
getService(Ci.nsINavHistoryService);
|
||||
// Check the database was corrupt.
|
||||
// nsBrowserGlue uses databaseStatus to manage initialization.
|
||||
do_check_eq(hs.databaseStatus, hs.DATABASE_STATUS_CORRUPT);
|
||||
|
||||
// Restore could take some time, usually less than 1s.
|
||||
// We will poll later in continue_test to be sure restore has finished.
|
||||
// Wait for init-complete notification before going on.
|
||||
do_test_pending();
|
||||
do_timeout(1000, "continue_test();");
|
||||
}
|
||||
|
||||
function continue_test() {
|
||||
let bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
|
||||
var bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
|
||||
getService(Ci.nsINavBookmarksService);
|
||||
do_test_finished();
|
||||
if (bs.getIdForItemAt(bs.toolbarFolder, 0) == -1) {
|
||||
// Not enough time to complete restore, poll again later.
|
||||
do_timeout(1000, "continue_test();");
|
||||
return;
|
||||
}
|
||||
|
||||
// Check that default bookmarks have been restored.
|
||||
let itemId = bs.getIdForItemAt(bs.toolbarFolder, SMART_BOOKMARKS_ON_TOOLBAR);
|
||||
var itemId = bs.getIdForItemAt(bs.toolbarFolder, SMART_BOOKMARKS_ON_TOOLBAR);
|
||||
do_check_neq(itemId, -1);
|
||||
do_check_eq(bs.getItemTitle(itemId), "example");
|
||||
|
||||
do_test_finished();
|
||||
|
@ -41,6 +41,34 @@
|
||||
* corrupt, nor a JSON backup nor bookmarks.html are available.
|
||||
*/
|
||||
|
||||
const NS_PLACES_INIT_COMPLETE_TOPIC = "places-init-complete";
|
||||
|
||||
// Create an observer for the Places notifications
|
||||
var os = Cc["@mozilla.org/observer-service;1"].
|
||||
getService(Ci.nsIObserverService);
|
||||
var observer = {
|
||||
observe: function thn_observe(aSubject, aTopic, aData) {
|
||||
if (aTopic == NS_PLACES_INIT_COMPLETE_TOPIC) {
|
||||
os.removeObserver(this, NS_PLACES_INIT_COMPLETE_TOPIC);
|
||||
var hs = Cc["@mozilla.org/browser/nav-history-service;1"].
|
||||
getService(Ci.nsINavHistoryService);
|
||||
// Check the database was corrupt.
|
||||
// nsBrowserGlue uses databaseStatus to manage initialization.
|
||||
do_check_eq(hs.databaseStatus, hs.DATABASE_STATUS_CORRUPT);
|
||||
|
||||
// Enqueue next part of the test.
|
||||
var tm = Cc["@mozilla.org/thread-manager;1"].
|
||||
getService(Ci.nsIThreadManager);
|
||||
tm.mainThread.dispatch({
|
||||
run: function() {
|
||||
continue_test();
|
||||
}
|
||||
}, Ci.nsIThread.DISPATCH_NORMAL);
|
||||
}
|
||||
}
|
||||
};
|
||||
os.addObserver(observer, NS_PLACES_INIT_COMPLETE_TOPIC, false);
|
||||
|
||||
function run_test() {
|
||||
// Remove bookmarks.html from profile.
|
||||
remove_bookmarks_html();
|
||||
@ -48,7 +76,7 @@ function run_test() {
|
||||
remove_all_JSON_backups();
|
||||
|
||||
// Remove current database file.
|
||||
let db = gProfD.clone();
|
||||
var db = gProfD.clone();
|
||||
db.append("places.sqlite");
|
||||
if (db.exists()) {
|
||||
db.remove(false);
|
||||
@ -64,30 +92,19 @@ function run_test() {
|
||||
Cc["@mozilla.org/browser/browserglue;1"].getService(Ci.nsIBrowserGlue);
|
||||
|
||||
// Initialize Places through the History Service.
|
||||
let hs = Cc["@mozilla.org/browser/nav-history-service;1"].
|
||||
var hs = Cc["@mozilla.org/browser/nav-history-service;1"].
|
||||
getService(Ci.nsINavHistoryService);
|
||||
// Check the database was corrupt.
|
||||
// nsBrowserGlue uses databaseStatus to manage initialization.
|
||||
do_check_eq(hs.databaseStatus, hs.DATABASE_STATUS_CORRUPT);
|
||||
|
||||
// Restore could take some time, usually less than 1s.
|
||||
// We will poll later in continue_test to be sure restore has finished.
|
||||
// Wait for init-complete notification before going on.
|
||||
do_test_pending();
|
||||
do_timeout(1000, "continue_test();");
|
||||
}
|
||||
|
||||
function continue_test() {
|
||||
let bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
|
||||
var bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
|
||||
getService(Ci.nsINavBookmarksService);
|
||||
|
||||
if (bs.getIdForItemAt(bs.toolbarFolder, 1) == -1) {
|
||||
// Not enough time to complete restore, poll again later.
|
||||
do_timeout(1000, "continue_test();");
|
||||
return;
|
||||
}
|
||||
|
||||
// Check that default bookmarks have been restored.
|
||||
let itemId = bs.getIdForItemAt(bs.toolbarFolder, SMART_BOOKMARKS_ON_TOOLBAR + 1);
|
||||
var itemId = bs.getIdForItemAt(bs.toolbarFolder, SMART_BOOKMARKS_ON_TOOLBAR + 1);
|
||||
do_check_true(itemId > 0);
|
||||
|
||||
do_test_finished();
|
||||
|
@ -275,6 +275,18 @@ PrivateBrowsingService.prototype = {
|
||||
getService(Ci.nsIHttpAuthManager);
|
||||
authMgr.clearAll();
|
||||
|
||||
// Prevent any SSL sockets from remaining open. Without this, SSL
|
||||
// websites may fail to load after switching the private browsing mode
|
||||
// because the SSL sockets may still be open while the corresponding
|
||||
// NSS resources have been destroyed by the logoutAndTeardown call
|
||||
// above. See bug 463256 for more information.
|
||||
let ios = Cc["@mozilla.org/network/io-service;1"].
|
||||
getService(Ci.nsIIOService);
|
||||
if (!ios.offline) {
|
||||
ios.offline = true;
|
||||
ios.offline = false;
|
||||
}
|
||||
|
||||
if (!this._inPrivateBrowsing) {
|
||||
// Clear the error console
|
||||
let consoleService = Cc["@mozilla.org/consoleservice;1"].
|
||||
|
@ -57,7 +57,10 @@ _BROWSER_TEST_FILES = \
|
||||
browser_privatebrowsing_windowtitle.js \
|
||||
browser_privatebrowsing_windowtitle_page.html \
|
||||
browser_privatebrowsing_urlbarfocus.js \
|
||||
browser_privatebrowsing_forgetthissite.js \
|
||||
$(NULL)
|
||||
# Test for bug 463256 disabled until we figure why it fails intermittently (bug 486640)
|
||||
# browser_privatebrowsing_sslsite_transition.js \
|
||||
|
||||
libs:: $(_BROWSER_TEST_FILES)
|
||||
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
|
||||
|
@ -0,0 +1,129 @@
|
||||
/* ***** 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 Private Browsing Tests.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Ehsan Akhgari.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ehsan Akhgari <ehsan.akhgari@gmail.com> (Original Author)
|
||||
*
|
||||
* 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 ***** */
|
||||
|
||||
// This test makes sure that the Forget This Site command is hidden in private
|
||||
// browsing mode.
|
||||
|
||||
function test() {
|
||||
// initialization
|
||||
let pb = Cc["@mozilla.org/privatebrowsing;1"].
|
||||
getService(Ci.nsIPrivateBrowsingService);
|
||||
let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
|
||||
getService(Ci.nsIWindowWatcher);
|
||||
waitForExplicitFinish();
|
||||
|
||||
// Add a history entry.
|
||||
const TEST_URI = "http://www.mozilla.org/privatebrowsing";
|
||||
ok(PlacesUtils, "checking PlacesUtils, running in chrome context?");
|
||||
let history = PlacesUtils.history;
|
||||
let visitId = history.addVisit(PlacesUtils._uri(TEST_URI), Date.now() * 1000,
|
||||
null, PlacesUtils.history.TRANSITION_TYPED, false, 0);
|
||||
ok(visitId > 0, TEST_URI + " successfully marked visited");
|
||||
|
||||
function testForgetThisSiteVisibility(expected, funcNext) {
|
||||
let observer = {
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
if (aTopic === "domwindowopened") {
|
||||
ww.unregisterNotification(this);
|
||||
let organizer = aSubject.QueryInterface(Ci.nsIDOMWindow);
|
||||
organizer.addEventListener("load", function onLoad(event) {
|
||||
organizer.removeEventListener("load", onLoad, false);
|
||||
executeSoon(function () {
|
||||
// Select History in the left pane.
|
||||
let PO = organizer.PlacesOrganizer;
|
||||
PO.selectLeftPaneQuery('History');
|
||||
let histContainer = PO._places.selectedNode.QueryInterface(Ci.nsINavHistoryContainerResultNode);
|
||||
histContainer.containerOpen = true;
|
||||
PO._places.selectNode(histContainer.getChild(0));
|
||||
// Select the first history entry.
|
||||
let doc = organizer.document;
|
||||
let tree = PO._content;
|
||||
let selection = tree.view.selection;
|
||||
selection.clearSelection();
|
||||
selection.rangedSelect(0, 0, true);
|
||||
is(tree.selectedNode.uri, TEST_URI, "The correct history item has been selected");
|
||||
// Open the context menu
|
||||
let contextmenu = doc.getElementById("placesContext");
|
||||
contextmenu.addEventListener("popupshown", function() {
|
||||
contextmenu.removeEventListener("popupshown", arguments.callee, false);
|
||||
let forgetThisSite = doc.getElementById("placesContext_deleteHost");
|
||||
is(forgetThisSite.hidden, !expected,
|
||||
"The Forget This Site menu item should " + (expected ? "not " : "") + "be hidden");
|
||||
let forgetThisSiteCmd = doc.getElementById("placesCmd_deleteDataHost");
|
||||
if (forgetThisSiteCmd.disabled, !expected,
|
||||
"The Forget This Site command should " + (expected ? "not " : "") + "be disabled");
|
||||
// Close the context menu
|
||||
contextmenu.hidePopup();
|
||||
// Close Library window.
|
||||
organizer.close();
|
||||
// Proceed
|
||||
funcNext();
|
||||
}, false);
|
||||
let event = document.createEvent("MouseEvents");
|
||||
event.initMouseEvent("contextmenu", true, true, organizer, 0,
|
||||
0, 0, 0, 0, false, false, false, false,
|
||||
0, null);
|
||||
tree.dispatchEvent(event);
|
||||
});
|
||||
}, false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ww.registerNotification(observer);
|
||||
ww.openWindow(null,
|
||||
"chrome://browser/content/places/places.xul",
|
||||
"",
|
||||
"chrome,toolbar=yes,dialog=no,resizable",
|
||||
null);
|
||||
}
|
||||
|
||||
testForgetThisSiteVisibility(true, function() {
|
||||
// Enter private browsing mode
|
||||
pb.privateBrowsingEnabled = true;
|
||||
testForgetThisSiteVisibility(false, function() {
|
||||
// Leave private browsing mode
|
||||
pb.privateBrowsingEnabled = false;
|
||||
testForgetThisSiteVisibility(true, function() {
|
||||
// Cleanup
|
||||
history.QueryInterface(Ci.nsIBrowserHistory)
|
||||
.removeAllPages();
|
||||
finish();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
/* ***** 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 Private Browsing Tests.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Ehsan Akhgari.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ehsan Akhgari <ehsan.akhgari@gmail.com> (Original Author)
|
||||
*
|
||||
* 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 ***** */
|
||||
|
||||
// This test makes sure that SSL sites load correctly after leaving the
|
||||
// Private Browsing mode (bug 463256).
|
||||
|
||||
// This test is disabled until we figure why it fails intermittently (bug 486640).
|
||||
|
||||
function test() {
|
||||
// initialization
|
||||
let prefBranch = Cc["@mozilla.org/preferences-service;1"].
|
||||
getService(Ci.nsIPrefBranch);
|
||||
prefBranch.setBoolPref("browser.privatebrowsing.keep_current_session", true);
|
||||
let pb = Cc["@mozilla.org/privatebrowsing;1"].
|
||||
getService(Ci.nsIPrivateBrowsingService);
|
||||
|
||||
const kTestURL = "https://example.com/";
|
||||
|
||||
// load an SSL site in the first tab and wait for it to finish loading
|
||||
let tab = gBrowser.addTab();
|
||||
gBrowser.selectedTab = tab;
|
||||
let browser = gBrowser.getBrowserForTab(tab);
|
||||
browser.addEventListener("load", function() {
|
||||
browser.removeEventListener("load", arguments.callee, true);
|
||||
|
||||
pb.privateBrowsingEnabled = true;
|
||||
pb.privateBrowsingEnabled = false;
|
||||
|
||||
// Note: if the page fails to load, the test will time out
|
||||
browser.addEventListener("load", function() {
|
||||
browser.removeEventListener("load", arguments.callee, true);
|
||||
|
||||
is(browser.contentWindow.location, kTestURL,
|
||||
"The original SSL page should be loaded at this stage");
|
||||
|
||||
gBrowser.removeTab(tab);
|
||||
prefBranch.clearUserPref("browser.privatebrowsing.keep_current_session");
|
||||
finish();
|
||||
}, true);
|
||||
|
||||
executeSoon(function(){
|
||||
browser.contentWindow.location = kTestURL;
|
||||
});
|
||||
}, true);
|
||||
browser.contentWindow.location = kTestURL;
|
||||
|
@ -0,0 +1,79 @@
|
||||
/* ***** 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 Private Browsing Tests.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Ehsan Akhgari.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ehsan Akhgari <ehsan.akhgari@gmail.com> (Original Author)
|
||||
*
|
||||
* 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 ***** */
|
||||
|
||||
// This tests the private browsing service to make sure it switches the offline
|
||||
// status as expected (see bug 463256).
|
||||
|
||||
function run_test_on_service() {
|
||||
// initialization
|
||||
var pb = Cc[PRIVATEBROWSING_CONTRACT_ID].
|
||||
getService(Ci.nsIPrivateBrowsingService);
|
||||
var os = Cc["@mozilla.org/observer-service;1"].
|
||||
getService(Ci.nsIObserverService);
|
||||
var prefBranch = Cc["@mozilla.org/preferences-service;1"].
|
||||
getService(Ci.nsIPrefBranch);
|
||||
prefBranch.setBoolPref("browser.privatebrowsing.keep_current_session", true);
|
||||
|
||||
var observer = {
|
||||
observe: function (aSubject, aTopic, aData) {
|
||||
if (aTopic == "network:offline-status-changed")
|
||||
this.events.push(aData);
|
||||
},
|
||||
events: []
|
||||
};
|
||||
os.addObserver(observer, "network:offline-status-changed", false);
|
||||
|
||||
// enter the private browsing mode, and wait for the about:pb page to load
|
||||
pb.privateBrowsingEnabled = true;
|
||||
do_check_eq(observer.events.length, 2);
|
||||
do_check_eq(observer.events[0], "offline");
|
||||
do_check_eq(observer.events[1], "online");
|
||||
|
||||
// leave the private browsing mode, and wait for the SSL page to load again
|
||||
pb.privateBrowsingEnabled = false;
|
||||
do_check_eq(observer.events.length, 4);
|
||||
do_check_eq(observer.events[2], "offline");
|
||||
do_check_eq(observer.events[3], "online");
|
||||
|
||||
os.removeObserver(observer, "network:offline-status-changed", false);
|
||||
prefBranch.clearUserPref("browser.privatebrowsing.keep_current_session");
|
||||
}
|
||||
|
||||
// Support running tests on both the service itself and its wrapper
|
||||
function run_test() {
|
||||
run_test_on_all_services();
|
||||
}
|
@ -20,6 +20,7 @@
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dietrich Ayala <dietrich@mozilla.com>
|
||||
* Michael Kraft <morac99-firefox@yahoo.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
|
||||
@ -58,7 +59,7 @@ interface nsIDOMNode;
|
||||
* |getBrowser().tabContainer| such as e.g. |getBrowser().selectedTab|.
|
||||
*/
|
||||
|
||||
[scriptable, uuid(91f6d650-898d-11dd-ad8b-0800200c9a66)]
|
||||
[scriptable, uuid(534d81e3-d3fb-4f1e-aed6-3de601406270)]
|
||||
interface nsISessionStore : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -138,6 +139,12 @@ interface nsISessionStore : nsISupports
|
||||
*/
|
||||
nsIDOMNode undoCloseTab(in nsIDOMWindow aWindow, in unsigned long aIndex);
|
||||
|
||||
/**
|
||||
* @param aWindow is the browser window associated with the closed tab.
|
||||
* @param aIndex is the index of the closed tab to be removed (FIFO ordered).
|
||||
*/
|
||||
nsIDOMNode forgetClosedTab(in nsIDOMWindow aWindow, in unsigned long aIndex);
|
||||
|
||||
/**
|
||||
* @param aWindow is the window to get the value for.
|
||||
* @param aKey is the value's name.
|
||||
|
@ -21,6 +21,7 @@
|
||||
* Contributor(s):
|
||||
* Dietrich Ayala <dietrich@mozilla.com>
|
||||
* Ehsan Akhgari <ehsan.akhgari@gmail.com>
|
||||
* Michael Kraft <morac99-firefox@yahoo.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
|
||||
@ -161,6 +162,9 @@ SessionStoreService.prototype = {
|
||||
// whether we are in private browsing mode
|
||||
_inPrivateBrowsing: false,
|
||||
|
||||
// whether we clearing history on shutdown
|
||||
_clearingOnShutdown: false,
|
||||
|
||||
/* ........ Global Event Handlers .............. */
|
||||
|
||||
/**
|
||||
@ -352,6 +356,8 @@ SessionStoreService.prototype = {
|
||||
// Delete the private browsing backed up state, if any
|
||||
if ("_stateBackup" in this)
|
||||
delete this._stateBackup;
|
||||
if (this._loadState == STATE_QUITTING)
|
||||
this._clearingOnShutdown = true;
|
||||
break;
|
||||
case "browser:purge-domain-data":
|
||||
// does a session history entry contain a url for the given domain?
|
||||
@ -909,6 +915,21 @@ SessionStoreService.prototype = {
|
||||
return tab;
|
||||
},
|
||||
|
||||
forgetClosedTab: function sss_forgetClosedTab(aWindow, aIndex) {
|
||||
if (!aWindow.__SSi)
|
||||
throw (Components.returnCode = Cr.NS_ERROR_INVALID_ARG);
|
||||
|
||||
var closedTabs = this._windows[aWindow.__SSi]._closedTabs;
|
||||
|
||||
// default to the most-recently closed tab
|
||||
aIndex = aIndex || 0;
|
||||
if (!(aIndex in closedTabs))
|
||||
throw (Components.returnCode = Cr.NS_ERROR_INVALID_ARG);
|
||||
|
||||
// remove closed tab from the array
|
||||
closedTabs.splice(aIndex, 1);
|
||||
},
|
||||
|
||||
getWindowValue: function sss_getWindowValue(aWindow, aKey) {
|
||||
if (aWindow.__SSi) {
|
||||
var data = this._windows[aWindow.__SSi].extData || {};
|
||||
@ -2427,8 +2448,11 @@ SessionStoreService.prototype = {
|
||||
* @returns bool
|
||||
*/
|
||||
_doResumeSession: function sss_doResumeSession() {
|
||||
if (this._clearingOnShutdown)
|
||||
return false;
|
||||
|
||||
return this._prefBranch.getIntPref("startup.page") == 3 ||
|
||||
this._prefBranch.getBoolPref("sessionstore.resume_session_once");
|
||||
this._prefBranch.getBoolPref("sessionstore.resume_session_once");
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -20,6 +20,7 @@
|
||||
#
|
||||
# Contributor(s):
|
||||
# Simon Bünzli <zeniko@gmail.com>
|
||||
# Michael Kraft <morac99-firefox@yahoo.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"),
|
||||
@ -68,6 +69,7 @@ _BROWSER_TEST_FILES = \
|
||||
browser_454908_sample.html \
|
||||
browser_456342.js \
|
||||
browser_456342_sample.xhtml \
|
||||
browser_461634.js \
|
||||
browser_463206.js \
|
||||
browser_463206_sample.html \
|
||||
browser_464199.js \
|
||||
|
108
browser/components/sessionstore/test/browser/browser_461634.js
Normal file
@ -0,0 +1,108 @@
|
||||
/* ***** 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 sessionstore test code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Simon Bünzli <zeniko@gmail.com>.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Michael Kraft <morac99-firefox@yahoo.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 ***** */
|
||||
|
||||
function test() {
|
||||
/** Test for Bug 461634 **/
|
||||
|
||||
// test setup
|
||||
let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
|
||||
waitForExplicitFinish();
|
||||
|
||||
const REMEMBER = Date.now(), FORGET = Math.random();
|
||||
let test_state = { windows: [{ "tabs": [{ "entries": [] }], _closedTabs: [
|
||||
{ state: { entries: [{ url: "http://www.example.net/" }] }, title: FORGET },
|
||||
{ state: { entries: [{ url: "http://www.example.net/" }] }, title: REMEMBER },
|
||||
{ state: { entries: [{ url: "http://www.example.net/" }] }, title: FORGET },
|
||||
{ state: { entries: [{ url: "http://www.example.net/" }] }, title: REMEMBER },
|
||||
] }] };
|
||||
let remember_count = 2;
|
||||
|
||||
function countByTitle(aClosedTabList, aTitle)
|
||||
aClosedTabList.filter(function(aData) aData.title == aTitle).length;
|
||||
|
||||
function testForError(aFunction) {
|
||||
try {
|
||||
aFunction();
|
||||
return false;
|
||||
}
|
||||
catch (ex) {
|
||||
return ex.name == "NS_ERROR_ILLEGAL_VALUE";
|
||||
}
|
||||
}
|
||||
|
||||
// open a window and add the above closed tab list
|
||||
let newWin = openDialog(location, "_blank", "chrome,all,dialog=no");
|
||||
newWin.addEventListener("load", function(aEvent) {
|
||||
gPrefService.setIntPref("browser.sessionstore.max_tabs_undo",
|
||||
test_state.windows[0]._closedTabs.length);
|
||||
ss.setWindowState(newWin, JSON.stringify(test_state), true);
|
||||
|
||||
let closedTabs = eval("(" + ss.getClosedTabData(newWin) + ")");
|
||||
is(closedTabs.length, test_state.windows[0]._closedTabs.length,
|
||||
"Closed tab list has the expected length");
|
||||
is(countByTitle(closedTabs, FORGET),
|
||||
test_state.windows[0]._closedTabs.length - remember_count,
|
||||
"The correct amout of tabs are to be forgotten");
|
||||
is(countByTitle(closedTabs, REMEMBER), remember_count,
|
||||
"Everything is set up.");
|
||||
|
||||
// all of the following calls with illegal arguments should throw NS_ERROR_ILLEGAL_VALUE
|
||||
ok(testForError(function() ss.forgetClosedTab({}, 0)),
|
||||
"Invalid window for forgetClosedTab throws");
|
||||
ok(testForError(function() ss.forgetClosedTab(newWin, -1)),
|
||||
"Invalid tab for forgetClosedTab throws");
|
||||
ok(testForError(function() ss.forgetClosedTab(newWin, test_state.windows[0]._closedTabs.length + 1)),
|
||||
"Invalid tab for forgetClosedTab throws");
|
||||
|
||||
// Remove third tab, then first tab
|
||||
ss.forgetClosedTab(newWin, 2);
|
||||
ss.forgetClosedTab(newWin, null);
|
||||
|
||||
closedTabs = eval("(" + ss.getClosedTabData(newWin) + ")");
|
||||
is(closedTabs.length, remember_count,
|
||||
"The correct amout of tabs was removed");
|
||||
is(countByTitle(closedTabs, FORGET), 0,
|
||||
"All tabs specifically forgotten were indeed removed");
|
||||
is(countByTitle(closedTabs, REMEMBER), remember_count,
|
||||
"... and tabs not specifically forgetten weren't.");
|
||||
|
||||
// clean up
|
||||
newWin.close();
|
||||
gPrefService.clearUserPref("browser.sessionstore.max_tabs_undo");
|
||||
finish();
|
||||
}, false);
|
||||
}
|
@ -61,39 +61,16 @@
|
||||
#define NETWORK_PREFPANE NS_LITERAL_CSTRING("/System/Library/PreferencePanes/Network.prefPane")
|
||||
#define DESKTOP_PREFPANE NS_LITERAL_CSTRING("/System/Library/PreferencePanes/DesktopScreenEffectsPref.prefPane")
|
||||
|
||||
#define SAFARI_BUNDLE_IDENTIFIER NS_LITERAL_CSTRING("com.apple.Safari")
|
||||
|
||||
// These Launch Services functions are undocumented. We're using them since they're
|
||||
// the only way to set the default opener for URLs / file extensions.
|
||||
extern "C" {
|
||||
// Returns the CFURL for application currently set as the default opener for the
|
||||
// given URL scheme. appURL must be released by the caller.
|
||||
extern OSStatus _LSCopyDefaultSchemeHandlerURL(CFStringRef scheme, CFURLRef *appURL);
|
||||
extern OSStatus _LSSetDefaultSchemeHandlerURL(CFStringRef scheme, CFURLRef appURL);
|
||||
extern OSStatus _LSSaveAndRefresh(void);
|
||||
// Callers should pass 0 as both inType and inCreator in order to set the default opener
|
||||
// without modifing those.
|
||||
extern OSStatus _LSSetWeakBindingForType(OSType inType,
|
||||
OSType inCreator,
|
||||
CFStringRef inExtension,
|
||||
LSRolesMask inRoleMask,
|
||||
const FSRef* inBindingRef);
|
||||
}
|
||||
#define SAFARI_BUNDLE_IDENTIFIER "com.apple.Safari"
|
||||
|
||||
NS_IMPL_ISUPPORTS3(nsMacShellService, nsIMacShellService, nsIShellService, nsIWebProgressListener)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMacShellService::IsDefaultBrowser(PRBool aStartupCheck, PRBool* aIsDefaultBrowser)
|
||||
{
|
||||
*aIsDefaultBrowser = PR_TRUE;
|
||||
*aIsDefaultBrowser = PR_FALSE;
|
||||
|
||||
// Since neither Launch Services nor Internet Config actually differ between
|
||||
// bundles which have the same bundle identifier (That is, if we set our
|
||||
// bundle's URL as the default handler, Launch Service might return the
|
||||
// URL of another firefox bundle as the defualt http handler), we are
|
||||
// comparing the bundles' identifiers rather than their URLs.
|
||||
|
||||
CFStringRef firefoxID = ::CFBundleGetIdentifier(CFBundleGetMainBundle());
|
||||
CFStringRef firefoxID = ::CFBundleGetIdentifier(::CFBundleGetMainBundle());
|
||||
if (!firefoxID) {
|
||||
// CFBundleGetIdentifier is expected to return NULL only if the specified
|
||||
// bundle doesn't have a bundle identifier in its plist. In this case, that
|
||||
@ -101,50 +78,20 @@ nsMacShellService::IsDefaultBrowser(PRBool aStartupCheck, PRBool* aIsDefaultBrow
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
::CFRetain(firefoxID);
|
||||
|
||||
// Get the default http handler URL
|
||||
CFURLRef defaultBrowserURL;
|
||||
OSStatus err = ::_LSCopyDefaultSchemeHandlerURL(CFSTR("http"),
|
||||
&defaultBrowserURL);
|
||||
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
if (err == noErr) {
|
||||
// Get a reference to the bundle (based on its URL)
|
||||
CFBundleRef defaultBrowserBundle = ::CFBundleCreate(NULL,
|
||||
defaultBrowserURL);
|
||||
if (defaultBrowserBundle) {
|
||||
CFStringRef defaultBrowserID = ::CFBundleGetIdentifier(defaultBrowserBundle);
|
||||
if (defaultBrowserID) {
|
||||
::CFRetain(defaultBrowserID);
|
||||
// and compare it to our bundle identifier
|
||||
*aIsDefaultBrowser = ::CFStringCompare(firefoxID, defaultBrowserID, 0)
|
||||
== kCFCompareEqualTo;
|
||||
::CFRelease(defaultBrowserID);
|
||||
}
|
||||
else {
|
||||
// If the default browser bundle doesn't have an identifier in its plist,
|
||||
// it's not our bundle
|
||||
*aIsDefaultBrowser = PR_FALSE;
|
||||
}
|
||||
|
||||
::CFRelease(defaultBrowserBundle);
|
||||
rv = NS_OK;
|
||||
}
|
||||
|
||||
::CFRelease(defaultBrowserURL);
|
||||
// Get the default http handler's bundle ID (or NULL if it has not been explicitly set)
|
||||
CFStringRef defaultBrowserID = ::LSCopyDefaultHandlerForURLScheme(CFSTR("http"));
|
||||
if (defaultBrowserID) {
|
||||
*aIsDefaultBrowser = ::CFStringCompare(firefoxID, defaultBrowserID, 0) == kCFCompareEqualTo;
|
||||
::CFRelease(defaultBrowserID);
|
||||
}
|
||||
|
||||
// release the idetifiers strings
|
||||
::CFRelease(firefoxID);
|
||||
|
||||
// If this is the first browser window, maintain internal state that we've
|
||||
// checked this session (so that subsequent window opens don't show the
|
||||
// default browser dialog).
|
||||
if (aStartupCheck)
|
||||
mCheckedThisSession = PR_TRUE;
|
||||
|
||||
return rv;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -152,25 +99,27 @@ nsMacShellService::SetDefaultBrowser(PRBool aClaimAllTypes, PRBool aForAllUsers)
|
||||
{
|
||||
// Note: We don't support aForAllUsers on Mac OS X.
|
||||
|
||||
CFURLRef firefoxURL = ::CFBundleCopyBundleURL(CFBundleGetMainBundle());
|
||||
CFStringRef firefoxID = ::CFBundleGetIdentifier(::CFBundleGetMainBundle());
|
||||
if (!firefoxID) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
::_LSSetDefaultSchemeHandlerURL(CFSTR("http"), firefoxURL);
|
||||
::_LSSetDefaultSchemeHandlerURL(CFSTR("https"), firefoxURL);
|
||||
if (::LSSetDefaultHandlerForURLScheme(CFSTR("http"), firefoxID) != noErr) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
if (::LSSetDefaultHandlerForURLScheme(CFSTR("https"), firefoxID) != noErr) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (aClaimAllTypes) {
|
||||
::_LSSetDefaultSchemeHandlerURL(CFSTR("ftp"), firefoxURL);
|
||||
|
||||
FSRef firefoxFSRef;
|
||||
// CFURLGetFSRef returns true if the conversion was successful
|
||||
if (::CFURLGetFSRef(firefoxURL, &firefoxFSRef)) {
|
||||
// Set the default opener for html/htm files
|
||||
::_LSSetWeakBindingForType(0, 0, CFSTR("html"), kLSRolesAll, &firefoxFSRef);
|
||||
::_LSSetWeakBindingForType(0, 0, CFSTR("htm"), kLSRolesAll, &firefoxFSRef);
|
||||
if (::LSSetDefaultHandlerForURLScheme(CFSTR("ftp"), firefoxID) != noErr) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
if (::LSSetDefaultRoleHandlerForContentType(kUTTypeHTML, kLSRolesAll, firefoxID) != noErr) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
::_LSSaveAndRefresh();
|
||||
|
||||
::CFRelease(firefoxURL);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -505,30 +454,35 @@ nsMacShellService::GetDefaultFeedReader(nsILocalFile** _retval)
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
*_retval = nsnull;
|
||||
|
||||
CFURLRef defaultHandlerURL;
|
||||
OSStatus err = ::_LSCopyDefaultSchemeHandlerURL(CFSTR("feed"),
|
||||
&defaultHandlerURL);
|
||||
if (defaultHandlerURL) {
|
||||
CFStringRef defaultHandlerID = ::LSCopyDefaultHandlerForURLScheme(CFSTR("feed"));
|
||||
if (!defaultHandlerID) {
|
||||
defaultHandlerID = ::CFStringCreateWithCString(kCFAllocatorDefault,
|
||||
SAFARI_BUNDLE_IDENTIFIER,
|
||||
kCFStringEncodingASCII);
|
||||
}
|
||||
|
||||
CFURLRef defaultHandlerURL = NULL;
|
||||
OSStatus status = ::LSFindApplicationForInfo(kLSUnknownCreator,
|
||||
defaultHandlerID,
|
||||
NULL, // inName
|
||||
NULL, // outAppRef
|
||||
&defaultHandlerURL);
|
||||
|
||||
if (status == noErr && defaultHandlerURL) {
|
||||
nsCOMPtr<nsILocalFileMac> defaultReader =
|
||||
do_CreateInstance("@mozilla.org/file/local;1", &rv);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = defaultReader->InitWithCFURL(defaultHandlerURL);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// ASSERT("Safari Is Not a Feed Reader");
|
||||
nsCAutoString bundleIdentifier;
|
||||
|
||||
// don't throw if the bundle has no identifier
|
||||
rv = NS_ERROR_FAILURE;
|
||||
if (NS_FAILED(defaultReader->GetBundleIdentifier(bundleIdentifier)) ||
|
||||
!bundleIdentifier.Equals(SAFARI_BUNDLE_IDENTIFIER)) {
|
||||
NS_ADDREF(*_retval = defaultReader);
|
||||
rv = NS_OK;
|
||||
}
|
||||
NS_ADDREF(*_retval = defaultReader);
|
||||
rv = NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
::CFRelease(defaultHandlerURL);
|
||||
}
|
||||
|
||||
::CFRelease(defaultHandlerID);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
@ -44,11 +44,12 @@ relativesrcdir = browser/fuel/test
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
# browser_Browser.js is disabled, because it times out occasionally. See bug 458688.
|
||||
|
||||
_BROWSER_FILES =browser_Application.js \
|
||||
browser_ApplicationPrefs.js \
|
||||
browser_ApplicationStorage.js \
|
||||
browser_ApplicationQuitting.js \
|
||||
browser_Browser.js \
|
||||
browser_Bookmarks.js \
|
||||
browser_Extensions.js \
|
||||
ContentA.html \
|
||||
|
@ -110,6 +110,11 @@ endif
|
||||
|
||||
include $(topsrcdir)/toolkit/mozapps/installer/packager.mk
|
||||
|
||||
libs::
|
||||
$(MAKE) -C $(DEPTH)/browser/locales langpack PKG_LANGPACK_PATH=
|
||||
|
||||
UPLOAD_EXTRA_FILES += $(PKG_LANGPACK_BASENAME).xpi
|
||||
|
||||
installer:: removed-files
|
||||
ifdef INSTALLER_DIR
|
||||
$(MAKE) -C $(INSTALLER_DIR)
|
||||
|
@ -334,6 +334,8 @@ langpack-%: libs-%
|
||||
cd $(DIST)/xpi-stage/locale-$(AB_CD) && \
|
||||
$(ZIP) -r9D $(LANGPACK_FILE) install.rdf chrome chrome.manifest -x chrome/$(AB_CD).manifest
|
||||
|
||||
langpack: langpack-$(AB_CD)
|
||||
|
||||
# This is a generic target that will make a langpack, repack ZIP (+tarball)
|
||||
# builds, and repack an installer if applicable. It is called from the
|
||||
# tinderbox scripts. Alter it with caution.
|
||||
|
@ -21,7 +21,7 @@ keyword.URL=http://www.google.com/search?ie=UTF-8&oe=UTF-8&sourceid=navclient&gf
|
||||
# TRANSLATION NOTE: {moz:domain} and {searchTerms} are placeholders for the site
|
||||
# to be searched and the user's search query. Place them in the appropriate location
|
||||
# for your locale's URL but do not translate them.
|
||||
browser.search.siteSearchURL=http://www.google.com/search?hl=en&q=site%3A{moz:domain}+{searchTerms}
|
||||
browser.search.siteSearchURL=http://www.google.com/search?ie=UTF-8&oe=UTF-8&sourceid=navclient&q=site%3A{moz:domain}+{searchTerms}
|
||||
|
||||
# increment this number when anything gets changed in the list below. This will
|
||||
# cause Firefox to re-read these prefs and inject any new handlers into the
|
||||
|
@ -197,11 +197,9 @@
|
||||
<!ENTITY maintenance.accesskey "I">
|
||||
|
||||
<!ENTITY backCmd.label "Back">
|
||||
<!ENTITY backCmd.accesskey "B">
|
||||
<!ENTITY backButton.tooltip "Go back">
|
||||
|
||||
<!ENTITY forwardCmd.label "Forward">
|
||||
<!ENTITY forwardCmd.accesskey "F">
|
||||
<!ENTITY forwardButton.tooltip "Go forward">
|
||||
|
||||
<!ENTITY detailsPane.more.label "More">
|
||||
|
Before Width: | Height: | Size: 757 B |
Before Width: | Height: | Size: 862 B |
@ -1025,7 +1025,7 @@ toolbar[iconsize="small"] #paste-button[disabled="true"] {
|
||||
|
||||
.ac-result-type-keyword,
|
||||
.autocomplete-treebody::-moz-tree-image(keyword, treecolAutoCompleteImage) {
|
||||
list-style-image: url(chrome://browser/skin/Search-glass.png);
|
||||
list-style-image: url(chrome://global/skin/icons/Search-glass.png);
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
@ -18,8 +18,6 @@ classic.jar:
|
||||
skin/classic/browser/Privacy-16.png
|
||||
skin/classic/browser/Privacy-48.png
|
||||
skin/classic/browser/searchbar.css (searchbar.css)
|
||||
skin/classic/browser/Search-glass.png
|
||||
skin/classic/browser/Search-glass-rtl.png
|
||||
skin/classic/browser/section_collapsed.png
|
||||
skin/classic/browser/section_expanded.png
|
||||
skin/classic/browser/Secure.png
|
||||
|
@ -69,12 +69,12 @@
|
||||
|
||||
.search-go-button {
|
||||
padding: 1px;
|
||||
list-style-image: url("chrome://browser/skin/Search-glass.png");
|
||||
list-style-image: url("chrome://global/skin/icons/Search-glass.png");
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.search-go-button[chromedir="rtl"] {
|
||||
list-style-image: url("chrome://browser/skin/Search-glass-rtl.png");
|
||||
-moz-transform: scaleX(-1);
|
||||
}
|
||||
|
||||
menuitem[cmd="cmd_clearhistory"] {
|
||||
|
@ -810,6 +810,10 @@ toolbar[iconsize="small"] #unified-back-forward-button > #back-forward-dropmarke
|
||||
background: url("chrome://browser/skin/urlbar/endcap-focused.png") transparent right center no-repeat;
|
||||
}
|
||||
|
||||
#urlbar[focused="true"]:-moz-system-metric(mac-graphite-theme) {
|
||||
background-image: url("chrome://browser/skin/urlbar/endcap-focused-graphite.png");
|
||||
}
|
||||
|
||||
#urlbar .textbox-input-box,
|
||||
#urlbar-icons {
|
||||
margin: 0;
|
||||
@ -821,6 +825,11 @@ toolbar[iconsize="small"] #unified-back-forward-button > #back-forward-dropmarke
|
||||
background-image: url("chrome://browser/skin/urlbar/textfield-mid-focused.png");
|
||||
}
|
||||
|
||||
#urlbar[focused="true"] .textbox-input-box:-moz-system-metric(mac-graphite-theme),
|
||||
#urlbar[focused="true"] #urlbar-icons:-moz-system-metric(mac-graphite-theme) {
|
||||
background-image: url("chrome://browser/skin/urlbar/textfield-mid-focused-graphite.png");
|
||||
}
|
||||
|
||||
#urlbar .textbox-input-box {
|
||||
padding-top: 1px;
|
||||
}
|
||||
@ -1868,6 +1877,10 @@ tabpanels.plain {
|
||||
background-image: url("chrome://browser/skin/urlbar/startcap-focused.png");
|
||||
}
|
||||
|
||||
#urlbar[focused="true"] > #identity-box:-moz-system-metric(mac-graphite-theme) {
|
||||
background-image: url("chrome://browser/skin/urlbar/startcap-focused-graphite.png");
|
||||
}
|
||||
|
||||
#identity-box:focus > hbox > #page-proxy-deck {
|
||||
outline: 2px solid #4F8EC9;
|
||||
-moz-outline-radius: 2px;
|
||||
@ -1938,6 +1951,18 @@ tabpanels.plain {
|
||||
background-image: url("chrome://browser/skin/urlbar/startcap-secure-end-focused.png");
|
||||
}
|
||||
|
||||
#urlbar[focused="true"] > #identity-box.verifiedDomain:-moz-system-metric(mac-graphite-theme) {
|
||||
background-image: url("chrome://browser/skin/urlbar/startcap-secure-start-focused-graphite.png");
|
||||
}
|
||||
|
||||
#urlbar[focused="true"] > #identity-box.verifiedDomain > hbox:-moz-system-metric(mac-graphite-theme) {
|
||||
background-image: url("chrome://browser/skin/urlbar/startcap-secure-mid-focused-graphite.png");
|
||||
}
|
||||
|
||||
#urlbar[focused="true"] > #identity-box.verifiedDomain > hbox > #identity-icon-label:-moz-system-metric(mac-graphite-theme) {
|
||||
background-image: url("chrome://browser/skin/urlbar/startcap-secure-end-focused-graphite.png");
|
||||
}
|
||||
|
||||
#identity-box.verifiedDomain > hbox > #identity-icon-label[value=""] {
|
||||
-moz-padding-start: 3px !important;
|
||||
-moz-padding-end: 8px !important;
|
||||
@ -1990,6 +2015,18 @@ tabpanels.plain {
|
||||
background-image: url("chrome://browser/skin/urlbar/startcap-verified-end-focused.png");
|
||||
}
|
||||
|
||||
#urlbar[focused="true"] > #identity-box.verifiedIdentity:-moz-system-metric(mac-graphite-theme) {
|
||||
background-image: url("chrome://browser/skin/urlbar/startcap-verified-start-focused-graphite.png");
|
||||
}
|
||||
|
||||
#urlbar[focused="true"] > #identity-box.verifiedIdentity > hbox:-moz-system-metric(mac-graphite-theme) {
|
||||
background-image: url("chrome://browser/skin/urlbar/startcap-verified-mid-focused-graphite.png");
|
||||
}
|
||||
|
||||
#urlbar[focused="true"] > #identity-box.verifiedIdentity > hbox > #identity-icon-label:-moz-system-metric(mac-graphite-theme) {
|
||||
background-image: url("chrome://browser/skin/urlbar/startcap-verified-end-focused-graphite.png");
|
||||
}
|
||||
|
||||
/* Favicon Glow */
|
||||
#identity-box.verifiedIdentity > hbox > #page-proxy-stack,
|
||||
#identity-box.verifiedDomain > hbox > #page-proxy-stack {
|
||||
|
@ -132,10 +132,14 @@ classic.jar:
|
||||
skin/classic/browser/urlbar/endcap.png (urlbar/endcap.png)
|
||||
skin/classic/browser/urlbar/endcap-rtl.png (urlbar/endcap-rtl.png)
|
||||
skin/classic/browser/urlbar/endcap-focused.png (urlbar/endcap-focused.png)
|
||||
skin/classic/browser/urlbar/endcap-focused-graphite.png (urlbar/endcap-focused-graphite.png)
|
||||
skin/classic/browser/urlbar/endcap-focused-graphite-rtl.png (urlbar/endcap-focused-graphite-rtl.png)
|
||||
skin/classic/browser/urlbar/endcap-focused-rtl.png (urlbar/endcap-focused-rtl.png)
|
||||
skin/classic/browser/urlbar/startcap.png (urlbar/startcap.png)
|
||||
skin/classic/browser/urlbar/startcap-rtl.png (urlbar/startcap-rtl.png)
|
||||
skin/classic/browser/urlbar/startcap-focused.png (urlbar/startcap-focused.png)
|
||||
skin/classic/browser/urlbar/startcap-focused-graphite.png (urlbar/startcap-focused-graphite.png)
|
||||
skin/classic/browser/urlbar/startcap-focused-graphite-rtl.png (urlbar/startcap-focused-graphite-rtl.png)
|
||||
skin/classic/browser/urlbar/startcap-focused-rtl.png (urlbar/startcap-focused-rtl.png)
|
||||
skin/classic/browser/urlbar/startcap-secure-start.png (urlbar/startcap-secure-start.png)
|
||||
skin/classic/browser/urlbar/startcap-secure-mid.png (urlbar/startcap-secure-mid.png)
|
||||
@ -144,8 +148,11 @@ classic.jar:
|
||||
skin/classic/browser/urlbar/startcap-secure-mid-active.png (urlbar/startcap-secure-mid-active.png)
|
||||
skin/classic/browser/urlbar/startcap-secure-end-active.png (urlbar/startcap-secure-end-active.png)
|
||||
skin/classic/browser/urlbar/startcap-secure-start-focused.png (urlbar/startcap-secure-start-focused.png)
|
||||
skin/classic/browser/urlbar/startcap-secure-start-focused-graphite.png (urlbar/startcap-secure-start-focused-graphite.png)
|
||||
skin/classic/browser/urlbar/startcap-secure-mid-focused.png (urlbar/startcap-secure-mid-focused.png)
|
||||
skin/classic/browser/urlbar/startcap-secure-mid-focused-graphite.png (urlbar/startcap-secure-mid-focused-graphite.png)
|
||||
skin/classic/browser/urlbar/startcap-secure-end-focused.png (urlbar/startcap-secure-end-focused.png)
|
||||
skin/classic/browser/urlbar/startcap-secure-end-focused-graphite.png (urlbar/startcap-secure-end-focused-graphite.png)
|
||||
skin/classic/browser/urlbar/startcap-verified-start.png (urlbar/startcap-verified-start.png)
|
||||
skin/classic/browser/urlbar/startcap-verified-mid.png (urlbar/startcap-verified-mid.png)
|
||||
skin/classic/browser/urlbar/startcap-verified-end.png (urlbar/startcap-verified-end.png)
|
||||
@ -153,16 +160,22 @@ classic.jar:
|
||||
skin/classic/browser/urlbar/startcap-verified-mid-active.png (urlbar/startcap-verified-mid-active.png)
|
||||
skin/classic/browser/urlbar/startcap-verified-end-active.png (urlbar/startcap-verified-end-active.png)
|
||||
skin/classic/browser/urlbar/startcap-verified-start-focused.png (urlbar/startcap-verified-start-focused.png)
|
||||
skin/classic/browser/urlbar/startcap-verified-start-focused-graphite.png (urlbar/startcap-verified-start-focused-graphite.png)
|
||||
skin/classic/browser/urlbar/startcap-verified-mid-focused.png (urlbar/startcap-verified-mid-focused.png)
|
||||
skin/classic/browser/urlbar/startcap-verified-mid-focused-graphite.png (urlbar/startcap-verified-mid-focused-graphite.png)
|
||||
skin/classic/browser/urlbar/startcap-verified-end-focused.png (urlbar/startcap-verified-end-focused.png)
|
||||
skin/classic/browser/urlbar/startcap-verified-end-focused-graphite.png (urlbar/startcap-verified-end-focused-graphite.png)
|
||||
skin/classic/browser/urlbar/startcap-secure.png (urlbar/startcap-secure.png)
|
||||
skin/classic/browser/urlbar/startcap-active.png (urlbar/startcap-active.png)
|
||||
skin/classic/browser/urlbar/startcap-active-rtl.png (urlbar/startcap-active-rtl.png)
|
||||
skin/classic/browser/urlbar/startcap-active-focused.png (urlbar/startcap-active-focused.png)
|
||||
skin/classic/browser/urlbar/startcap-active-focused-graphite.png (urlbar/startcap-active-focused-graphite.png)
|
||||
skin/classic/browser/urlbar/startcap-active-focused-graphite-rtl.png (urlbar/startcap-active-focused-graphite-rtl.png)
|
||||
skin/classic/browser/urlbar/startcap-active-focused-rtl.png (urlbar/startcap-active-focused-rtl.png)
|
||||
skin/classic/browser/urlbar/startcap-secure-active.png (urlbar/startcap-secure-active.png)
|
||||
skin/classic/browser/urlbar/urlbar-favicon-glow.png (urlbar/urlbar-favicon-glow.png)
|
||||
skin/classic/browser/urlbar/textfield-mid.png (urlbar/textfield-mid.png)
|
||||
skin/classic/browser/urlbar/textfield-mid-focused.png (urlbar/textfield-mid-focused.png)
|
||||
skin/classic/browser/urlbar/textfield-mid-focused-graphite.png (urlbar/textfield-mid-focused-graphite.png)
|
||||
icon.png
|
||||
preview.png
|
||||
|
@ -22,6 +22,10 @@
|
||||
background-image: url("chrome://browser/skin/urlbar/textfield-mid-focused.png");
|
||||
}
|
||||
|
||||
.searchbar-textbox[focused="true"] > .autocomplete-textbox-container > .textbox-input-box:-moz-system-metric(mac-graphite-theme) {
|
||||
background-image: url("chrome://browser/skin/urlbar/textfield-mid-focused-graphite.png");
|
||||
}
|
||||
|
||||
.searchbar-engine-image {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
@ -53,6 +57,14 @@
|
||||
background-image: url("chrome://browser/skin/urlbar/startcap-focused-rtl.png");
|
||||
}
|
||||
|
||||
.searchbar-textbox[focused="true"] > .searchbar-engine-button:-moz-system-metric(mac-graphite-theme) {
|
||||
background-image: url("chrome://browser/skin/urlbar/startcap-focused-graphite.png");
|
||||
}
|
||||
|
||||
.searchbar-textbox[focused="true"] > .searchbar-engine-button[chromedir="rtl"]:-moz-system-metric(mac-graphite-theme) {
|
||||
background-image: url("chrome://browser/skin/urlbar/startcap-focused-graphite-rtl.png");
|
||||
}
|
||||
|
||||
.searchbar-engine-button:hover:active,
|
||||
.searchbar-engine-button[open="true"] {
|
||||
background-image: url("chrome://browser/skin/urlbar/startcap-active.png") !important;
|
||||
@ -73,6 +85,16 @@
|
||||
background-image: url("chrome://browser/skin/urlbar/startcap-active-focused-rtl.png") !important;
|
||||
}
|
||||
|
||||
.searchbar-textbox[focused="true"] > .searchbar-engine-button:active:-moz-system-metric(mac-graphite-theme),
|
||||
.searchbar-textbox[focused="true"] > .searchbar-engine-button[open="true"]:-moz-system-metric(mac-graphite-theme) {
|
||||
background-image: url("chrome://browser/skin/urlbar/startcap-active-focused-graphite.png") !important;
|
||||
}
|
||||
|
||||
.searchbar-textbox[focused="true"] > .searchbar-engine-button[chromedir="rtl"]:active:-moz-system-metric(mac-graphite-theme),
|
||||
.searchbar-textbox[focused="true"] > .searchbar-engine-button[open="true"][chromedir="rtl"]:-moz-system-metric(mac-graphite-theme) {
|
||||
background-image: url("chrome://browser/skin/urlbar/startcap-active-focused-graphite-rtl.png") !important;
|
||||
}
|
||||
|
||||
.searchbar-engine-button > .button-box {
|
||||
-moz-appearance: none;
|
||||
padding: 0;
|
||||
@ -108,6 +130,14 @@
|
||||
background: url("chrome://browser/skin/urlbar/endcap-focused-rtl.png") no-repeat left top;
|
||||
}
|
||||
|
||||
.searchbar-textbox[focused="true"] > .search-go-container:-moz-system-metric(mac-graphite-theme) {
|
||||
background-image: url("chrome://browser/skin/urlbar/endcap-focused-graphite.png");
|
||||
}
|
||||
|
||||
.searchbar-textbox[focused="true"] > .search-go-container[chromedir="rtl"]:-moz-system-metric(mac-graphite-theme) {
|
||||
background-image: url("chrome://browser/skin/urlbar/endcap-focused-graphite-rtl.png");
|
||||
}
|
||||
|
||||
#searchbar[empty="true"] .search-go-button {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
After Width: | Height: | Size: 941 B |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 585 B |
After Width: | Height: | Size: 246 B |
After Width: | Height: | Size: 897 B |
After Width: | Height: | Size: 584 B |
After Width: | Height: | Size: 248 B |
After Width: | Height: | Size: 908 B |
After Width: | Height: | Size: 204 B |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.4 KiB |
@ -1163,7 +1163,7 @@ statusbarpanel#statusbar-display {
|
||||
|
||||
.ac-result-type-keyword,
|
||||
.autocomplete-treebody::-moz-tree-image(keyword, treecolAutoCompleteImage) {
|
||||
list-style-image: url(chrome://browser/skin/Search-glass.png);
|
||||
list-style-image: url(chrome://global/skin/icons/Search-glass.png);
|
||||
-moz-image-region: rect(0px 32px 16px 16px);
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
|
@ -30,8 +30,6 @@ classic.jar:
|
||||
skin/classic/browser/Go-arrow.png (Go-arrow.png)
|
||||
skin/classic/browser/Go-arrow-rtl.png (Go-arrow-rtl.png)
|
||||
* skin/classic/browser/searchbar.css (searchbar.css)
|
||||
skin/classic/browser/Search-glass.png (Search-glass.png)
|
||||
skin/classic/browser/Search-glass-rtl.png (Search-glass-rtl.png)
|
||||
skin/classic/browser/Search-addengines.png
|
||||
skin/classic/browser/section_collapsed.png
|
||||
skin/classic/browser/section_expanded.png
|
||||
@ -124,8 +122,6 @@ classic.jar:
|
||||
skin/classic/aero/browser/Go-arrow.png (Go-arrow-aero.png)
|
||||
skin/classic/aero/browser/Go-arrow-rtl.png (Go-arrow-rtl-aero.png)
|
||||
* skin/classic/aero/browser/searchbar.css (searchbar.css)
|
||||
skin/classic/aero/browser/Search-glass.png (Search-glass-aero.png)
|
||||
skin/classic/aero/browser/Search-glass-rtl.png (Search-glass-rtl-aero.png)
|
||||
skin/classic/aero/browser/Search-addengines.png
|
||||
skin/classic/aero/browser/section_collapsed.png
|
||||
skin/classic/aero/browser/section_expanded.png
|
||||
|
@ -80,12 +80,12 @@
|
||||
|
||||
.search-go-button {
|
||||
padding: 2px;
|
||||
list-style-image: url("chrome://browser/skin/Search-glass.png");
|
||||
list-style-image: url("chrome://global/skin/icons/Search-glass.png");
|
||||
-moz-image-region: rect(0px 16px 16px 0px);
|
||||
}
|
||||
|
||||
.search-go-button[chromedir="rtl"] {
|
||||
list-style-image: url("chrome://browser/skin/Search-glass-rtl.png");
|
||||
-moz-transform: scaleX(-1);
|
||||
}
|
||||
|
||||
.search-go-button:hover {
|
||||
|
@ -48,7 +48,7 @@ AC_DEFUN(MOZ_PATH_PROG,
|
||||
if test "$msyshost"; then
|
||||
case "[$]$1" in
|
||||
/*)
|
||||
$1="$(cd $(dirname "[$]$1") && pwd -W)/$(basename "[$]$1")"
|
||||
$1="$(cd "$(dirname "[$]$1")" && pwd -W)/$(basename "[$]$1")"
|
||||
if test -e "[$]$1.exe"; then
|
||||
$1="[$]$1.exe"
|
||||
fi
|
||||
@ -61,7 +61,7 @@ AC_DEFUN(MOZ_PATH_PROGS,
|
||||
if test "$msyshost"; then
|
||||
case "[$]$1" in
|
||||
/*)
|
||||
$1="$(cd $(dirname "[$]$1") && pwd -W)/$(basename "[$]$1")"
|
||||
$1="$(cd "$(dirname "[$]$1")" && pwd -W)/$(basename "[$]$1")"
|
||||
if test -e "[$]$1.exe"; then
|
||||
$1="[$]$1.exe"
|
||||
fi
|
||||
|
@ -68,6 +68,7 @@ __all__ = [
|
||||
"DEFAULT_APP",
|
||||
"CERTS_SRC_DIR",
|
||||
"environment",
|
||||
"dumpLeakLog",
|
||||
]
|
||||
|
||||
# These are generated in mozilla/build/Makefile.in
|
||||
@ -245,6 +246,7 @@ user_pref("network.manage-offline-status", false);
|
||||
user_pref("security.default_personal_cert", "Select Automatically"); // Need to client auth test be w/o any dialogs
|
||||
user_pref("network.http.prompt-temp-redirect", false);
|
||||
user_pref("svg.smil.enabled", true); // Needed for SMIL mochitests until bug 482402 lands
|
||||
user_pref("media.cache_size", 100);
|
||||
|
||||
user_pref("camino.warn_when_closing", false); // Camino-only, harmless to others
|
||||
"""
|
||||
@ -429,8 +431,35 @@ def checkForCrashes(profileDir, symbolsPath):
|
||||
# RUN THE APP #
|
||||
###############
|
||||
|
||||
def processLeakLog(leakLogFile, leakThreshold):
|
||||
"Process the leak log."
|
||||
def dumpLeakLog(leakLogFile, filter = False):
|
||||
"""Process the leak log, without parsing it.
|
||||
|
||||
Use this function if you want the raw log only.
|
||||
Use it preferably with the |XPCOM_MEM_LEAK_LOG| environment variable.
|
||||
"""
|
||||
|
||||
# Don't warn (nor "info") if the log file is not there.
|
||||
if not os.path.exists(leakLogFile):
|
||||
return
|
||||
|
||||
leaks = open(leakLogFile, "r")
|
||||
leakReport = leaks.read()
|
||||
leaks.close()
|
||||
|
||||
# Only |XPCOM_MEM_LEAK_LOG| reports can be actually filtered out.
|
||||
# Only check whether an actual leak was reported.
|
||||
if filter and not "0 TOTAL " in leakReport:
|
||||
return
|
||||
|
||||
# Simply copy the log.
|
||||
log.info(leakReport.rstrip("\n"))
|
||||
|
||||
def processLeakLog(leakLogFile, leakThreshold = 0):
|
||||
"""Process the leak log, parsing it.
|
||||
|
||||
Use this function if you want an additional PASS/FAIL summary.
|
||||
It must be used with the |XPCOM_MEM_BLOAT_LOG| environment variable.
|
||||
"""
|
||||
|
||||
if not os.path.exists(leakLogFile):
|
||||
log.info("WARNING refcount logging is off, so leaks can't be detected!")
|
||||
|
@ -1,2 +1,2 @@
|
||||
repo: f5ab154deef2ffa97f1b2139589ae4a1962090a4
|
||||
node: c07f9fe9fdaa85888314efa7001cd4fd768904c4
|
||||
node: 162a3b79a8b0799a9fb3c2aed909a3d09f6f1d39
|
||||
|
@ -9,6 +9,9 @@ A drop-in or mostly drop-in replacement for GNU make.
|
||||
import sys, os
|
||||
import pymake.command, pymake.process
|
||||
|
||||
import gc
|
||||
gc.disable()
|
||||
|
||||
pymake.command.main(sys.argv[1:], os.environ, os.getcwd(), cb=sys.exit)
|
||||
pymake.process.ParallelContext.spin()
|
||||
assert False, "Not reached"
|
||||
|
@ -6,7 +6,7 @@ structure, environment, and working directory. Typically they will all share a p
|
||||
except when a submake specifies -j1 when the parent make is building in parallel.
|
||||
"""
|
||||
|
||||
import os, subprocess, sys, logging, time, traceback
|
||||
import os, subprocess, sys, logging, time, traceback, re
|
||||
from optparse import OptionParser
|
||||
import data, parserdata, process, util
|
||||
|
||||
@ -15,6 +15,7 @@ import data, parserdata, process, util
|
||||
|
||||
makepypath = os.path.normpath(os.path.join(os.path.dirname(__file__), '../make.py'))
|
||||
|
||||
_simpleopts = re.compile(r'^[a-zA-Z]+(\s|$)')
|
||||
def parsemakeflags(env):
|
||||
"""
|
||||
Parse MAKEFLAGS from the environment into a sequence of command-line arguments.
|
||||
@ -26,7 +27,7 @@ def parsemakeflags(env):
|
||||
if makeflags == '':
|
||||
return []
|
||||
|
||||
if makeflags[0] not in ('-', ' '):
|
||||
if _simpleopts.match(makeflags):
|
||||
makeflags = '-' + makeflags
|
||||
|
||||
opts = []
|
||||
@ -71,6 +72,82 @@ DEALINGS IN THE SOFTWARE."""
|
||||
|
||||
_log = logging.getLogger('pymake.execution')
|
||||
|
||||
class _MakeContext(object):
|
||||
def __init__(self, makeflags, makelevel, workdir, context, env, targets, options, ostmts, overrides, cb):
|
||||
self.makeflags = makeflags
|
||||
self.makelevel = makelevel
|
||||
|
||||
self.workdir = workdir
|
||||
self.context = context
|
||||
self.env = env
|
||||
self.targets = targets
|
||||
self.options = options
|
||||
self.ostmts = ostmts
|
||||
self.overrides = overrides
|
||||
self.cb = cb
|
||||
|
||||
self.restarts = 0
|
||||
|
||||
self.remakecb(True)
|
||||
|
||||
def remakecb(self, remade):
|
||||
if remade:
|
||||
if self.restarts > 0:
|
||||
_log.info("make.py[%i]: Restarting makefile parsing", self.makelevel)
|
||||
|
||||
self.makefile = data.Makefile(restarts=self.restarts,
|
||||
make='%s %s' % (sys.executable.replace('\\', '/'), makepypath.replace('\\', '/')),
|
||||
makeflags=self.makeflags,
|
||||
makeoverrides=self.overrides,
|
||||
workdir=self.workdir,
|
||||
context=self.context, env=self.env, makelevel=self.makelevel,
|
||||
targets=self.targets, keepgoing=self.options.keepgoing)
|
||||
|
||||
self.restarts += 1
|
||||
|
||||
try:
|
||||
self.ostmts.execute(self.makefile)
|
||||
for f in self.options.makefiles:
|
||||
self.makefile.include(f)
|
||||
self.makefile.finishparsing()
|
||||
self.makefile.remakemakefiles(self.remakecb)
|
||||
except util.MakeError, e:
|
||||
print e
|
||||
self.context.defer(self.cb, 2)
|
||||
|
||||
return
|
||||
|
||||
if len(self.targets) == 0:
|
||||
if self.makefile.defaulttarget is None:
|
||||
print "No target specified and no default target found."
|
||||
self.context.defer(self.cb, 2)
|
||||
return
|
||||
|
||||
_log.info("Making default target %s", self.makefile.defaulttarget)
|
||||
self.realtargets = [self.makefile.defaulttarget]
|
||||
self.tstack = ['<default-target>']
|
||||
else:
|
||||
self.realtargets = self.targets
|
||||
self.tstack = ['<command-line>']
|
||||
|
||||
self.makefile.gettarget(self.realtargets.pop(0)).make(self.makefile, self.tstack, cb=self.makecb)
|
||||
|
||||
def makecb(self, error, didanything):
|
||||
assert error in (True, False)
|
||||
|
||||
if error:
|
||||
self.context.defer(self.cb, 2)
|
||||
return
|
||||
|
||||
if not len(self.realtargets):
|
||||
if self.options.printdir:
|
||||
print "make.py[%i]: Leaving directory '%s'" % (self.makelevel, self.workdir)
|
||||
sys.stdout.flush()
|
||||
|
||||
self.context.defer(self.cb, 0)
|
||||
else:
|
||||
self.makefile.gettarget(self.realtargets.pop(0)).make(self.makefile, self.tstack, self.makecb)
|
||||
|
||||
def main(args, env, cwd, cb):
|
||||
"""
|
||||
Start a single makefile execution, given a command line, working directory, and environment.
|
||||
@ -89,6 +166,9 @@ def main(args, env, cwd, cb):
|
||||
op.add_option('-d',
|
||||
action="store_true",
|
||||
dest="verbose", default=False)
|
||||
op.add_option('-k', '--keep-going',
|
||||
action="store_true",
|
||||
dest="keepgoing", default=False)
|
||||
op.add_option('--debug-log',
|
||||
dest="debuglog", default=None)
|
||||
op.add_option('-C', '--directory',
|
||||
@ -97,12 +177,16 @@ def main(args, env, cwd, cb):
|
||||
dest="printversion", default=False)
|
||||
op.add_option('-j', '--jobs', type="int",
|
||||
dest="jobcount", default=1)
|
||||
op.add_option('-w', '--print-directory', action="store_true",
|
||||
dest="printdir")
|
||||
op.add_option('--no-print-directory', action="store_false",
|
||||
dest="printdir", default=True)
|
||||
|
||||
options, arguments1 = op.parse_args(parsemakeflags(env))
|
||||
options, arguments2 = op.parse_args(args, values=options)
|
||||
|
||||
op.destroy()
|
||||
|
||||
arguments = arguments1 + arguments2
|
||||
|
||||
if options.printversion:
|
||||
@ -113,6 +197,12 @@ def main(args, env, cwd, cb):
|
||||
shortflags = []
|
||||
longflags = []
|
||||
|
||||
if options.keepgoing:
|
||||
shortflags.append('k')
|
||||
|
||||
if options.printdir:
|
||||
shortflags.append('w')
|
||||
|
||||
loglevel = logging.WARNING
|
||||
if options.verbose:
|
||||
loglevel = logging.DEBUG
|
||||
@ -128,9 +218,12 @@ def main(args, env, cwd, cb):
|
||||
else:
|
||||
workdir = os.path.join(cwd, options.directory)
|
||||
|
||||
shortflags.append('j%i' % (options.jobcount,))
|
||||
if options.jobcount != 1:
|
||||
longflags.append('-j%i' % (options.jobcount,))
|
||||
|
||||
makeflags = ''.join(shortflags) + ' ' + ' '.join(longflags)
|
||||
makeflags = ''.join(shortflags)
|
||||
if len(longflags):
|
||||
makeflags += ' ' + ' '.join(longflags)
|
||||
|
||||
logging.basicConfig(level=loglevel, **logkwargs)
|
||||
|
||||
@ -148,69 +241,9 @@ def main(args, env, cwd, cb):
|
||||
cb(2)
|
||||
return
|
||||
|
||||
overrides, targets = parserdata.parsecommandlineargs(arguments)
|
||||
|
||||
def makecb(error, didanything, makefile, realtargets, tstack, i, firsterror):
|
||||
if error is not None:
|
||||
print error
|
||||
if firsterror is None:
|
||||
firsterror = error
|
||||
|
||||
if i == len(realtargets):
|
||||
if options.printdir:
|
||||
print "make.py[%i]: Leaving directory '%s'" % (makelevel, workdir)
|
||||
sys.stdout.flush()
|
||||
|
||||
context.defer(cb, firsterror and 2 or 0)
|
||||
else:
|
||||
deferredmake = process.makedeferrable(makecb, makefile=makefile,
|
||||
realtargets=realtargets, tstack=tstack, i=i+1, firsterror=firsterror)
|
||||
|
||||
makefile.gettarget(realtargets[i]).make(makefile, tstack, [], cb=deferredmake)
|
||||
|
||||
|
||||
def remakecb(remade, restarts, makefile):
|
||||
if remade:
|
||||
if restarts > 0:
|
||||
_log.info("make.py[%i]: Restarting makefile parsing", makelevel)
|
||||
makefile = data.Makefile(restarts=restarts, make='%s %s' % (sys.executable.replace('\\', '/'), makepypath.replace('\\', '/')),
|
||||
makeflags=makeflags, makelevel=makelevel, workdir=workdir,
|
||||
context=context, env=env,
|
||||
targets=targets)
|
||||
|
||||
try:
|
||||
overrides.execute(makefile)
|
||||
for f in options.makefiles:
|
||||
makefile.include(f)
|
||||
makefile.finishparsing()
|
||||
makefile.remakemakefiles(process.makedeferrable(remakecb, restarts=restarts + 1, makefile=makefile))
|
||||
|
||||
except util.MakeError, e:
|
||||
print e
|
||||
context.defer(cb, 2)
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
if len(targets) == 0:
|
||||
if makefile.defaulttarget is None:
|
||||
print "No target specified and no default target found."
|
||||
context.defer(cb, 2)
|
||||
return
|
||||
|
||||
_log.info("Making default target %s", makefile.defaulttarget)
|
||||
realtargets = [makefile.defaulttarget]
|
||||
tstack = ['<default-target>']
|
||||
else:
|
||||
realtargets = targets
|
||||
tstack = ['<command-line>']
|
||||
|
||||
deferredmake = process.makedeferrable(makecb, makefile=makefile,
|
||||
realtargets=realtargets, tstack=tstack, i=1, firsterror=None)
|
||||
makefile.gettarget(realtargets[0]).make(makefile, tstack, [], cb=deferredmake)
|
||||
|
||||
context.defer(remakecb, True, 0, None)
|
||||
ostmts, targets, overrides = parserdata.parsecommandlineargs(arguments)
|
||||
|
||||
_MakeContext(makeflags, makelevel, workdir, context, env, targets, options, ostmts, overrides, cb)
|
||||
except (util.MakeError), e:
|
||||
print e
|
||||
if options.printdir:
|
||||
|
@ -2,7 +2,7 @@
|
||||
A representation of makefile data structures.
|
||||
"""
|
||||
|
||||
import logging, re, os
|
||||
import logging, re, os, sys
|
||||
import parserdata, parser, functions, process, util, builtins
|
||||
from cStringIO import StringIO
|
||||
|
||||
@ -312,14 +312,6 @@ class Variables(object):
|
||||
assert source in (self.SOURCE_OVERRIDE, self.SOURCE_MAKEFILE, self.SOURCE_AUTOMATIC)
|
||||
assert isinstance(value, str)
|
||||
|
||||
def expand():
|
||||
try:
|
||||
d = parser.Data.fromstring(value, parserdata.Location("Expansion of variable '%s'" % (name,), 1, 0))
|
||||
valueexp, t, o = parser.parsemakesyntax(d, 0, (), parser.iterdata)
|
||||
return valueexp, None
|
||||
except parser.SyntaxError, e:
|
||||
return None, e
|
||||
|
||||
if name not in self._map:
|
||||
self._map[name] = self.FLAVOR_APPEND, source, value, None
|
||||
return
|
||||
@ -475,131 +467,263 @@ class Pattern(object):
|
||||
|
||||
return self._backre.sub(r'\\\1', self.data[0]) + '%' + self.data[1]
|
||||
|
||||
MAKESTATE_NONE = 0
|
||||
MAKESTATE_FINISHED = 1
|
||||
MAKESTATE_WORKING = 2
|
||||
class RemakeTargetSerially(object):
|
||||
__slots__ = ('target', 'makefile', 'indent', 'rlist')
|
||||
|
||||
def __init__(self, target, makefile, indent, rlist):
|
||||
self.target = target
|
||||
self.makefile = makefile
|
||||
self.indent = indent
|
||||
self.rlist = rlist
|
||||
self.commandscb(False)
|
||||
|
||||
def resolvecb(self, error, didanything):
|
||||
assert error in (True, False)
|
||||
|
||||
if didanything:
|
||||
self.target.didanything = True
|
||||
|
||||
if error:
|
||||
self.target.error = True
|
||||
self.makefile.error = True
|
||||
if not self.makefile.keepgoing:
|
||||
self.target.notifydone(self.makefile)
|
||||
return
|
||||
else:
|
||||
# don't run the commands!
|
||||
del self.rlist[0]
|
||||
self.commandscb(error=False)
|
||||
else:
|
||||
self.rlist.pop(0).runcommands(self.indent, self.commandscb)
|
||||
|
||||
def commandscb(self, error):
|
||||
assert error in (True, False)
|
||||
|
||||
if error:
|
||||
self.target.error = True
|
||||
self.makefile.error = True
|
||||
|
||||
if self.target.error and not self.makefile.keepgoing:
|
||||
self.target.notifydone(self.makefile)
|
||||
return
|
||||
|
||||
if not len(self.rlist):
|
||||
self.target.notifydone(self.makefile)
|
||||
else:
|
||||
self.rlist[0].resolvedeps(True, self.resolvecb)
|
||||
|
||||
class RemakeTargetParallel(object):
|
||||
__slots__ = ('target', 'makefile', 'indent', 'rlist', 'rulesremaining', 'currunning')
|
||||
|
||||
def __init__(self, target, makefile, indent, rlist):
|
||||
self.target = target
|
||||
self.makefile = makefile
|
||||
self.indent = indent
|
||||
self.rlist = rlist
|
||||
|
||||
self.rulesremaining = len(rlist)
|
||||
self.currunning = False
|
||||
|
||||
for r in rlist:
|
||||
makefile.context.defer(self.doresolve, r)
|
||||
|
||||
def doresolve(self, r):
|
||||
if self.makefile.error and not self.makefile.keepgoing:
|
||||
r.error = True
|
||||
self.resolvecb(True, False)
|
||||
else:
|
||||
r.resolvedeps(False, self.resolvecb)
|
||||
|
||||
def resolvecb(self, error, didanything):
|
||||
assert error in (True, False)
|
||||
|
||||
if error:
|
||||
self.target.error = True
|
||||
|
||||
if didanything:
|
||||
self.target.didanything = True
|
||||
|
||||
self.rulesremaining -= 1
|
||||
|
||||
# commandscb takes care of the details if we're currently building
|
||||
# something
|
||||
if self.currunning:
|
||||
return
|
||||
|
||||
self.runnext()
|
||||
|
||||
def runnext(self):
|
||||
assert not self.currunning
|
||||
|
||||
if self.makefile.error and not self.makefile.keepgoing:
|
||||
self.rlist = []
|
||||
else:
|
||||
while len(self.rlist) and self.rlist[0].error:
|
||||
del self.rlist[0]
|
||||
|
||||
if not len(self.rlist):
|
||||
if not self.rulesremaining:
|
||||
self.target.notifydone(self.makefile)
|
||||
return
|
||||
|
||||
if self.rlist[0].depsremaining != 0:
|
||||
return
|
||||
|
||||
self.currunning = True
|
||||
self.rlist.pop(0).runcommands(self.indent, self.commandscb)
|
||||
|
||||
def commandscb(self, error):
|
||||
assert error in (True, False)
|
||||
if error:
|
||||
self.target.error = True
|
||||
self.makefile.error = True
|
||||
|
||||
assert self.currunning
|
||||
self.currunning = False
|
||||
self.runnext()
|
||||
|
||||
class RemakeRuleContext(object):
|
||||
__slots__ = ('rule', 'deps', 'depsremaining', 'error', 'didanything', 'running')
|
||||
|
||||
def __init__(self, rule, deps):
|
||||
def __init__(self, target, makefile, rule, deps,
|
||||
targetstack, avoidremakeloop):
|
||||
self.target = target
|
||||
self.makefile = makefile
|
||||
self.rule = rule
|
||||
self.deps = deps
|
||||
self.targetstack = targetstack
|
||||
self.avoidremakeloop = avoidremakeloop
|
||||
|
||||
self.running = False
|
||||
self.error = False
|
||||
self.depsremaining = len(deps) + 1
|
||||
|
||||
def resolvedeps(self, target, makefile, targetstack, rulestack, serial, cb):
|
||||
if serial:
|
||||
self._resolvedepsserial(target, makefile, targetstack, rulestack, cb)
|
||||
else:
|
||||
self._resolvedepsparallel(target, makefile, targetstack, rulestack, cb)
|
||||
|
||||
def _resolvedepsserial(self, target, makefile, targetstack, rulestack, cb):
|
||||
resolvelist = list(self.deps)
|
||||
def resolvedeps(self, serial, cb):
|
||||
self.resolvecb = cb
|
||||
self.didanything = False
|
||||
if serial:
|
||||
self._resolvedepsserial()
|
||||
else:
|
||||
self._resolvedepsparallel()
|
||||
|
||||
def depfinished(error, didanything):
|
||||
if error is not None:
|
||||
cb(error=error, didanything=None)
|
||||
def _depfinishedserial(self, error, didanything):
|
||||
assert error in (True, False)
|
||||
|
||||
if didanything:
|
||||
self.didanything = True
|
||||
|
||||
if error:
|
||||
self.error = True
|
||||
if not self.makefile.keepgoing:
|
||||
self.resolvecb(error=True, didanything=self.didanything)
|
||||
return
|
||||
|
||||
if len(self.resolvelist):
|
||||
self.makefile.context.defer(self.resolvelist.pop(0).make,
|
||||
self.makefile, self.targetstack, self._depfinishedserial)
|
||||
else:
|
||||
self.resolvecb(error=self.error, didanything=self.didanything)
|
||||
|
||||
if didanything:
|
||||
self.didanything = True
|
||||
|
||||
if len(resolvelist):
|
||||
makefile.context.defer(resolvelist.pop(0).make, makefile, targetstack, rulestack, depfinished)
|
||||
else:
|
||||
cb(error=None, didanything=self.didanything)
|
||||
def _resolvedepsserial(self):
|
||||
self.resolvelist = list(self.deps)
|
||||
self._depfinishedserial(False, False)
|
||||
|
||||
depfinished(None, False)
|
||||
def _startdepparallel(self, d):
|
||||
if self.makefile.error:
|
||||
depfinished(True, False)
|
||||
else:
|
||||
d.make(self.makefile, self.targetstack, self._depfinishedparallel)
|
||||
|
||||
def _depfinishedparallel(self, error, didanything):
|
||||
assert error in (True, False)
|
||||
|
||||
if error:
|
||||
print "<%s>: Found error" % self.target.target
|
||||
self.error = True
|
||||
if didanything:
|
||||
self.didanything = True
|
||||
|
||||
def _resolvedepsparallel(self, target, makefile, targetstack, rulestack, cb):
|
||||
self.depsremaining -= 1
|
||||
if self.depsremaining == 0:
|
||||
cb(error=None, didanything=False)
|
||||
self.resolvecb(error=self.error, didanything=self.didanything)
|
||||
|
||||
def _resolvedepsparallel(self):
|
||||
self.depsremaining -= 1
|
||||
if self.depsremaining == 0:
|
||||
self.resolvecb(error=self.error, didanything=self.didanything)
|
||||
return
|
||||
|
||||
self.error = None
|
||||
self.didanything = False
|
||||
|
||||
def startdep(d):
|
||||
if self.error is not None:
|
||||
depfinished(None, False)
|
||||
else:
|
||||
d.make(makefile, targetstack, rulestack, depfinished)
|
||||
|
||||
def depfinished(error, didanything):
|
||||
if error is not None:
|
||||
if self.error is None:
|
||||
self.error = error
|
||||
elif didanything:
|
||||
self.didanything = True
|
||||
|
||||
self.depsremaining -= 1
|
||||
|
||||
if self.depsremaining == 0:
|
||||
cb(error=self.error, didanything=self.didanything)
|
||||
|
||||
for d in self.deps:
|
||||
makefile.context.defer(startdep, d)
|
||||
self.makefile.context.defer(self._startdepparallel, d)
|
||||
|
||||
def runcommands(self, target, makefile, avoidremakeloop, indent, cb):
|
||||
assert not self.running
|
||||
self.running = True
|
||||
if self.rule is None or not len(self.rule.commands):
|
||||
if target.mtime is None:
|
||||
target._beingremade()
|
||||
else:
|
||||
for d in self.deps:
|
||||
if mtimeislater(d.mtime, target.mtime):
|
||||
target._beingremade()
|
||||
break
|
||||
cb(error=None)
|
||||
def _commandcb(self, error):
|
||||
assert error in (True, False)
|
||||
|
||||
if error:
|
||||
self.runcb(error=True)
|
||||
return
|
||||
|
||||
def commandcb(error):
|
||||
if error is not None:
|
||||
cb(error=error)
|
||||
return
|
||||
if len(self.commands):
|
||||
self.commands.pop(0)(self._commandcb)
|
||||
else:
|
||||
self.runcb(error=False)
|
||||
|
||||
if len(commands):
|
||||
commands.pop(0)(commandcb)
|
||||
def runcommands(self, indent, cb):
|
||||
assert not self.running
|
||||
self.running = True
|
||||
|
||||
self.runcb = cb
|
||||
|
||||
if self.rule is None or not len(self.rule.commands):
|
||||
if self.target.mtime is None:
|
||||
self.target.beingremade()
|
||||
else:
|
||||
cb(error=None)
|
||||
for d in self.deps:
|
||||
if mtimeislater(d.mtime, self.target.mtime):
|
||||
self.target.beingremade()
|
||||
break
|
||||
cb(error=False)
|
||||
return
|
||||
|
||||
remake = False
|
||||
if target.mtime is None:
|
||||
if self.target.mtime is None:
|
||||
remake = True
|
||||
_log.info("%sRemaking %s using rule at %s: target doesn't exist or is a forced target", indent, target.target, self.rule.loc)
|
||||
_log.info("%sRemaking %s using rule at %s: target doesn't exist or is a forced target", indent, self.target.target, self.rule.loc)
|
||||
|
||||
if not remake:
|
||||
if self.rule.doublecolon:
|
||||
if len(self.deps) == 0:
|
||||
if avoidremakeloop:
|
||||
_log.info("%sNot remaking %s using rule at %s because it would introduce an infinite loop.", indent, target.target, self.rule.loc)
|
||||
if self.avoidremakeloop:
|
||||
_log.info("%sNot remaking %s using rule at %s because it would introduce an infinite loop.", indent, self.target.target, self.rule.loc)
|
||||
else:
|
||||
_log.info("%sRemaking %s using rule at %s because there are no prerequisites listed for a double-colon rule.", indent, target.target, self.rule.loc)
|
||||
_log.info("%sRemaking %s using rule at %s because there are no prerequisites listed for a double-colon rule.", indent, self.target.target, self.rule.loc)
|
||||
remake = True
|
||||
|
||||
if not remake:
|
||||
for d in self.deps:
|
||||
if mtimeislater(d.mtime, target.mtime):
|
||||
_log.info("%sRemaking %s using rule at %s because %s is newer.", indent, target.target, self.rule.loc, d.target)
|
||||
if mtimeislater(d.mtime, self.target.mtime):
|
||||
_log.info("%sRemaking %s using rule at %s because %s is newer.", indent, self.target.target, self.rule.loc, d.target)
|
||||
remake = True
|
||||
break
|
||||
|
||||
if remake:
|
||||
target._beingremade()
|
||||
target._didanything = True
|
||||
self.target.beingremade()
|
||||
self.target.didanything = True
|
||||
try:
|
||||
commands = [c for c in self.rule.getcommands(target, makefile)]
|
||||
self.commands = [c for c in self.rule.getcommands(self.target, self.makefile)]
|
||||
except util.MakeError, e:
|
||||
cb(error=e)
|
||||
print e
|
||||
sys.stdout.flush()
|
||||
cb(error=True)
|
||||
return
|
||||
|
||||
commandcb(None)
|
||||
self._commandcb(False)
|
||||
else:
|
||||
cb(error=None)
|
||||
cb(error=False)
|
||||
|
||||
MAKESTATE_NONE = 0
|
||||
MAKESTATE_FINISHED = 1
|
||||
MAKESTATE_WORKING = 2
|
||||
|
||||
class Target(object):
|
||||
"""
|
||||
@ -843,7 +967,7 @@ class Target(object):
|
||||
self.vpathtarget = self.target
|
||||
self.mtime = None
|
||||
|
||||
def _beingremade(self):
|
||||
def beingremade(self):
|
||||
"""
|
||||
When we remake ourself, we need to reset our mtime and vpathtarget.
|
||||
|
||||
@ -853,37 +977,38 @@ class Target(object):
|
||||
self.mtime = None
|
||||
self.vpathtarget = self.target
|
||||
|
||||
def _notifydone(self, makefile):
|
||||
assert self._state == MAKESTATE_WORKING
|
||||
def notifydone(self, makefile):
|
||||
assert self._state == MAKESTATE_WORKING, "State was %s" % self._state
|
||||
|
||||
self._state = MAKESTATE_FINISHED
|
||||
for cb in self._callbacks:
|
||||
makefile.context.defer(cb, error=self._makeerror, didanything=self._didanything)
|
||||
makefile.context.defer(cb, error=self.error, didanything=self.didanything)
|
||||
del self._callbacks
|
||||
|
||||
def make(self, makefile, targetstack, rulestack, cb, avoidremakeloop=False):
|
||||
def make(self, makefile, targetstack, cb, avoidremakeloop=False):
|
||||
"""
|
||||
If we are out of date, asynchronously make ourself. This is a multi-stage process, mostly handled
|
||||
by enclosed functions:
|
||||
by the helper objects RemakeTargetSerially, RemakeTargetParallel,
|
||||
RemakeRuleContext. These helper objects should keep us from developing
|
||||
any cyclical dependencies.
|
||||
|
||||
* resolve dependencies (synchronous)
|
||||
* gather a list of rules to execute and related dependencies (synchronous)
|
||||
* for each rule (rulestart)
|
||||
** remake dependencies (asynchronous, toplevel, callback to start each dependency is `depstart`,
|
||||
callback when each is finished is `depfinished``
|
||||
** build list of commands to execute (synchronous, in `runcommands`)
|
||||
** execute each command (asynchronous, runcommands.commandcb)
|
||||
* asynchronously notify rulefinished when each rule is complete
|
||||
* for each rule (in parallel)
|
||||
** remake dependencies (asynchronous)
|
||||
** build list of commands to execute (synchronous)
|
||||
** execute each command (asynchronous)
|
||||
* asynchronously notify when all rules are complete
|
||||
|
||||
@param cb A callback function to notify when remaking is finished. It is called
|
||||
thusly: callback(error=exception/None, didanything=True/False/None)
|
||||
thusly: callback(error=True/False, didanything=True/False)
|
||||
If there is no asynchronous activity to perform, the callback may be called directly.
|
||||
"""
|
||||
|
||||
serial = makefile.context.jcount == 1
|
||||
|
||||
if self._state == MAKESTATE_FINISHED:
|
||||
cb(error=self._makeerror, didanything=self._didanything)
|
||||
cb(error=self.error, didanything=self.didanything)
|
||||
return
|
||||
|
||||
if self._state == MAKESTATE_WORKING:
|
||||
@ -895,25 +1020,26 @@ class Target(object):
|
||||
|
||||
self._state = MAKESTATE_WORKING
|
||||
self._callbacks = [cb]
|
||||
self._makeerror = None
|
||||
self._didanything = False
|
||||
self.error = False
|
||||
self.didanything = False
|
||||
|
||||
indent = getindent(targetstack)
|
||||
|
||||
try:
|
||||
self.resolvedeps(makefile, targetstack, rulestack, False)
|
||||
self.resolvedeps(makefile, targetstack, [], False)
|
||||
except util.MakeError, e:
|
||||
self._makeerror = e
|
||||
self._notifydone(makefile)
|
||||
print e
|
||||
self.error = True
|
||||
self.notifydone(makefile)
|
||||
return
|
||||
|
||||
assert self.vpathtarget is not None, "Target was never resolved!"
|
||||
if not len(self.rules):
|
||||
self._notifydone(makefile)
|
||||
self.notifydone(makefile)
|
||||
return
|
||||
|
||||
if self.isdoublecolon():
|
||||
rulelist = [RemakeRuleContext(r, [makefile.gettarget(p) for p in r.prerequisites]) for r in self.rules]
|
||||
rulelist = [RemakeRuleContext(self, makefile, r, [makefile.gettarget(p) for p in r.prerequisites], targetstack, avoidremakeloop) for r in self.rules]
|
||||
else:
|
||||
alldeps = []
|
||||
|
||||
@ -929,85 +1055,14 @@ class Target(object):
|
||||
else:
|
||||
alldeps.extend(rdeps)
|
||||
|
||||
rulelist = [RemakeRuleContext(commandrule, alldeps)]
|
||||
rulelist = [RemakeRuleContext(self, makefile, commandrule, alldeps, targetstack, avoidremakeloop)]
|
||||
|
||||
targetstack = targetstack + [self.target]
|
||||
|
||||
if serial:
|
||||
def resolvecb(error, didanything):
|
||||
if error is not None:
|
||||
self._makeerror = error
|
||||
self._notifydone(makefile)
|
||||
return
|
||||
|
||||
if didanything:
|
||||
self._didanything = True
|
||||
rulelist.pop(0).runcommands(self, makefile, avoidremakeloop, indent, commandscb)
|
||||
|
||||
def commandscb(error):
|
||||
if error is not None:
|
||||
self._makeerror = error
|
||||
self._notifydone(makefile)
|
||||
return
|
||||
|
||||
if not len(rulelist):
|
||||
self._notifydone(makefile)
|
||||
return
|
||||
|
||||
rulelist[0].resolvedeps(self, makefile, targetstack, rulestack, serial, resolvecb)
|
||||
|
||||
commandscb(None)
|
||||
RemakeTargetSerially(self, makefile, indent, rulelist)
|
||||
else:
|
||||
def doresolve(r):
|
||||
if self._makeerror is not None:
|
||||
resolvecb(None, False)
|
||||
else:
|
||||
r.resolvedeps(self, makefile, targetstack, rulestack, serial, resolvecb)
|
||||
|
||||
def resolvecb(error, didanything):
|
||||
if error is not None:
|
||||
if self._makeerror is None:
|
||||
self._makeerror = error
|
||||
elif didanything:
|
||||
self._didanything = didanything
|
||||
|
||||
if self._makeerror is not None:
|
||||
r = rulelist.pop()
|
||||
assert not r.running
|
||||
if not len(rulelist):
|
||||
self._notifydone(makefile)
|
||||
return
|
||||
|
||||
rtop = rulelist[0]
|
||||
if rtop.running or rtop.depsremaining != 0:
|
||||
return
|
||||
|
||||
rtop.runcommands(self, makefile, avoidremakeloop, indent, commandscb)
|
||||
|
||||
def commandscb(error):
|
||||
if error is not None:
|
||||
if self._makeerror is None:
|
||||
self._makeerror = error
|
||||
|
||||
r = rulelist.pop(0)
|
||||
assert r.running
|
||||
|
||||
if not len(rulelist):
|
||||
self._notifydone(makefile)
|
||||
return
|
||||
|
||||
if self._makeerror is not None:
|
||||
return
|
||||
|
||||
rtop = rulelist[0]
|
||||
if rtop.running or rtop.depsremaining != 0:
|
||||
return
|
||||
|
||||
rtop.runcommands(self, makefile, avoidremakeloop, indent, commandscb)
|
||||
|
||||
for r in rulelist:
|
||||
makefile.context.defer(doresolve, r)
|
||||
|
||||
RemakeTargetParallel(self, makefile, indent, rulelist)
|
||||
|
||||
def dirpart(p):
|
||||
d, s, f = util.strrpartition(p, '/')
|
||||
@ -1084,9 +1139,10 @@ class _CommandWrapper(object):
|
||||
|
||||
def _cb(self, res):
|
||||
if res != 0 and not self.ignoreErrors:
|
||||
self.usercb(error=DataError("command '%s' failed, return code %s" % (self.cline, res), self.loc))
|
||||
print "%s: command '%s' failed, return code %i" % (self.loc, self.cline, res)
|
||||
self.usercb(error=True)
|
||||
else:
|
||||
self.usercb(error=None)
|
||||
self.usercb(error=False)
|
||||
|
||||
def __call__(self, cb):
|
||||
self.usercb = cb
|
||||
@ -1212,13 +1268,39 @@ class PatternRule(object):
|
||||
def prerequisitesforstem(self, dir, stem):
|
||||
return [p.resolve(dir, stem) for p in self.prerequisites]
|
||||
|
||||
class _RemakeContext(object):
|
||||
def __init__(self, makefile, remakelist, mtimelist, cb):
|
||||
self.makefile = makefile
|
||||
self.remakelist = remakelist
|
||||
self.mtimelist = mtimelist # list of (target, mtime)
|
||||
self.cb = cb
|
||||
|
||||
self.remakecb(error=False, didanything=False)
|
||||
|
||||
def remakecb(self, error, didanything):
|
||||
assert error in (True, False)
|
||||
|
||||
if error:
|
||||
print "Error remaking makefiles (ignored)"
|
||||
|
||||
if len(self.remakelist):
|
||||
self.remakelist.pop(0).make(self.makefile, [], avoidremakeloop=True, cb=self.remakecb)
|
||||
else:
|
||||
for t, oldmtime in self.mtimelist:
|
||||
if t.mtime != oldmtime:
|
||||
self.cb(remade=True)
|
||||
return
|
||||
self.cb(remade=False)
|
||||
|
||||
class Makefile(object):
|
||||
"""
|
||||
The top-level data structure for makefile execution. It holds Targets, implicit rules, and other
|
||||
state data.
|
||||
"""
|
||||
|
||||
def __init__(self, workdir=None, env=None, restarts=0, make=None, makeflags=None, makelevel=0, context=None, targets=()):
|
||||
def __init__(self, workdir=None, env=None, restarts=0, make=None,
|
||||
makeflags='', makeoverrides='',
|
||||
makelevel=0, context=None, targets=(), keepgoing=False):
|
||||
self.defaulttarget = None
|
||||
|
||||
if env is None:
|
||||
@ -1230,8 +1312,8 @@ class Makefile(object):
|
||||
|
||||
self.context = context
|
||||
self.exportedvars = {}
|
||||
self.overrides = []
|
||||
self._targets = {}
|
||||
self.keepgoing = keepgoing
|
||||
self._patternvariables = [] # of (pattern, variables)
|
||||
self.implicitrules = []
|
||||
self.parsingfinished = False
|
||||
@ -1255,9 +1337,18 @@ class Makefile(object):
|
||||
self.variables.set('MAKE', Variables.FLAVOR_SIMPLE,
|
||||
Variables.SOURCE_MAKEFILE, make)
|
||||
|
||||
if makeflags is not None:
|
||||
self.variables.set('MAKEFLAGS', Variables.FLAVOR_SIMPLE,
|
||||
Variables.SOURCE_MAKEFILE, makeflags)
|
||||
if makeoverrides != '':
|
||||
self.variables.set('-*-command-variables-*-', Variables.FLAVOR_SIMPLE,
|
||||
Variables.SOURCE_AUTOMATIC, makeoverrides)
|
||||
makeflags += ' -- $(MAKEOVERRIDES)'
|
||||
|
||||
self.variables.set('MAKEOVERRIDES', Variables.FLAVOR_RECURSIVE,
|
||||
Variables.SOURCE_ENVIRONMENT,
|
||||
'${-*-command-variables-*-}')
|
||||
|
||||
self.variables.set('MAKEFLAGS', Variables.FLAVOR_RECURSIVE,
|
||||
Variables.SOURCE_MAKEFILE, makeflags)
|
||||
self.exportedvars['MAKEFLAGS'] = True
|
||||
|
||||
self.makelevel = makelevel
|
||||
self.variables.set('MAKELEVEL', Variables.FLAVOR_SIMPLE,
|
||||
@ -1267,7 +1358,8 @@ class Makefile(object):
|
||||
Variables.SOURCE_AUTOMATIC, ' '.join(targets))
|
||||
|
||||
for vname, val in builtins.variables.iteritems():
|
||||
self.variables.set(vname, Variables.FLAVOR_SIMPLE,
|
||||
self.variables.set(vname,
|
||||
Variables.FLAVOR_SIMPLE,
|
||||
Variables.SOURCE_IMPLICIT, val)
|
||||
|
||||
def foundtarget(self, t):
|
||||
@ -1349,6 +1441,8 @@ class Makefile(object):
|
||||
if len(np.rules):
|
||||
self.context = process.getcontext(1)
|
||||
|
||||
self.error = False
|
||||
|
||||
def include(self, path, required=True, loc=None):
|
||||
"""
|
||||
Include the makefile at `path`.
|
||||
@ -1389,17 +1483,6 @@ class Makefile(object):
|
||||
return withoutdups(vp)
|
||||
|
||||
def remakemakefiles(self, cb):
|
||||
reparse = False
|
||||
|
||||
serial = self.context.jcount == 1
|
||||
|
||||
def remakedone():
|
||||
for t, oldmtime in mlist:
|
||||
if t.mtime != oldmtime:
|
||||
cb(remade=True)
|
||||
return
|
||||
cb(remade=False)
|
||||
|
||||
mlist = []
|
||||
for f in self.included:
|
||||
t = self.gettarget(f)
|
||||
@ -1409,33 +1492,7 @@ class Makefile(object):
|
||||
|
||||
mlist.append((t, oldmtime))
|
||||
|
||||
if serial:
|
||||
remakelist = [self.gettarget(f) for f in self.included]
|
||||
def remakecb(error, didanything):
|
||||
if error is not None:
|
||||
print "Error remaking makefiles (ignored): ", error
|
||||
|
||||
if len(remakelist):
|
||||
t = remakelist.pop(0)
|
||||
t.make(self, [], [], avoidremakeloop=True, cb=remakecb)
|
||||
else:
|
||||
remakedone()
|
||||
|
||||
remakelist.pop(0).make(self, [], [], avoidremakeloop=True, cb=remakecb)
|
||||
else:
|
||||
o = util.makeobject(('remakesremaining',), remakesremaining=len(self.included))
|
||||
def remakecb(error, didanything):
|
||||
if error is not None:
|
||||
print "Error remaking makefiles (ignored): ", error
|
||||
|
||||
o.remakesremaining -= 1
|
||||
if o.remakesremaining == 0:
|
||||
remakedone()
|
||||
|
||||
for t, mtime in mlist:
|
||||
t.make(self, [], [], avoidremakeloop=True, cb=remakecb)
|
||||
|
||||
flagescape = re.compile(r'([\s\\])')
|
||||
_RemakeContext(self, [self.gettarget(f) for f in self.included], mlist, cb)
|
||||
|
||||
def getsubenvironment(self, variables):
|
||||
env = dict(self.env)
|
||||
@ -1452,16 +1509,5 @@ class Makefile(object):
|
||||
|
||||
makeflags = ''
|
||||
|
||||
flavor, source, val = variables.get('MAKEFLAGS')
|
||||
if val is not None:
|
||||
flagsval = val.resolvestr(self, variables, ['MAKEFLAGS'])
|
||||
if flagsval != '':
|
||||
makeflags = flagsval
|
||||
|
||||
makeflags += ' -- '
|
||||
makeflags += ' '.join((self.flagescape.sub(r'\\\1', o) for o in self.overrides))
|
||||
|
||||
env['MAKEFLAGS'] = makeflags
|
||||
|
||||
env['MAKELEVEL'] = str(self.makelevel + 1)
|
||||
return env
|
||||
|
@ -574,6 +574,8 @@ class OriginFunction(Function):
|
||||
r = 'command line'
|
||||
elif source == data.Variables.SOURCE_AUTOMATIC:
|
||||
r = 'automatic'
|
||||
elif source == data.Variables.SOURCE_IMPLICIT:
|
||||
r = 'default'
|
||||
|
||||
fd.write(r)
|
||||
|
||||
|
@ -451,7 +451,22 @@ _conditionkeywordstokenlist = TokenList.get(_conditiontokens)
|
||||
|
||||
_varsettokens = (':=', '+=', '?=', '=')
|
||||
|
||||
_parsecache = {} # realpath -> (mtime, Statements)
|
||||
def _parsefile(pathname):
|
||||
fd = open(pathname, "rU")
|
||||
stmts = parsestream(fd, pathname)
|
||||
stmts.mtime = os.fstat(fd.fileno()).st_mtime
|
||||
fd.close()
|
||||
return stmts
|
||||
|
||||
def _checktime(path, stmts):
|
||||
mtime = os.path.getmtime(path)
|
||||
if mtime != stmts.mtime:
|
||||
_log.debug("Re-parsing makefile '%s': mtimes differ", path)
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
_parsecache = util.MostUsedCache(15, _parsefile, _checktime)
|
||||
|
||||
def parsefile(pathname):
|
||||
"""
|
||||
@ -460,23 +475,7 @@ def parsefile(pathname):
|
||||
"""
|
||||
|
||||
pathname = os.path.realpath(pathname)
|
||||
|
||||
mtime = os.path.getmtime(pathname)
|
||||
|
||||
if pathname in _parsecache:
|
||||
oldmtime, stmts = _parsecache[pathname]
|
||||
|
||||
if mtime == oldmtime:
|
||||
_log.debug("Using '%s' from the parser cache.", pathname)
|
||||
return stmts
|
||||
|
||||
_log.debug("Not using '%s' from the parser cache, mtimes don't match: was %s, now %s", pathname, oldmtime, mtime)
|
||||
|
||||
fd = open(pathname, "rU")
|
||||
stmts = parsestream(fd, pathname)
|
||||
fd.close()
|
||||
_parsecache[pathname] = mtime, stmts
|
||||
return stmts
|
||||
return _parsecache.get(pathname)
|
||||
|
||||
def parsestream(fd, filename):
|
||||
"""
|
||||
|
@ -66,12 +66,15 @@ def _expandwildcards(makefile, tlist):
|
||||
for r in l:
|
||||
yield r
|
||||
|
||||
_flagescape = re.compile(r'([\s\\])')
|
||||
|
||||
def parsecommandlineargs(args):
|
||||
"""
|
||||
Given a set of arguments from a command-line invocation of make,
|
||||
parse out the variable definitions and return (stmts, arglist)
|
||||
parse out the variable definitions and return (stmts, arglist, overridestr)
|
||||
"""
|
||||
|
||||
overrides = []
|
||||
stmts = StatementList()
|
||||
r = []
|
||||
for i in xrange(0, len(args)):
|
||||
@ -81,7 +84,7 @@ def parsecommandlineargs(args):
|
||||
if t == '':
|
||||
vname, t, val = util.strpartition(a, '=')
|
||||
if t != '':
|
||||
stmts.append(Override(a))
|
||||
overrides.append(_flagescape.sub(r'\\\1', a))
|
||||
|
||||
vname = vname.strip()
|
||||
vnameexp = data.Expansion.fromstring(vname, "Command-line argument")
|
||||
@ -92,7 +95,7 @@ def parsecommandlineargs(args):
|
||||
else:
|
||||
r.append(a)
|
||||
|
||||
return stmts, r
|
||||
return stmts, r, ' '.join(overrides)
|
||||
|
||||
class Statement(object):
|
||||
"""
|
||||
@ -102,18 +105,6 @@ class Statement(object):
|
||||
def execute(self, makefile, context)
|
||||
"""
|
||||
|
||||
class Override(Statement):
|
||||
__slots__ = ('s',)
|
||||
|
||||
def __init__(self, s):
|
||||
self.s = s
|
||||
|
||||
def execute(self, makefile, context):
|
||||
makefile.overrides.append(self.s)
|
||||
|
||||
def dump(self, fd, indent):
|
||||
print >>fd, "%sOverride: %s" % (indent, self.s)
|
||||
|
||||
class DummyRule(object):
|
||||
__slots__ = ()
|
||||
|
||||
@ -470,8 +461,11 @@ class EmptyDirective(Statement):
|
||||
def dump(self, fd, indent):
|
||||
print >>fd, "%sEmptyDirective: %s" % (indent, self.exp)
|
||||
|
||||
class _EvalContext(object):
|
||||
__slots__ = ('currule',)
|
||||
|
||||
class StatementList(list):
|
||||
__slots__ = ()
|
||||
__slots__ = ('mtime',)
|
||||
|
||||
def append(self, statement):
|
||||
assert isinstance(statement, Statement)
|
||||
@ -479,7 +473,7 @@ class StatementList(list):
|
||||
|
||||
def execute(self, makefile, context=None):
|
||||
if context is None:
|
||||
context = util.makeobject('currule')
|
||||
context = _EvalContext()
|
||||
|
||||
for s in self:
|
||||
s.execute(makefile, context)
|
||||
|
@ -1,14 +1,5 @@
|
||||
import os
|
||||
|
||||
def makeobject(proplist, **kwargs):
|
||||
class P(object):
|
||||
__slots__ = proplist
|
||||
|
||||
p = P()
|
||||
for k, v in kwargs.iteritems():
|
||||
setattr(p, k, v)
|
||||
return p
|
||||
|
||||
class MakeError(Exception):
|
||||
def __init__(self, message, loc=None):
|
||||
self.message = message
|
||||
@ -87,3 +78,62 @@ except ImportError:
|
||||
if i:
|
||||
return True
|
||||
return False
|
||||
|
||||
class _MostUsedItem(object):
|
||||
__slots__ = ('key', 'o', 'count')
|
||||
|
||||
def __init__(self, key):
|
||||
self.key = key
|
||||
self.o = None
|
||||
self.count = 1
|
||||
|
||||
def __repr__(self):
|
||||
return "MostUsedItem(key=%r, count=%i, o=%r)" % (self.key, self.count, self.o)
|
||||
|
||||
class MostUsedCache(object):
|
||||
def __init__(self, capacity, creationfunc, verifyfunc):
|
||||
self.capacity = capacity
|
||||
self.cfunc = creationfunc
|
||||
self.vfunc = verifyfunc
|
||||
|
||||
self.d = {}
|
||||
self.active = [] # lazily sorted!
|
||||
|
||||
def setactive(self, item):
|
||||
if item in self.active:
|
||||
return
|
||||
|
||||
if len(self.active) == self.capacity:
|
||||
self.active.sort(key=lambda i: i.count)
|
||||
old = self.active.pop(0)
|
||||
old.o = None
|
||||
# print "Evicting %s" % old.key
|
||||
|
||||
self.active.append(item)
|
||||
|
||||
def get(self, key):
|
||||
item = self.d.get(key, None)
|
||||
if item is None:
|
||||
item = _MostUsedItem(key)
|
||||
self.d[key] = item
|
||||
else:
|
||||
item.count += 1
|
||||
|
||||
if item.o is not None and self.vfunc(key, item.o):
|
||||
return item.o
|
||||
|
||||
item.o = self.cfunc(key)
|
||||
self.setactive(item)
|
||||
return item.o
|
||||
|
||||
def verify(self):
|
||||
for k, v in self.d.iteritems():
|
||||
if v.o:
|
||||
assert v in self.active
|
||||
else:
|
||||
assert v not in self.active
|
||||
|
||||
def debugitems(self):
|
||||
l = [i.key for i in self.active]
|
||||
l.sort()
|
||||
return l
|
||||
|
@ -41,5 +41,38 @@ class GetPatSubstTest(unittest.TestCase):
|
||||
for word in words))
|
||||
self.assertEqual(a, e, 'Pattern(%r).subst(%r, %r)' % (s, r, d))
|
||||
|
||||
class LRUTest(unittest.TestCase):
|
||||
# getkey, expected, funccount, debugitems
|
||||
expected = (
|
||||
(0, '', 1, (0,)),
|
||||
(0, '', 2, (0,)),
|
||||
(1, ' ', 3, (1, 0)),
|
||||
(1, ' ', 3, (1, 0)),
|
||||
(0, '', 4, (0, 1)),
|
||||
(2, ' ', 5, (2, 0, 1)),
|
||||
(1, ' ', 5, (1, 2, 0)),
|
||||
(3, ' ', 6, (3, 1, 2)),
|
||||
)
|
||||
|
||||
def spaceFunc(self, l):
|
||||
self.funccount += 1
|
||||
return ''.ljust(l)
|
||||
|
||||
def runTest(self):
|
||||
self.funccount = 0
|
||||
c = pymake.util.LRUCache(3, self.spaceFunc, lambda k, v: k % 2)
|
||||
self.assertEqual(tuple(c.debugitems()), ())
|
||||
|
||||
for i in xrange(0, len(self.expected)):
|
||||
k, e, fc, di = self.expected[i]
|
||||
|
||||
v = c.get(k)
|
||||
self.assertEqual(v, e)
|
||||
self.assertEqual(self.funccount, fc,
|
||||
"funccount, iteration %i, got %i expected %i" % (i, self.funccount, fc))
|
||||
goti = tuple(c.debugitems())
|
||||
self.assertEqual(goti, di,
|
||||
"debugitems, iteration %i, got %r expected %r" % (i, goti, di))
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
16
build/pymake/tests/keep-going-doublecolon.mk
Normal file
@ -0,0 +1,16 @@
|
||||
#T commandline: ['-k']
|
||||
#T returncode: 2
|
||||
#T grep-for: "TEST-PASS"
|
||||
|
||||
all:: t1
|
||||
@echo TEST-FAIL "(t1)"
|
||||
|
||||
all:: t2
|
||||
@echo TEST-PASS
|
||||
|
||||
t1:
|
||||
@false
|
||||
|
||||
t2:
|
||||
touch $@
|
||||
|
11
build/pymake/tests/keep-going-parallel.mk
Normal file
@ -0,0 +1,11 @@
|
||||
#T commandline: ['-k', '-j2']
|
||||
#T returncode: 2
|
||||
#T grep-for: "TEST-PASS"
|
||||
|
||||
all: t1 slow1 slow2 slow3 t2
|
||||
|
||||
t2:
|
||||
@echo TEST-PASS
|
||||
|
||||
slow%:
|
||||
sleep 1
|
14
build/pymake/tests/keep-going.mk
Normal file
@ -0,0 +1,14 @@
|
||||
#T commandline: ['-k']
|
||||
#T returncode: 2
|
||||
#T grep-for: "TEST-PASS"
|
||||
|
||||
all: t2 t3
|
||||
|
||||
t1:
|
||||
@false
|
||||
|
||||
t2: t1
|
||||
@echo TEST-FAIL
|
||||
|
||||
t3:
|
||||
@echo TEST-PASS
|
6
build/pymake/tests/makeflags.mk
Normal file
@ -0,0 +1,6 @@
|
||||
#T environment: {'MAKEFLAGS': 'OVAR=oval'}
|
||||
|
||||
all:
|
||||
test "$(OVAR)" = "oval"
|
||||
@echo TEST-PASS
|
||||
|
32
build/pymake/tests/override-propagate.mk
Normal file
@ -0,0 +1,32 @@
|
||||
#T commandline: ['-w', 'OVAR=oval']
|
||||
|
||||
OVAR=mval
|
||||
|
||||
all: vartest run-override
|
||||
$(MAKE) -f $(TESTPATH)/override-propagate.mk vartest
|
||||
@echo TEST-PASS
|
||||
|
||||
SORTED_CLINE := $(sort OVAR=oval TESTPATH=$(TESTPATH) NATIVE_TESTPATH=$(NATIVE_TESTPATH))
|
||||
|
||||
vartest:
|
||||
@echo MAKELEVEL: '$(MAKELEVEL)'
|
||||
test '$(value MAKEFLAGS)' = 'w -- $$(MAKEOVERRIDES)'
|
||||
test '$(origin MAKEFLAGS)' = 'file'
|
||||
test '$(value MAKEOVERRIDES)' = '$${-*-command-variables-*-}'
|
||||
test "$(sort $(MAKEOVERRIDES))" = "$(SORTED_CLINE)"
|
||||
test '$(origin MAKEOVERRIDES)' = 'environment'
|
||||
test '$(origin -*-command-variables-*-)' = 'automatic'
|
||||
test "$(origin OVAR)" = "command line"
|
||||
test "$(OVAR)" = "oval"
|
||||
|
||||
run-override: MAKEOVERRIDES=
|
||||
run-override:
|
||||
test "$(OVAR)" = "oval"
|
||||
$(MAKE) -f $(TESTPATH)/override-propagate.mk otest
|
||||
|
||||
otest:
|
||||
test '$(value MAKEFLAGS)' = 'w'
|
||||
test '$(value MAKEOVERRIDES)' = '$${-*-command-variables-*-}'
|
||||
test '$(MAKEOVERRIDES)' = ''
|
||||
test '$(origin -*-command-variables-*-)' = 'undefined'
|
||||
test "$(OVAR)" = "mval"
|
@ -12,6 +12,7 @@ The test file may contain lines at the beginning to alter the default behavior.
|
||||
#T returncode: 2
|
||||
#T returncode-on: {'win32': 2}
|
||||
#T environment: {'VAR': 'VALUE}
|
||||
#T grep-for: "text"
|
||||
"""
|
||||
|
||||
from subprocess import Popen, PIPE, STDOUT
|
||||
@ -63,6 +64,7 @@ for makefile in makefiles:
|
||||
cline += ['__WIN32__=1']
|
||||
|
||||
returncode = 0
|
||||
grepfor = None
|
||||
|
||||
env = dict(os.environ)
|
||||
|
||||
@ -83,6 +85,8 @@ for makefile in makefiles:
|
||||
elif key == 'environment':
|
||||
for k, v in data.iteritems():
|
||||
env[k] = v
|
||||
elif key == 'grep-for':
|
||||
grepfor = data
|
||||
else:
|
||||
print >>sys.stderr, "Unexpected #T key: %s" % key
|
||||
sys.exit(1)
|
||||
@ -98,10 +102,17 @@ for makefile in makefiles:
|
||||
print "FAIL"
|
||||
print stdout
|
||||
elif returncode == 0:
|
||||
if stdout.find('TEST-PASS') != -1:
|
||||
if stdout.find(grepfor or 'TEST-PASS') != -1:
|
||||
print "PASS"
|
||||
else:
|
||||
print "FAIL (no passing output)"
|
||||
print "FAIL (no expected output)"
|
||||
print stdout
|
||||
# check that test produced the expected output while failing
|
||||
elif grepfor:
|
||||
if stdout.find(grepfor) != -1:
|
||||
print "PASS"
|
||||
else:
|
||||
print "FAIL (no expected output)"
|
||||
print stdout
|
||||
else:
|
||||
print "EXPECTED-FAIL"
|
||||
|
10
build/pymake/tests/simple-makeflags.mk
Normal file
@ -0,0 +1,10 @@
|
||||
# There once was a time when MAKEFLAGS=w without any following spaces would
|
||||
# cause us to treat w as a target, not a flag. Silly!
|
||||
|
||||
MAKEFLAGS=w
|
||||
|
||||
all:
|
||||
$(MAKE) -f $(TESTPATH)/simple-makeflags.mk subt
|
||||
@echo TEST-PASS
|
||||
|
||||
subt:
|
@ -70,11 +70,12 @@ DIRS += include/sys
|
||||
|
||||
ifdef MOZ_MEMORY
|
||||
REQUIRES = jemalloc
|
||||
JEMALLOC_LIB = $(DIST)/lib/jemalloc.lib
|
||||
CFLAGS += -DMOZ_MEMORY
|
||||
CXXFLAGS += -DMOZ_MEMORY
|
||||
endif
|
||||
|
||||
EXTRA_LIBS += $(JEMALLOC_LIBS)
|
||||
|
||||
CPPSRCS = map.cpp
|
||||
|
||||
DEFINES += -DMOZCE_SHUNT_EXPORTS
|
||||
|
@ -176,6 +176,9 @@ MOZCE_SHUNT_API int _unlink(const char *filename );
|
||||
|
||||
MOZCE_SHUNT_API unsigned short* mozce_GetEnvironmentCL();
|
||||
|
||||
/* square root of 1/2, missing from math.h */
|
||||
#define M_SQRT1_2 0.707106781186547524401
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
@ -80,9 +80,6 @@ main(int argc, char **argv)
|
||||
args[i++] = "/LIBPATH:\"" WCE_LIB "\"";
|
||||
args[i++] = "/LIBPATH:\"" WCE_CRT "\"";
|
||||
args[i++] = "/NODEFAULTLIB";
|
||||
#ifdef MOZ_MEMORY
|
||||
args[i++] = JEMALLOC_LIB;
|
||||
#endif
|
||||
#ifdef HAVE_SHUNT // simple test to see if we're in configure or not
|
||||
if(!getenv("NO_SHUNT")) {
|
||||
args[i++] = "/LIBPATH:\"" SHUNT_LIB "\"";
|
||||
|
@ -15,9 +15,6 @@ main(int argc, char **argv)
|
||||
args[i++] = "/LIBPATH:\"" WCE_CRT "\"";
|
||||
args[i++] = "/NODEFAULTLIB";
|
||||
|
||||
#ifdef MOZ_MEMORY
|
||||
args[i++] = JEMALLOC_LIB;
|
||||
#endif
|
||||
#ifdef HAVE_SHUNT // simple test to see if we're in configure or not
|
||||
if(getenv("NO_SHUNT") == NULL) {
|
||||
args[i++] = "/LIBPATH:\"" SHUNT_LIB "\"";
|
||||
|
@ -257,13 +257,11 @@ class JarMaker(object):
|
||||
if self.outputFormat == 'jar':
|
||||
#jar
|
||||
jarfilepath = jarfile + '.jar'
|
||||
if os.path.isfile(jarfilepath) and \
|
||||
os.path.getsize(jarfilepath) > 0:
|
||||
jf = ZipFile(jarfilepath, 'a', lock = True)
|
||||
else:
|
||||
if not os.path.isdir(os.path.dirname(jarfilepath)):
|
||||
os.makedirs(os.path.dirname(jarfilepath))
|
||||
jf = ZipFile(jarfilepath, 'w', lock = True)
|
||||
try:
|
||||
os.makedirs(os.path.dirname(jarfilepath))
|
||||
except OSError:
|
||||
pass
|
||||
jf = ZipFile(jarfilepath, 'a', lock = True)
|
||||
outHelper = self.OutputHelper_jar(jf)
|
||||
else:
|
||||
outHelper = getattr(self, 'OutputHelper_' + self.outputFormat)(jarfile)
|
||||
|
@ -39,9 +39,9 @@ import zipfile
|
||||
import time
|
||||
import binascii, struct
|
||||
import zlib
|
||||
import os
|
||||
from utils import lockFile
|
||||
|
||||
|
||||
class ZipFile(zipfile.ZipFile):
|
||||
""" Class with methods to open, read, write, close, list zip files.
|
||||
|
||||
@ -55,6 +55,13 @@ class ZipFile(zipfile.ZipFile):
|
||||
self.lockfile = lockFile(file + '.lck')
|
||||
else:
|
||||
self.lockfile = None
|
||||
|
||||
if mode == 'a' and lock:
|
||||
# appending to a file which doesn't exist fails, but we can't check
|
||||
# existence util we hold the lock
|
||||
if (not os.path.isfile(file)) or os.path.getsize(file) == 0:
|
||||
mode = 'w'
|
||||
|
||||
zipfile.ZipFile.__init__(self, file, mode, compression)
|
||||
self._remove = []
|
||||
self.end = self.fp.tell()
|
||||
|
@ -281,7 +281,7 @@ OS_LDFLAGS = @LDFLAGS@
|
||||
OS_COMPILE_CFLAGS = $(OS_CPPFLAGS) @COMPILE_CFLAGS@
|
||||
OS_COMPILE_CXXFLAGS = $(OS_CPPFLAGS) @COMPILE_CXXFLAGS@
|
||||
|
||||
OS_INCLUDES = $(NSPR_CFLAGS) $(JPEG_CFLAGS) $(PNG_CFLAGS) $(ZLIB_CFLAGS) $(LCMS_CFLAGS)
|
||||
OS_INCLUDES = $(NSPR_CFLAGS) $(JPEG_CFLAGS) $(PNG_CFLAGS) $(ZLIB_CFLAGS)
|
||||
OS_LIBS = @LIBS@
|
||||
ACDEFINES = @MOZ_DEFINES@
|
||||
|
||||
@ -389,6 +389,7 @@ TARGET_MD_ARCH = @TARGET_MD_ARCH@
|
||||
TARGET_XPCOM_ABI = @TARGET_XPCOM_ABI@
|
||||
|
||||
AUTOCONF = @AUTOCONF@
|
||||
GMAKE = @GMAKE@
|
||||
PERL = @PERL@
|
||||
PYTHON = @PYTHON@
|
||||
RANLIB = @RANLIB@
|
||||
@ -447,9 +448,7 @@ PNG_LIBS = @MOZ_PNG_LIBS@
|
||||
PNG_REQUIRES = png
|
||||
endif
|
||||
|
||||
LCMS_CFLAGS = @LCMS_CFLAGS@
|
||||
LCMS_LIBS = @LCMS_LIBS@
|
||||
LCMS_REQUIRES = lcms
|
||||
QCMS_LIBS = @QCMS_LIBS@
|
||||
|
||||
MOZ_NATIVE_SQLITE = @MOZ_NATIVE_SQLITE@
|
||||
SQLITE_CFLAGS = @SQLITE_CFLAGS@
|
||||
@ -655,4 +654,5 @@ MOZ_EMBEDDING_LEVEL_DEFAULT = @MOZ_EMBEDDING_LEVEL_DEFAULT@
|
||||
MOZ_EMBEDDING_LEVEL_BASIC = @MOZ_EMBEDDING_LEVEL_BASIC@
|
||||
MOZ_EMBEDDING_LEVEL_MINIMAL = @MOZ_EMBEDDING_LEVEL_MINIMAL@
|
||||
|
||||
HAVE_ARM_SIMD= @HAVE_ARM_SIMD@
|
||||
HAVE_ARM_SIMD = @HAVE_ARM_SIMD@
|
||||
HAVE_ARM_NEON = @HAVE_ARM_NEON@
|
||||
|
@ -56,16 +56,10 @@ $(error config/nspr/Makefile.in is not compatible with MOZ_NATIVE_NSPR)
|
||||
endif
|
||||
|
||||
# Copy NSPR to the SDK
|
||||
ABS_DIST = cd $(DIST) && pwd
|
||||
ifeq (,$(CROSS_COMPILE)$(filter-out WINNT,$(OS_ARCH))) # {
|
||||
ifdef CYGDRIVE_MOUNT # {
|
||||
ABS_DIST = cygpath -w $(DIST) | sed -e 's|\\\\|/|g'
|
||||
endif # }
|
||||
endif # }
|
||||
ABS_DIST = $(call core_abspath,$(DIST))
|
||||
|
||||
libs::
|
||||
_ABS_DIST=`$(ABS_DIST)`; \
|
||||
$(MAKE) -C $(DEPTH)/nsprpub install prefix=$$_ABS_DIST/sdk exec_prefix=$$_ABS_DIST/sdk bindir=$$_ABS_DIST/sdk/dummy includedir=$$_ABS_DIST/sdk/include libdir=$$_ABS_DIST/sdk/lib datadir=$$_ABS_DIST/sdk/dummy DESTDIR=
|
||||
$(MAKE) -C $(DEPTH)/nsprpub install prefix=$(ABS_DIST)/sdk exec_prefix=$(ABS_DIST)/sdk bindir=$(ABS_DIST)/sdk/dummy includedir=$(ABS_DIST)/sdk/include libdir=$(ABS_DIST)/sdk/lib datadir=$(ABS_DIST)/sdk/dummy DESTDIR=
|
||||
$(RM) -rf $(DIST)/sdk/dummy
|
||||
ifneq (,$(filter OS2 WINNT,$(OS_ARCH))) # {
|
||||
$(RM) -f $(DIST)/sdk/lib/$(DLL_PREFIX)nspr4$(DLL_SUFFIX) $(DIST)/sdk/lib/$(DLL_PREFIX)plc4$(DLL_SUFFIX) $(DIST)/sdk/lib/$(DLL_PREFIX)plds4$(DLL_SUFFIX)
|
||||
|