Merge mozilla-central into mozilla-inbound

This commit is contained in:
Ehsan Akhgari 2012-12-06 13:13:33 -05:00
Родитель 074d23a851 9360dba19d
Коммит 629d8a0ae2
20 изменённых файлов: 768 добавлений и 142 удалений

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

@ -44,6 +44,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "DownloadUtils",
"resource://gre/modules/DownloadUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "DownloadsCommon",
"resource:///modules/DownloadsCommon.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
"resource://gre/modules/PrivateBrowsingUtils.jsm");
////////////////////////////////////////////////////////////////////////////////
//// DownloadsPanel
@ -107,7 +109,7 @@ const DownloadsPanel = {
DownloadsOverlayLoader.ensureOverlayLoaded(this.kDownloadsOverlay,
function DP_I_callback() {
DownloadsViewController.initialize();
DownloadsCommon.data.addView(DownloadsView);
DownloadsCommon.getData(window).addView(DownloadsView);
DownloadsPanel._attachEventListeners();
aCallback();
});
@ -130,7 +132,7 @@ const DownloadsPanel = {
this.hidePanel();
DownloadsViewController.terminate();
DownloadsCommon.data.removeView(DownloadsView);
DownloadsCommon.getData(window).removeView(DownloadsView);
this._unattachEventListeners();
this._state = this.kStateUninitialized;
@ -230,7 +232,7 @@ const DownloadsPanel = {
this._state = this.kStateShown;
// Since at most one popup is open at any given time, we can set globally.
DownloadsCommon.indicatorData.attentionSuppressed = true;
DownloadsCommon.getIndicatorData(window).attentionSuppressed = true;
// Ensure that an item is selected when the panel is focused.
if (DownloadsView.richListBox.itemCount > 0 &&
@ -249,7 +251,7 @@ const DownloadsPanel = {
}
// Since at most one popup is open at any given time, we can set globally.
DownloadsCommon.indicatorData.attentionSuppressed = false;
DownloadsCommon.getIndicatorData(window).attentionSuppressed = false;
// Allow the anchor to be hidden.
DownloadsButton.releaseAnchor();
@ -1110,7 +1112,11 @@ const DownloadsViewController = {
{
// Handle commands that are not selection-specific.
if (aCommand == "downloadsCmd_clearList") {
return Services.downloads.canCleanUp;
if (PrivateBrowsingUtils.isWindowPrivate(window)) {
return Services.downloads.canCleanUpPrivate;
} else {
return Services.downloads.canCleanUp;
}
}
// Other commands are selection-specific.
@ -1157,7 +1163,11 @@ const DownloadsViewController = {
commands: {
downloadsCmd_clearList: function DVC_downloadsCmd_clearList()
{
Services.downloads.cleanUp();
if (PrivateBrowsingUtils.isWindowPrivate(window)) {
Services.downloads.cleanUpPrivate();
} else {
Services.downloads.cleanUp();
}
}
}
};
@ -1171,7 +1181,7 @@ const DownloadsViewController = {
*/
function DownloadsViewItemController(aElement) {
let downloadGuid = aElement.getAttribute("downloadGuid");
this.dataItem = DownloadsCommon.data.dataItems[downloadGuid];
this.dataItem = DownloadsCommon.getData(window).dataItems[downloadGuid];
}
DownloadsViewItemController.prototype = {
@ -1457,10 +1467,10 @@ const DownloadsSummary = {
return this._active;
}
if (aActive) {
DownloadsCommon.getSummary(DownloadsView.kItemCountLimit)
DownloadsCommon.getSummary(window, DownloadsView.kItemCountLimit)
.addView(this);
} else {
DownloadsCommon.getSummary(DownloadsView.kItemCountLimit)
DownloadsCommon.getSummary(window, DownloadsView.kItemCountLimit)
.removeView(this);
DownloadsFooter.showingSummary = false;
}

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

@ -286,7 +286,7 @@ const DownloadsIndicatorView = {
this._initialized = true;
window.addEventListener("unload", this.onWindowUnload, false);
DownloadsCommon.indicatorData.addView(this);
DownloadsCommon.getIndicatorData(window).addView(this);
},
/**
@ -300,7 +300,7 @@ const DownloadsIndicatorView = {
this._initialized = false;
window.removeEventListener("unload", this.onWindowUnload, false);
DownloadsCommon.indicatorData.removeView(this);
DownloadsCommon.getIndicatorData(window).removeView(this);
// Reset the view properties, so that a neutral indicator is displayed if we
// are visible only temporarily as an anchor.
@ -327,7 +327,7 @@ const DownloadsIndicatorView = {
// If the view is initialized, we need to update the elements now that
// they are finally available in the document.
if (this._initialized) {
DownloadsCommon.indicatorData.refreshView(this);
DownloadsCommon.getIndicatorData(window).refreshView(this);
}
aCallback();
@ -508,7 +508,7 @@ const DownloadsIndicatorView = {
{
if (DownloadsCommon.useToolkitUI) {
// The panel won't suppress attention for us, we need to clear now.
DownloadsCommon.indicatorData.attention = false;
DownloadsCommon.getIndicatorData(window).attention = false;
BrowserDownloadsUI();
} else {
DownloadsPanel.showPanel();

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

@ -56,6 +56,10 @@ XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
"resource://gre/modules/PluralForm.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "DownloadUtils",
"resource://gre/modules/DownloadUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
"resource://gre/modules/PrivateBrowsingUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "RecentWindow",
"resource:///modules/RecentWindow.jsm");
const nsIDM = Ci.nsIDownloadManager;
@ -173,37 +177,95 @@ this.DownloadsCommon = {
},
/**
* Returns a reference to the DownloadsData singleton.
* Get access to one of the DownloadsData or PrivateDownloadsData objects,
* depending on the privacy status of the window in question.
*
* This does not need to be a lazy getter, since no initialization is required
* at present.
* @param aWindow
* The browser window which owns the download button.
*/
get data() DownloadsData,
getData: function DC_getData(aWindow) {
if (PrivateBrowsingUtils.isWindowPrivate(aWindow)) {
return PrivateDownloadsData;
} else {
return DownloadsData;
}
},
/**
* Returns a reference to the DownloadsData singleton.
* Initializes the data link for both the private and non-private downloads
* data objects.
*
* This does not need to be a lazy getter, since no initialization is required
* at present.
* @param aDownloadManagerService
* Reference to the service implementing nsIDownloadManager. We need
* this because getService isn't available for us when this method is
* called, and we must ensure to register our listeners before the
* getService call for the Download Manager returns.
*/
get indicatorData() DownloadsIndicatorData,
initializeAllDataLinks: function DC_initializeAllDataLinks(aDownloadManagerService) {
DownloadsData.initializeDataLink(aDownloadManagerService);
PrivateDownloadsData.initializeDataLink(aDownloadManagerService);
},
/**
* Terminates the data link for both the private and non-private downloads
* data objects.
*/
terminateAllDataLinks: function DC_terminateAllDataLinks() {
DownloadsData.terminateDataLink();
PrivateDownloadsData.terminateDataLink();
},
/**
* Reloads the specified kind of downloads from the non-private store.
* This method must only be called when Private Browsing Mode is disabled.
*
* @param aActiveOnly
* True to load only active downloads from the database.
*/
ensureAllPersistentDataLoaded:
function DC_ensureAllPersistentDataLoaded(aActiveOnly) {
DownloadsData.ensurePersistentDataLoaded(aActiveOnly);
},
/**
* Get access to one of the DownloadsIndicatorData or
* PrivateDownloadsIndicatorData objects, depending on the privacy status of
* the window in question.
*/
getIndicatorData: function DC_getIndicatorData(aWindow) {
if (PrivateBrowsingUtils.isWindowPrivate(aWindow)) {
return PrivateDownloadsIndicatorData;
} else {
return DownloadsIndicatorData;
}
},
/**
* Returns a reference to the DownloadsSummaryData singleton - creating one
* in the process if one hasn't been instantiated yet.
*
* @param aWindow
* The browser window which owns the download button.
* @param aNumToExclude
* The number of items on the top of the downloads list to exclude
* from the summary.
*/
_summary: null,
getSummary: function DC_getSummary(aNumToExclude)
getSummary: function DC_getSummary(aWindow, aNumToExclude)
{
if (this._summary) {
return this._summary;
if (PrivateBrowsingUtils.isWindowPrivate(aWindow)) {
if (this._privateSummary) {
return this._privateSummary;
}
return this._privateSummary = new DownloadsSummaryData(true, aNumToExclude);
} else {
if (this._summary) {
return this._summary;
}
return this._summary = new DownloadsSummaryData(false, aNumToExclude);
}
return this._summary = new DownloadsSummaryData(aNumToExclude);
},
_summary: null,
_privateSummary: null,
/**
* Given an iterable collection of DownloadDataItems, generates and returns
@ -354,8 +416,33 @@ XPCOMUtils.defineLazyGetter(DownloadsCommon, "isWinVistaOrHigher", function () {
* service. Consumers will see an empty list of downloads until the service is
* actually started. This is useful to display a neutral progress indicator in
* the main browser window until the autostart timeout elapses.
*
* Note that DownloadsData and PrivateDownloadsData are two equivalent singleton
* objects, one accessing non-private downloads, and the other accessing private
* ones.
*/
const DownloadsData = {
function DownloadsDataCtor(aPrivate) {
this._isPrivate = aPrivate;
// This Object contains all the available DownloadsDataItem objects, indexed by
// their globally unique identifier. The identifiers of downloads that have
// been removed from the Download Manager data are still present, however the
// associated objects are replaced with the value "null". This is required to
// prevent race conditions when populating the list asynchronously.
this.dataItems = {};
#ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
// While operating in Private Browsing Mode, persistent data items are parked
// here until we return to the normal mode.
this._persistentDataItems = {};
#endif
// Array of view objects that should be notified when the available download
// data changes.
this._views = [];
}
DownloadsDataCtor.prototype = {
/**
* Starts receiving events for current downloads.
*
@ -368,10 +455,12 @@ const DownloadsData = {
initializeDataLink: function DD_initializeDataLink(aDownloadManagerService)
{
// Start receiving real-time events.
aDownloadManagerService.addListener(this);
aDownloadManagerService.addPrivacyAwareListener(this);
Services.obs.addObserver(this, "download-manager-remove-download-guid", false);
#ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
Services.obs.addObserver(this, "download-manager-database-type-changed",
false);
#endif
},
/**
@ -382,7 +471,9 @@ const DownloadsData = {
this._terminateDataAccess();
// Stop receiving real-time events.
#ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
Services.obs.removeObserver(this, "download-manager-database-type-changed");
#endif
Services.obs.removeObserver(this, "download-manager-remove-download-guid");
Services.downloads.removeListener(this);
},
@ -390,12 +481,6 @@ const DownloadsData = {
//////////////////////////////////////////////////////////////////////////////
//// Registration of views
/**
* Array of view objects that should be notified when the available download
* data changes.
*/
_views: [],
/**
* Adds an object to be notified when the available download data changes.
* The specified object is initialized with the currently available downloads.
@ -454,21 +539,6 @@ const DownloadsData = {
//////////////////////////////////////////////////////////////////////////////
//// In-memory downloads data store
/**
* Object containing all the available DownloadsDataItem objects, indexed by
* their numeric download identifier. The identifiers of downloads that have
* been removed from the Download Manager data are still present, however the
* associated objects are replaced with the value "null". This is required to
* prevent race conditions when populating the list asynchronously.
*/
dataItems: {},
/**
* While operating in Private Browsing Mode, persistent data items are parked
* here until we return to the normal mode.
*/
_persistentDataItems: {},
/**
* Clears the loaded data.
*/
@ -591,7 +661,9 @@ const DownloadsData = {
// Reload the list using the Download Manager service. The list is
// returned in no particular order.
let downloads = Services.downloads.activeDownloads;
let downloads = this._isPrivate ?
Services.downloads.activePrivateDownloads :
Services.downloads.activeDownloads;
while (downloads.hasMoreElements()) {
let download = downloads.getNext().QueryInterface(Ci.nsIDownload);
this._getOrAddDataItem(download, true);
@ -609,7 +681,10 @@ const DownloadsData = {
// columns are read in the _initFromDataRow method of DownloadsDataItem.
// Order by descending download identifier so that the most recent
// downloads are notified first to the listening views.
let statement = Services.downloads.DBConnection.createAsyncStatement(
let dbConnection = this._isPrivate ?
Services.downloads.privateDBConnection :
Services.downloads.DBConnection;
let statement = dbConnection.createAsyncStatement(
"SELECT guid, target, name, source, referrer, state, "
+ "startTime, endTime, currBytes, maxBytes "
+ "FROM moz_downloads "
@ -714,6 +789,7 @@ const DownloadsData = {
}
break;
#ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
case "download-manager-database-type-changed":
let pbs = Cc["@mozilla.org/privatebrowsing;1"]
.getService(Ci.nsIPrivateBrowsingService);
@ -731,6 +807,7 @@ const DownloadsData = {
// already invalidated by the previous calls.
this._views.forEach(this._updateView, this);
break;
#endif
}
},
@ -739,6 +816,12 @@ const DownloadsData = {
onDownloadStateChange: function DD_onDownloadStateChange(aState, aDownload)
{
if (aDownload.isPrivate != this._isPrivate) {
// Ignore the downloads with a privacy status other than what we are
// tracking.
return;
}
// When a new download is added, it may have the same identifier of a
// download that we previously deleted during this session, and we also
// want to provide a visible indication that the download started.
@ -784,6 +867,12 @@ const DownloadsData = {
aCurTotalProgress,
aMaxTotalProgress, aDownload)
{
if (aDownload.isPrivate != this._isPrivate) {
// Ignore the downloads with a privacy status other than what we are
// tracking.
return;
}
let dataItem = this._getOrAddDataItem(aDownload, false);
if (!dataItem) {
return;
@ -833,7 +922,7 @@ const DownloadsData = {
}
// Show the panel in the most recent browser window, if present.
let browserWin = gBrowserGlue.getMostRecentBrowserWindow();
let browserWin = RecentWindow.getMostRecentBrowserWindow({ private: this._isPrivate });
if (!browserWin) {
return;
}
@ -850,6 +939,14 @@ const DownloadsData = {
}
};
XPCOMUtils.defineLazyGetter(this, "PrivateDownloadsData", function() {
return new DownloadsDataCtor(true);
});
XPCOMUtils.defineLazyGetter(this, "DownloadsData", function() {
return new DownloadsDataCtor(false);
});
////////////////////////////////////////////////////////////////////////////////
//// DownloadsDataItem
@ -1116,8 +1213,18 @@ const DownloadsViewPrototype = {
/**
* Array of view objects that should be notified when the available status
* data changes.
*
* SUBCLASSES MUST OVERRIDE THIS PROPERTY.
*/
_views: [],
_views: null,
/**
* Determines whether this view object is over the private or non-private
* downloads.
*
* SUBCLASSES MUST OVERRIDE THIS PROPERTY.
*/
_isPrivate: false,
/**
* Adds an object to be notified when the available status data changes.
@ -1131,7 +1238,11 @@ const DownloadsViewPrototype = {
{
// Start receiving events when the first of our views is registered.
if (this._views.length == 0) {
DownloadsCommon.data.addView(this);
if (this._isPrivate) {
PrivateDownloadsData.addView(this);
} else {
DownloadsData.addView(this);
}
}
this._views.push(aView);
@ -1167,7 +1278,11 @@ const DownloadsViewPrototype = {
// Stop receiving events when the last of our views is unregistered.
if (this._views.length == 0) {
DownloadsCommon.data.removeView(this);
if (this._isPrivate) {
PrivateDownloadsData.removeView(this);
} else {
DownloadsData.removeView(this);
}
}
},
@ -1291,7 +1406,10 @@ const DownloadsViewPrototype = {
* actually started. This is useful to display a neutral progress indicator in
* the main browser window until the autostart timeout elapses.
*/
const DownloadsIndicatorData = {
function DownloadsIndicatorDataCtor(aPrivate) {
this._isPrivate = aPrivate;
}
DownloadsIndicatorDataCtor.prototype = {
__proto__: DownloadsViewPrototype,
/**
@ -1373,23 +1491,25 @@ const DownloadsIndicatorData = {
*/
getViewItem: function DID_getViewItem(aDataItem)
{
let data = this._isPrivate ? PrivateDownloadsIndicatorData
: DownloadsIndicatorData;
return Object.freeze({
onStateChange: function DIVI_onStateChange()
{
if (aDataItem.state == nsIDM.DOWNLOAD_FINISHED ||
aDataItem.state == nsIDM.DOWNLOAD_FAILED) {
DownloadsIndicatorData.attention = true;
data.attention = true;
}
// Since the state of a download changed, reset the estimated time left.
DownloadsIndicatorData._lastRawTimeLeft = -1;
DownloadsIndicatorData._lastTimeLeft = -1;
data._lastRawTimeLeft = -1;
data._lastTimeLeft = -1;
DownloadsIndicatorData._updateViews();
data._updateViews();
},
onProgressChange: function DIVI_onProgressChange()
{
DownloadsIndicatorData._updateViews();
data._updateViews();
}
});
},
@ -1489,7 +1609,9 @@ const DownloadsIndicatorData = {
*/
_activeDataItems: function DID_activeDataItems()
{
for each (let dataItem in DownloadsCommon.data.dataItems) {
let dataItems = this._isPrivate ? PrivateDownloadsData.dataItems
: DownloadsData.dataItems;
for each (let dataItem in dataItems) {
if (dataItem && dataItem.inProgress) {
yield dataItem;
}
@ -1529,7 +1651,15 @@ const DownloadsIndicatorData = {
this._counter = DownloadsCommon.formatTimeLeft(this._lastTimeLeft);
}
}
}
};
XPCOMUtils.defineLazyGetter(this, "PrivateDownloadsIndicatorData", function() {
return new DownloadsIndicatorDataCtor(true);
});
XPCOMUtils.defineLazyGetter(this, "DownloadsIndicatorData", function() {
return new DownloadsIndicatorDataCtor(false);
});
////////////////////////////////////////////////////////////////////////////////
//// DownloadsSummaryData
@ -1541,16 +1671,18 @@ const DownloadsIndicatorData = {
* constructed with aNumToExclude equal to 3, then that DownloadsSummaryData
* would produce a summary of the last 2 downloads.
*
* @param aIsPrivate
* True if the browser window which owns the download button is a private
* window.
* @param aNumToExclude
* The number of items to exclude from the summary, starting from the
* top of the list.
*/
function DownloadsSummaryData(aNumToExclude) {
function DownloadsSummaryData(aIsPrivate, aNumToExclude) {
this._numToExclude = aNumToExclude;
// Since we can have multiple instances of DownloadsSummaryData, we
// override these values from the prototype so that each instance can be
// completely separated from one another.
this._views = [];
this._loading = false;
this._dataItems = [];
@ -1574,6 +1706,9 @@ function DownloadsSummaryData(aNumToExclude) {
this._description = "";
this._numActive = 0;
this._percentComplete = -1;
this._isPrivate = aIsPrivate;
this._views = [];
}
DownloadsSummaryData.prototype = {

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

@ -31,16 +31,22 @@ XPCOMUtils.defineLazyModuleGetter(this, "DownloadsCommon",
XPCOMUtils.defineLazyServiceGetter(this, "gSessionStartup",
"@mozilla.org/browser/sessionstartup;1",
"nsISessionStartup");
#ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
XPCOMUtils.defineLazyServiceGetter(this, "gPrivateBrowsingService",
"@mozilla.org/privatebrowsing;1",
"nsIPrivateBrowsingService");
#endif
const kObservedTopics = [
"sessionstore-windows-restored",
"sessionstore-browser-state-restored",
"download-manager-initialized",
"download-manager-change-retention",
#ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING
"last-pb-context-exited",
#else
"private-browsing-transition-complete",
#endif
"browser-lastwindow-close-granted",
"quit-application",
"profile-change-teardown",
@ -113,8 +119,8 @@ DownloadsStartup.prototype = {
// Start receiving events for active and new downloads before we return
// from this observer function. We can't defer the execution of this
// step, to ensure that we don't lose events raised in the meantime.
DownloadsCommon.data.initializeDataLink(
aSubject.QueryInterface(Ci.nsIDownloadManager));
DownloadsCommon.initializeAllDataLinks(
aSubject.QueryInterface(Ci.nsIDownloadManager));
this._downloadsServiceInitialized = true;
@ -139,11 +145,13 @@ DownloadsStartup.prototype = {
}
break;
#ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
case "private-browsing-transition-complete":
// Ensure that persistent data is reloaded only when the database
// connection is available again.
this._ensureDataLoaded();
break;
#endif
case "browser-lastwindow-close-granted":
// When using the panel interface, downloads that are already completed
@ -158,6 +166,16 @@ DownloadsStartup.prototype = {
}
break;
#ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING
case "last-pb-context-exited":
// Similar to the above notification, but for private downloads.
if (this._downloadsServiceInitialized &&
!DownloadsCommon.useToolkitUI) {
Services.downloads.cleanUpPrivate();
}
break;
#endif
case "quit-application":
// When the application is shutting down, we must free all resources in
// addition to cleaning up completed downloads. If the Download Manager
@ -169,7 +187,7 @@ DownloadsStartup.prototype = {
break;
}
DownloadsCommon.data.terminateDataLink();
DownloadsCommon.terminateAllDataLinks();
// When using the panel interface, downloads that are already completed
// should be removed when quitting the application.
@ -258,15 +276,18 @@ DownloadsStartup.prototype = {
*/
_ensureDataLoaded: function DS_ensureDataLoaded()
{
if (!this._downloadsServiceInitialized ||
gPrivateBrowsingService.privateBrowsingEnabled) {
if (!this._downloadsServiceInitialized
#ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
|| gPrivateBrowsingService.privateBrowsingEnabled
#endif
) {
return;
}
// If the previous session has been already restored, then we ensure that
// all the downloads are loaded. Otherwise, we only ensure that the active
// downloads from the previous session are loaded.
DownloadsCommon.data.ensurePersistentDataLoaded(!this._recoverAllDownloads);
DownloadsCommon.ensureAllPersistentDataLoaded(!this._recoverAllDownloads);
}
};

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

@ -11,11 +11,14 @@ include $(DEPTH)/config/autoconf.mk
EXTRA_COMPONENTS = \
BrowserDownloads.manifest \
DownloadsStartup.js \
DownloadsUI.js \
$(NULL)
EXTRA_JS_MODULES = \
EXTRA_PP_COMPONENTS = \
DownloadsStartup.js \
$(NULL)
EXTRA_PP_JS_MODULES = \
DownloadsCommon.jsm \
$(NULL)

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

@ -33,13 +33,13 @@ function gen_test()
try {
// Ensure that state is reset in case previous tests didn't finish.
for (let yy in gen_resetState()) yield;
for (let yy in gen_resetState(DownloadsCommon.getData(window))) yield;
// Populate the downloads database with the data required by this test.
for (let yy in gen_addDownloadRows(DownloadData)) yield;
// Open the user interface and wait for data to be fully loaded.
for (let yy in gen_openPanel()) yield;
for (let yy in gen_openPanel(DownloadsCommon.getData(window))) yield;
// Test item data and count. This also tests the ordering of the display.
let richlistbox = document.getElementById("downloadsListBox");
@ -57,6 +57,6 @@ function gen_test()
}
} finally {
// Clean up when the test finishes.
for (let yy in gen_resetState()) yield;
for (let yy in gen_resetState(DownloadsCommon.getData(window))) yield;
}
}

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

@ -12,32 +12,32 @@ function gen_test()
{
try {
// Ensure that state is reset in case previous tests didn't finish.
for (let yy in gen_resetState()) yield;
for (let yy in gen_resetState(DownloadsCommon.getData(window))) yield;
// With this set to false, we should automatically open the panel
// the first time a download is started.
DownloadsCommon.data.panelHasShownBefore = false;
DownloadsCommon.getData(window).panelHasShownBefore = false;
prepareForPanelOpen();
DownloadsCommon.data._notifyNewDownload();
DownloadsCommon.getData(window)._notifyNewDownload();
yield;
// If we got here, that means the panel opened.
DownloadsPanel.hidePanel();
ok(DownloadsCommon.data.panelHasShownBefore,
ok(DownloadsCommon.getData(window).panelHasShownBefore,
"Should have recorded that the panel was opened on a download.")
// Next, make sure that if we start another download, we don't open
// the panel automatically.
panelShouldNotOpen();
DownloadsCommon.data._notifyNewDownload();
DownloadsCommon.getData(window)._notifyNewDownload();
yield waitFor(2);
} catch(e) {
ok(false, e);
} finally {
// Clean up when the test finishes.
for (let yy in gen_resetState()) yield;
for (let yy in gen_resetState(DownloadsCommon.getData(window))) yield;
}
}

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

@ -130,7 +130,7 @@ var testRunner = {
// for (let yy in gen_example("Parameter")) yield;
//
function gen_resetState()
function gen_resetState(aData)
{
let statement = Services.downloads.DBConnection.createAsyncStatement(
"DELETE FROM moz_downloads");
@ -155,8 +155,8 @@ function gen_resetState()
Services.prefs.clearUserPref("browser.download.panel.shown");
// Ensure that the panel is closed and data is unloaded.
DownloadsCommon.data.clear();
DownloadsCommon.data._loadState = DownloadsCommon.data.kLoadNone;
aData.clear();
aData._loadState = aData.kLoadNone;
DownloadsPanel.hidePanel();
// Wait for focus on the main window.
@ -224,7 +224,7 @@ function gen_openPanel(aData)
};
// Start loading all the downloads from the database asynchronously.
DownloadsCommon.data.ensurePersistentDataLoaded(false);
aData.ensurePersistentDataLoaded(false);
// Wait for focus on the main window.
waitForFocus(testRunner.continueTest);

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

@ -53,6 +53,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
XPCOMUtils.defineLazyModuleGetter(this, "KeywordURLResetPrompter",
"resource:///modules/KeywordURLResetPrompter.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "RecentWindow",
"resource:///modules/RecentWindow.jsm");
const PREF_PLUGINS_NOTIFYUSER = "plugins.update.notifyUser";
const PREF_PLUGINS_UPDATEURL = "plugins.update.url";
@ -1584,41 +1587,9 @@ BrowserGlue.prototype = {
}
},
#ifndef XP_WIN
#define BROKEN_WM_Z_ORDER
#endif
// this returns the most recent non-popup browser window
getMostRecentBrowserWindow: function BG_getMostRecentBrowserWindow() {
function isFullBrowserWindow(win) {
return !win.closed &&
win.toolbar.visible;
}
#ifdef BROKEN_WM_Z_ORDER
var win = Services.wm.getMostRecentWindow("navigator:browser");
// if we're lucky, this isn't a popup, and we can just return this
if (win && !isFullBrowserWindow(win)) {
win = null;
let windowList = Services.wm.getEnumerator("navigator:browser");
// this is oldest to newest, so this gets a bit ugly
while (windowList.hasMoreElements()) {
let nextWin = windowList.getNext();
if (isFullBrowserWindow(nextWin))
win = nextWin;
}
}
return win;
#else
var windowList = Services.wm.getZOrderDOMWindowEnumerator("navigator:browser", true);
while (windowList.hasMoreElements()) {
let win = windowList.getNext();
if (isFullBrowserWindow(win))
return win;
}
return null;
#endif
return RecentWindow.getMostRecentBrowserWindow();
},
#ifdef MOZ_SERVICES_SYNC

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

@ -28,11 +28,13 @@ EXTRA_JS_MODULES = \
KeywordURLResetPrompter.jsm \
$(NULL)
EXTRA_PP_JS_MODULES = RecentWindow.jsm
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
EXTRA_JS_MODULES += \
WindowsPreviewPerTab.jsm \
$(NULL)
EXTRA_PP_JS_MODULES = \
EXTRA_PP_JS_MODULES += \
WindowsJumpLists.jsm \
$(NULL)
endif

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

@ -0,0 +1,65 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
this.EXPORTED_SYMBOLS = ["RecentWindow"];
const Cu = Components.utils;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
#ifndef XP_WIN
#define BROKEN_WM_Z_ORDER
#endif
this.RecentWindow = {
/*
* Get the most recent browser window.
*
* @param aOptions an object accepting the arguments for the search.
* Set the private property to true in order to restrict the
* search to private windows only, or to false in order to
* restrict the search to non-private windows only. To search
* in both groups, don't specify the private property.
*/
getMostRecentBrowserWindow: function RW_getMostRecentBrowserWindow(aOptions) {
let checkPrivacy = typeof aOptions == "object" &&
"private" in aOptions;
function isSuitableBrowserWindow(win) {
return (!win.closed &&
win.toolbar.visible &&
(!checkPrivacy ||
PrivateBrowsingUtils.isWindowPrivate(win) == aOptions.private));
}
#ifdef BROKEN_WM_Z_ORDER
let win = Services.wm.getMostRecentWindow("navigator:browser");
// if we're lucky, this isn't a popup, and we can just return this
if (win && !isSuitableBrowserWindow(win)) {
win = null;
let windowList = Services.wm.getEnumerator("navigator:browser");
// this is oldest to newest, so this gets a bit ugly
while (windowList.hasMoreElements()) {
let nextWin = windowList.getNext();
if (isSuitableBrowserWindow(nextWin))
win = nextWin;
}
}
return win;
#else
let windowList = Services.wm.getZOrderDOMWindowEnumerator("navigator:browser", true);
while (windowList.hasMoreElements()) {
let win = windowList.getNext();
if (isSuitableBrowserWindow(win))
return win;
}
return null;
#endif
}
};

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

@ -35,8 +35,12 @@ case "$target" in
;;
*-darwin*)
# GCC on darwin is based on gcc 4.2 and we don't support it anymore.
MOZ_PATH_PROGS(CC, $CC clang)
MOZ_PATH_PROGS(CXX, $CXX clang++)
if test -z "$CC"; then
MOZ_PATH_PROGS(CC, clang)
fi
if test -z "$CXX"; then
MOZ_PATH_PROGS(CXX, clang++)
fi
IS_GCC=$($CC -v 2>&1 | grep gcc)
if test -n "$IS_GCC"
then

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

@ -18,6 +18,8 @@ endif
topsrcdir = $(TOPSRCDIR)
include $(OBJDIR)/config/autoconf.mk
core_abspath = $(if $(filter /%,$(1)),$(1),$(CURDIR)/$(1))
DIST = $(OBJDIR)/dist
ifdef LIBXUL_SDK # {
@ -72,7 +74,7 @@ postflight_all:
$(DIST_ARCH_2)/$(MOZ_PKG_APPNAME)/$(APPNAME)/$(BUILDCONFIG)
mkdir -p $(DIST_UNI)/$(MOZ_PKG_APPNAME)
rm -f $(DIST_ARCH_2)/universal
ln -s $(DIST_UNI) $(DIST_ARCH_2)/universal
ln -s $(call core_abspath,$(DIST_UNI)) $(DIST_ARCH_2)/universal
rm -rf $(DIST_UNI)/$(MOZ_PKG_APPNAME)/$(APPNAME)
$(TOPSRCDIR)/build/macosx/universal/unify \
--unify-with-sort "\.manifest$$" \

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

@ -1639,7 +1639,11 @@ MOZ_ARG_ENABLE_BOOL(profiling,
# For profiling builds keep the symbol information
if test "$MOZ_PROFILING" -a -z "$STRIP_FLAGS"; then
STRIP_FLAGS="--strip-debug"
case "$OS_TARGET" in
Linux|DragonFly|FreeBSD|NetBSD|OpenBSD)
STRIP_FLAGS="--strip-debug"
;;
esac
fi
dnl ========================================================

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

@ -35,8 +35,12 @@ case "$target" in
;;
*-darwin*)
# GCC on darwin is based on gcc 4.2 and we don't support it anymore.
MOZ_PATH_PROGS(CC, $CC clang)
MOZ_PATH_PROGS(CXX, $CXX clang++)
if test -z "$CC"; then
MOZ_PATH_PROGS(CC, clang)
fi
if test -z "$CXX"; then
MOZ_PATH_PROGS(CXX, clang++)
fi
IS_GCC=$($CC -v 2>&1 | grep gcc)
if test -n "$IS_GCC"
then

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

@ -21,6 +21,9 @@ from mach.decorators import (
)
DEBUGGER_HELP = 'Debugger binary to run test in. Program name or path.'
class ReftestRunner(MozbuildObject):
"""Easily run reftests.
@ -51,7 +54,8 @@ class ReftestRunner(MozbuildObject):
def _make_shell_string(self, s):
return "'%s'" % re.sub("'", r"'\''", s)
def run_reftest_test(self, test_file=None, filter=None, suite=None):
def run_reftest_test(self, test_file=None, filter=None, suite=None,
debugger=None):
"""Runs a reftest.
test_file is a path to a test file. It can be a relative path from the
@ -63,27 +67,39 @@ class ReftestRunner(MozbuildObject):
suite is the type of reftest to run. It can be one of ('reftest',
'crashtest').
debugger is the program name (in $PATH) or the full path of the
debugger to run.
"""
if suite not in ('reftest', 'crashtest'):
raise Exception('None or unrecognized reftest suite type.')
env = {}
extra_args = []
if test_file:
path = self._find_manifest(suite, test_file)
if not os.path.exists(path):
raise Exception('No manifest file was found at %s.' % path)
env[b'TEST_PATH'] = path
if filter:
if b'EXTRA_TEST_ARGS' in os.environ:
env[b'EXTRA_TEST_ARGS'] = os.environ[b'EXTRA_TEST_ARGS'] + ' '
else:
env[b'EXTRA_TEST_ARGS'] = ' '
env[b'EXTRA_TEST_ARGS'] += ("--filter %s" %
self._make_shell_string(filter))
extra_args.extend(['--filter', self._make_shell_string(filter)])
pass_thru = False
if debugger:
extra_args.append('--debugger=%s' % debugger)
pass_thru = True
if extra_args:
args = [os.environ.get(b'EXTRA_TEST_ARGS', '')]
args.extend(extra_args)
env[b'EXTRA_TEST_ARGS'] = ' '.join(args)
# TODO hook up harness via native Python
self._run_make(directory='.', target=suite, append_env=env)
return self._run_make(directory='.', target=suite, append_env=env,
pass_thru=pass_thru, ensure_exit_code=False)
@CommandProvider
@ -95,18 +111,23 @@ class MachCommands(MachCommandBase):
@CommandArgument('--filter', default=None, metavar='REGEX',
help='A JS regular expression to match test URLs against, to select '
'a subset of tests to run.')
def run_reftest(self, test_file, filter):
self._run_reftest(test_file, filter=filter, suite='reftest')
@CommandArgument('--debugger', metavar='DEBUGGER', help=DEBUGGER_HELP)
def run_reftest(self, test_file, filter, debugger=None):
return self._run_reftest(test_file, filter=filter, suite='reftest',
debugger=debugger)
@Command('crashtest', help='Run a crashtest.')
@CommandArgument('test_file', default=None, nargs='?', metavar='MANIFEST',
help='Crashtest manifest file, or a direction in which to select '
'crashtests.list.')
def run_crashtest(self, test_file):
self._run_reftest(test_file, suite='crashtest')
@CommandArgument('--debugger', metavar='DEBUGGER', help=DEBUGGER_HELP)
def run_crashtest(self, test_file, debugger=None):
return self._run_reftest(test_file, suite='crashtest',
debugger=debugger)
def _run_reftest(self, test_file, filter, suite):
def _run_reftest(self, test_file, filter, suite, debugger=None):
reftest = self._spawn(ReftestRunner)
reftest.run_reftest_test(test_file, filter, suite)
return reftest.run_reftest_test(test_file, filter, suite,
debugger=debugger)

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

@ -32,6 +32,7 @@ MOCHITEST_BROWSER_FILES = \
ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING
MOCHITEST_BROWSER_FILES += \
browser_bug248970.js \
browser_favicon_setAndFetchFaviconForPage.js \
$(NULL)
else
MOCHITEST_BROWSER_FILES += \

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

@ -0,0 +1,145 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// This file tests the normal operation of setAndFetchFaviconForPage.
function test() {
// Initialization
waitForExplicitFinish();
let windowsToClose = [];
let testURI = "https://www.mozilla.org/en-US/";
let favIconLocation =
"http://example.org/tests/toolkit/components/places/tests/browser/favicon-normal32.png";
let favIconURI = NetUtil.newURI(favIconLocation);
let favIconMimeType= "image/png";
let pageURI;
let favIconData;
function testOnWindow(aOptions, aCallback) {
whenNewWindowLoaded(aOptions, function(aWin) {
windowsToClose.push(aWin);
executeSoon(function() aCallback(aWin));
});
};
// This function is called after calling finish() on the test.
registerCleanupFunction(function() {
windowsToClose.forEach(function(aWin) {
aWin.close();
});
});
function getIconFile(aCallback) {
NetUtil.asyncFetch(favIconLocation, function(inputStream, status) {
if (!Components.isSuccessCode(status)) {
ok(false, "Could not get the icon file");
// Handle error.
return;
}
// Check the returned size versus the expected size.
let size = inputStream.available();
favIconData = NetUtil.readInputStreamToString(inputStream, size);
is(size, favIconData.length, "Check correct icon size");
// Check that the favicon loaded correctly before starting the actual tests.
is(favIconData.length, 344, "Check correct icon length (344)");
if (aCallback) {
aCallback();
} else {
finish();
}
});
}
function testNormal(aWindow, aCallback) {
pageURI = NetUtil.newURI("http://example.com/normal");
waitForFaviconChanged(pageURI, favIconURI, aWindow,
function testNormalCallback() {
checkFaviconDataForPage(pageURI, favIconMimeType, favIconData, aWindow,
aCallback);
}
);
addVisits({uri: pageURI, transition: TRANSITION_TYPED}, aWindow,
function () {
aWindow.PlacesUtils.favicons.setAndFetchFaviconForPage(pageURI,
favIconURI, true, aWindow.PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE);
}
);
}
function testAboutURIBookmarked(aWindow, aCallback) {
pageURI = NetUtil.newURI("about:testAboutURI_bookmarked");
waitForFaviconChanged(pageURI, favIconURI, aWindow,
function testAboutURIBookmarkedCallback() {
checkFaviconDataForPage(pageURI, favIconMimeType, favIconData, aWindow,
aCallback);
}
);
aWindow.PlacesUtils.bookmarks.insertBookmark(
aWindow.PlacesUtils.unfiledBookmarksFolderId, pageURI,
aWindow.PlacesUtils.bookmarks.DEFAULT_INDEX, pageURI.spec);
aWindow.PlacesUtils.favicons.setAndFetchFaviconForPage(pageURI, favIconURI,
true, aWindow.PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE);
}
function testPrivateBrowsingBookmarked(aWindow, aCallback) {
pageURI = NetUtil.newURI("http://example.com/privateBrowsing_bookmarked");
waitForFaviconChanged(pageURI, favIconURI, aWindow,
function testPrivateBrowsingBookmarkedCallback() {
checkFaviconDataForPage(pageURI, favIconMimeType, favIconData, aWindow,
aCallback);
}
);
aWindow.PlacesUtils.bookmarks.insertBookmark(
aWindow.PlacesUtils.unfiledBookmarksFolderId, pageURI,
aWindow.PlacesUtils.bookmarks.DEFAULT_INDEX, pageURI.spec);
aWindow.PlacesUtils.favicons.setAndFetchFaviconForPage(pageURI, favIconURI,
true, aWindow.PlacesUtils.favicons.FAVICON_LOAD_PRIVATE);
}
function testDisabledHistoryBookmarked(aWindow, aCallback) {
pageURI = NetUtil.newURI("http://example.com/disabledHistory_bookmarked");
waitForFaviconChanged(pageURI, favIconURI, aWindow,
function testDisabledHistoryBookmarkedCallback() {
checkFaviconDataForPage(pageURI, favIconMimeType, favIconData, aWindow,
aCallback);
}
);
// Disable history while changing the favicon.
aWindow.Services.prefs.setBoolPref("places.history.enabled", false);
aWindow.PlacesUtils.bookmarks.insertBookmark(
aWindow.PlacesUtils.unfiledBookmarksFolderId, pageURI,
aWindow.PlacesUtils.bookmarks.DEFAULT_INDEX, pageURI.spec);
aWindow.PlacesUtils.favicons.setAndFetchFaviconForPage(pageURI, favIconURI,
true, aWindow.PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE);
// The setAndFetchFaviconForPage function calls CanAddURI synchronously, thus
// we can set the preference back to true immediately. We don't clear the
// preference because not all products enable Places by default.
aWindow.Services.prefs.setBoolPref("places.history.enabled", true);
}
getIconFile(function () {
testOnWindow({}, function(aWin) {
testNormal(aWin, function () {
testOnWindow({}, function(aWin) {
testAboutURIBookmarked(aWin, function () {
testOnWindow({private: true}, function(aWin) {
testPrivateBrowsingBookmarked(aWin, function () {
testOnWindow({}, function(aWin) {
testDisabledHistoryBookmarked(aWin, finish);
});
});
});
});
});
});
});
});
}

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

@ -1,5 +1,7 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
const TRANSITION_LINK = Ci.nsINavHistoryService.TRANSITION_LINK;
const TRANSITION_TYPED = Ci.nsINavHistoryService.TRANSITION_TYPED;
Components.utils.import("resource://gre/modules/NetUtil.jsm");
@ -112,3 +114,235 @@ function fieldForUrl(aURI, aFieldName, aCallback)
});
stmt.finalize();
}
function whenNewWindowLoaded(aOptions, aCallback) {
let win = OpenBrowserWindow(aOptions);
win.addEventListener("load", function onLoad() {
win.removeEventListener("load", onLoad, false);
aCallback(win);
}, false);
}
/**
* Generic nsINavHistoryObserver that doesn't implement anything, but provides
* dummy methods to prevent errors about an object not having a certain method.
*/
function NavHistoryObserver() {}
NavHistoryObserver.prototype = {
onBeginUpdateBatch: function () {},
onEndUpdateBatch: function () {},
onVisit: function () {},
onTitleChanged: function () {},
onBeforeDeleteURI: function () {},
onDeleteURI: function () {},
onClearHistory: function () {},
onPageChanged: function () {},
onDeleteVisits: function () {},
QueryInterface: XPCOMUtils.generateQI([
Ci.nsINavHistoryObserver,
])
};
/**
* Waits for the first OnPageChanged notification for ATTRIBUTE_FAVICON, and
* verifies that it matches the expected page URI and associated favicon URI.
*
* This function also double-checks the GUID parameter of the notification.
*
* @param aExpectedPageURI
* nsIURI object of the page whose favicon should change.
* @param aExpectedFaviconURI
* nsIURI object of the newly associated favicon.
* @param aCallback
* This function is called after the check finished.
*/
function waitForFaviconChanged(aExpectedPageURI, aExpectedFaviconURI, aWindow,
aCallback) {
let historyObserver = {
__proto__: NavHistoryObserver.prototype,
onPageChanged: function WFFC_onPageChanged(aURI, aWhat, aValue, aGUID) {
if (aWhat != Ci.nsINavHistoryObserver.ATTRIBUTE_FAVICON) {
return;
}
aWindow.PlacesUtils.history.removeObserver(this);
ok(aURI.equals(aExpectedPageURI),
"Check URIs are equal for the page which favicon changed");
is(aValue, aExpectedFaviconURI.spec,
"Check changed favicon URI is the expected");
checkGuidForURI(aURI, aGUID);
if (aCallback) {
aCallback();
}
}
};
aWindow.PlacesUtils.history.addObserver(historyObserver, false);
}
/**
* Asynchronously adds visits to a page, invoking a callback function when done.
*
* @param aPlaceInfo
* Can be an nsIURI, in such a case a single LINK visit will be added.
* Otherwise can be an object describing the visit to add, or an array
* of these objects:
* { uri: nsIURI of the page,
* transition: one of the TRANSITION_* from nsINavHistoryService,
* [optional] title: title of the page,
* [optional] visitDate: visit date in microseconds from the epoch
* [optional] referrer: nsIURI of the referrer for this visit
* }
* @param [optional] aCallback
* Function to be invoked on completion.
* @param [optional] aStack
* The stack frame used to report errors.
*/
function addVisits(aPlaceInfo, aWindow, aCallback, aStack) {
let stack = aStack || Components.stack.caller;
let places = [];
if (aPlaceInfo instanceof Ci.nsIURI) {
places.push({ uri: aPlaceInfo });
}
else if (Array.isArray(aPlaceInfo)) {
places = places.concat(aPlaceInfo);
} else {
places.push(aPlaceInfo)
}
// Create mozIVisitInfo for each entry.
let now = Date.now();
for (let i = 0; i < places.length; i++) {
if (!places[i].title) {
places[i].title = "test visit for " + places[i].uri.spec;
}
places[i].visits = [{
transitionType: places[i].transition === undefined ? TRANSITION_LINK
: places[i].transition,
visitDate: places[i].visitDate || (now++) * 1000,
referrerURI: places[i].referrer
}];
}
aWindow.PlacesUtils.asyncHistory.updatePlaces(
places,
{
handleError: function AAV_handleError() {
throw("Unexpected error in adding visit.");
},
handleResult: function () {},
handleCompletion: function UP_handleCompletion() {
if (aCallback)
aCallback();
}
}
);
}
/**
* Checks that the favicon for the given page matches the provided data.
*
* @param aPageURI
* nsIURI object for the page to check.
* @param aExpectedMimeType
* Expected MIME type of the icon, for example "image/png".
* @param aExpectedData
* Expected icon data, expressed as an array of byte values.
* @param aCallback
* This function is called after the check finished.
*/
function checkFaviconDataForPage(aPageURI, aExpectedMimeType, aExpectedData,
aWindow, aCallback) {
aWindow.PlacesUtils.favicons.getFaviconDataForPage(aPageURI,
function (aURI, aDataLen, aData, aMimeType) {
is(aExpectedMimeType, aMimeType, "Check expected MimeType");
is(aExpectedData.length, aData.length,
"Check favicon data for the given page matches the provided data");
checkGuidForURI(aPageURI);
aCallback();
});
}
/**
* Tests that a guid was set in moz_places for a given uri.
*
* @param aURI
* The uri to check.
* @param [optional] aGUID
* The expected guid in the database.
*/
function checkGuidForURI(aURI, aGUID) {
let guid = doGetGuidForURI(aURI);
if (aGUID) {
doCheckValidPlacesGuid(aGUID);
is(guid, aGUID, "Check equal guid for URIs");
}
}
/**
* Retrieves the guid for a given uri.
*
* @param aURI
* The uri to check.
* @return the associated the guid.
*/
function doGetGuidForURI(aURI) {
let stmt = DBConn().createStatement(
"SELECT guid "
+ "FROM moz_places "
+ "WHERE url = :url "
);
stmt.params.url = aURI.spec;
ok(stmt.executeStep(), "Check get guid for uri from moz_places");
let guid = stmt.row.guid;
stmt.finalize();
doCheckValidPlacesGuid(guid);
return guid;
}
/**
* Tests if a given guid is valid for use in Places or not.
*
* @param aGuid
* The guid to test.
*/
function doCheckValidPlacesGuid(aGuid) {
ok(/^[a-zA-Z0-9\-_]{12}$/.test(aGuid), "Check guid for valid places");
}
/**
* Gets the database connection. If the Places connection is invalid it will
* try to create a new connection.
*
* @param [optional] aForceNewConnection
* Forces creation of a new connection to the database. When a
* connection is asyncClosed it cannot anymore schedule async statements,
* though connectionReady will keep returning true (Bug 726990).
*
* @return The database connection or null if unable to get one.
*/
function DBConn(aForceNewConnection) {
let gDBConn;
if (!aForceNewConnection) {
let db = PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase)
.DBConnection;
if (db.connectionReady)
return db;
}
// If the Places database connection has been closed, create a new connection.
if (!gDBConn || aForceNewConnection) {
let file = Services.dirsvc.get('ProfD', Ci.nsIFile);
file.append("places.sqlite");
let dbConn = gDBConn = Services.storage.openDatabase(file);
// Be sure to cleanly close this connection.
Services.obs.addObserver(function DBCloseCallback(aSubject, aTopic, aData) {
Services.obs.removeObserver(DBCloseCallback, aTopic);
dbConn.asyncClose();
}, "profile-before-change", false);
}
return gDBConn.connectionReady ? gDBConn : null;
}

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

@ -611,17 +611,21 @@ class Dumper_Linux(Dumper):
return False
def CopyDebug(self, file, debug_file, guid):
import zlib, struct, hashlib
# We want to strip out the debug info, and add a
# .gnu_debuglink section to the object, so the debugger can
# actually load our debug info later.
file_dbg = file + ".dbg"
if subprocess.call([self.objcopy, '--only-keep-debug', file, file_dbg]) == 0 and \
subprocess.call([self.objcopy, '--add-gnu-debuglink=%s' % file_dbg, file]) == 0:
if subprocess.call([self.objcopy, '--only-keep-debug', file, file_dbg], stdout=sys.stderr) == 0 and \
subprocess.call([self.objcopy, '--add-gnu-debuglink=%s' % file_dbg, file], stdout=sys.stderr) == 0:
rel_path = os.path.join(debug_file,
guid,
debug_file + ".dbg")
full_path = os.path.normpath(os.path.join(self.symbol_path,
rel_path))
# Temporary debug information
print >>sys.stderr, read_output('objdump', '-j', '.gnu_debuglink', '-s', file)
print >>sys.stderr, "%s crc: %08x" % (file_dbg, 0xffffffff & zlib.crc32(open(file_dbg).read()))
shutil.move(file_dbg, full_path)
# gzip the shipped debug files
os.system("gzip %s" % full_path)