Merge mozilla-central to tracemonkey.

This commit is contained in:
Robert Sayre 2009-04-07 19:04:17 -04:00
commit 51f43ccd72
1130 changed files with 48785 additions and 13559 deletions

View File

@ -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)

View File

@ -51,7 +51,8 @@
#include "nsISelection2.h"
#include "nsServiceManagerUtils.h"
#include "nsIViewManager.h"
#include "nsIWidget.h"
class nsIWidget;
NS_IMPL_ISUPPORTS1(nsCaretAccessible, nsISelectionListener)

View File

@ -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

View File

@ -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);

View File

@ -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 \

View File

@ -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

View File

@ -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

View File

@ -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) {

View File

@ -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");

View File

@ -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++;

View File

@ -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 \

View 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);
}

View File

@ -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

View File

@ -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

View File

@ -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);
},

View File

@ -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) {

View File

@ -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 =

View File

@ -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]) {

View File

@ -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"/>

View File

@ -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"

View File

@ -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,

View File

@ -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)

View File

@ -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);
}

View File

@ -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!

View File

@ -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);
}

View File

@ -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();
});
});
}

View File

@ -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)

View File

@ -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>

View File

@ -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;
}

View File

@ -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();

View File

@ -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();

View File

@ -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"].

View File

@ -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)

View File

@ -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();
});
});
});
}

View File

@ -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;

View File

@ -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();
}

View File

@ -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.

View File

@ -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");
},
/**

View File

@ -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 \

View 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);
}

View File

@ -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;
}

View File

@ -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 \

View File

@ -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)

View File

@ -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.

View File

@ -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

View File

@ -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">

Binary file not shown.

Before

Width:  |  Height:  |  Size: 757 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 862 B

View File

@ -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;
}

View File

@ -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

View File

@ -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"] {

View File

@ -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 {

View File

@ -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

View File

@ -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;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 941 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 585 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 246 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 897 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 584 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 248 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 908 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -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;

View File

@ -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

View File

@ -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 {

View File

@ -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

View File

@ -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!")

View File

@ -1,2 +1,2 @@
repo: f5ab154deef2ffa97f1b2139589ae4a1962090a4
node: c07f9fe9fdaa85888314efa7001cd4fd768904c4
node: 162a3b79a8b0799a9fb3c2aed909a3d09f6f1d39

View File

@ -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"

View File

@ -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:

View File

@ -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

View File

@ -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)

View File

@ -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):
"""

View File

@ -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)

View File

@ -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

View File

@ -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()

View 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 $@

View 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

View 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

View File

@ -0,0 +1,6 @@
#T environment: {'MAKEFLAGS': 'OVAR=oval'}
all:
test "$(OVAR)" = "oval"
@echo TEST-PASS

View 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"

View File

@ -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"

View 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:

View File

@ -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

View File

@ -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

View File

@ -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 "\"";

View File

@ -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 "\"";

View File

@ -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)

View File

@ -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()

View File

@ -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@

View File

@ -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)

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