Merge m-c to s-c.
|
@ -237,7 +237,7 @@ AndroidPresenter.prototype.actionInvoked = function(aObject, aActionName) {
|
|||
gecko: {
|
||||
type: 'Accessibility:Event',
|
||||
eventType: ANDROID_TYPE_VIEW_CLICKED,
|
||||
text: [UtteranceGenerator.genForAction(aObject, aActionName)]
|
||||
text: UtteranceGenerator.genForAction(aObject, aActionName)
|
||||
}
|
||||
});
|
||||
};
|
||||
|
|
|
@ -54,7 +54,7 @@ var UtteranceGenerator = {
|
|||
},
|
||||
|
||||
genForAction: function(aObject, aActionName) {
|
||||
return gStringBundle.GetStringFromName(this.gActionMap[aActionName]);
|
||||
return [gStringBundle.GetStringFromName(this.gActionMap[aActionName])];
|
||||
},
|
||||
|
||||
verbosityRoleMap: {
|
||||
|
|
|
@ -71,10 +71,13 @@ nsXULTreeAccessible::
|
|||
mFlags |= eXULTreeAccessible;
|
||||
|
||||
mTree = nsCoreUtils::GetTreeBoxObject(aContent);
|
||||
if (mTree)
|
||||
mTree->GetView(getter_AddRefs(mTreeView));
|
||||
NS_ASSERTION(mTree, "Can't get mTree!\n");
|
||||
|
||||
NS_ASSERTION(mTree && mTreeView, "Can't get mTree or mTreeView!\n");
|
||||
if (mTree) {
|
||||
nsCOMPtr<nsITreeView> treeView;
|
||||
mTree->GetView(getter_AddRefs(treeView));
|
||||
mTreeView = treeView;
|
||||
}
|
||||
|
||||
nsIContent* parentContent = mContent->GetParent();
|
||||
if (parentContent) {
|
||||
|
@ -95,14 +98,12 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULTreeAccessible)
|
|||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXULTreeAccessible,
|
||||
nsAccessible)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTree)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTreeView)
|
||||
CycleCollectorTraverseCache(tmp->mAccessibleCache, &cb);
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsXULTreeAccessible,
|
||||
nsAccessible)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTree)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTreeView)
|
||||
ClearCache(tmp->mAccessibleCache);
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
|
@ -145,10 +146,11 @@ nsXULTreeAccessible::NativeState()
|
|||
void
|
||||
nsXULTreeAccessible::Value(nsString& aValue)
|
||||
{
|
||||
// Return the value is the first selected child.
|
||||
|
||||
aValue.Truncate();
|
||||
if (!mTreeView)
|
||||
return;
|
||||
|
||||
// Return the value is the first selected child.
|
||||
nsCOMPtr<nsITreeSelection> selection;
|
||||
mTreeView->GetSelection(getter_AddRefs(selection));
|
||||
if (!selection)
|
||||
|
@ -739,13 +741,11 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULTreeItemAccessibleBase)
|
|||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXULTreeItemAccessibleBase,
|
||||
nsAccessible)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTree)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTreeView)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsXULTreeItemAccessibleBase,
|
||||
nsAccessible)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTree)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTreeView)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsXULTreeItemAccessibleBase)
|
||||
|
|
|
@ -143,7 +143,7 @@ protected:
|
|||
virtual already_AddRefed<nsAccessible> CreateTreeItemAccessible(PRInt32 aRow);
|
||||
|
||||
nsCOMPtr<nsITreeBoxObject> mTree;
|
||||
nsCOMPtr<nsITreeView> mTreeView;
|
||||
nsITreeView* mTreeView;
|
||||
nsAccessibleHashtable mAccessibleCache;
|
||||
};
|
||||
|
||||
|
@ -244,7 +244,7 @@ protected:
|
|||
void GetCellName(nsITreeColumn* aColumn, nsAString& aName);
|
||||
|
||||
nsCOMPtr<nsITreeBoxObject> mTree;
|
||||
nsCOMPtr<nsITreeView> mTreeView;
|
||||
nsITreeView* mTreeView;
|
||||
PRInt32 mRow;
|
||||
};
|
||||
|
||||
|
|
|
@ -818,14 +818,12 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULTreeGridCellAccessible)
|
|||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXULTreeGridCellAccessible,
|
||||
nsLeafAccessible)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTree)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTreeView)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mColumn)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsXULTreeGridCellAccessible,
|
||||
nsLeafAccessible)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTree)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTreeView)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mColumn)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
|
|
|
@ -210,7 +210,7 @@ protected:
|
|||
enum { eAction_Click = 0 };
|
||||
|
||||
nsCOMPtr<nsITreeBoxObject> mTree;
|
||||
nsCOMPtr<nsITreeView> mTreeView;
|
||||
nsITreeView* mTreeView;
|
||||
|
||||
PRInt32 mRow;
|
||||
nsCOMPtr<nsITreeColumn> mColumn;
|
||||
|
|
|
@ -408,6 +408,8 @@
|
|||
@BINPATH@/components/messageWakeupService.manifest
|
||||
@BINPATH@/components/SettingsManager.js
|
||||
@BINPATH@/components/SettingsManager.manifest
|
||||
@BINPATH@/components/SettingsService.js
|
||||
@BINPATH@/components/SettingsService.manifest
|
||||
@BINPATH@/components/nsFilePicker.js
|
||||
@BINPATH@/components/nsFilePicker.manifest
|
||||
#ifdef MOZ_B2G_RIL
|
||||
|
|
|
@ -62,6 +62,10 @@ DEFINES += \
|
|||
-DAPP_VERSION="$(MOZ_APP_VERSION)" \
|
||||
-DFIREFOX_ICO=\"$(DIST)/branding/firefox.ico\" \
|
||||
-DDOCUMENT_ICO=\"$(DIST)/branding/document.ico\" \
|
||||
-DNEWWINDOW_ICO=\"$(DIST)/branding/newwindow.ico\" \
|
||||
-DNEWTAB_ICO=\"$(DIST)/branding/newtab.ico\" \
|
||||
-DPBMODE_ICO=\"$(DIST)/branding/pbmode.ico\" \
|
||||
|
||||
$(NULL)
|
||||
|
||||
ifdef LIBXUL_SDK #{
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
<?xml version="1.0"?>
|
||||
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1333739604000">
|
||||
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1335396801000">
|
||||
<emItems>
|
||||
<emItem blockID="i58" id="webmaster@buzzzzvideos.info">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i86" id="{45147e67-4020-47e2-8f7a-55464fb535aa}">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i41" id="{99079a25-328f-4bd4-be04-00955acaa0a7}">
|
||||
<versionRange minVersion="0.1" maxVersion="4.3.1.00" severity="1">
|
||||
</versionRange>
|
||||
|
@ -81,6 +85,10 @@
|
|||
<versionRange minVersion="2.0.3" maxVersion="2.0.3">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i83" id="flash@adobee.com">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i59" id="ghostviewer@youtube2.com">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
|
@ -99,6 +107,10 @@
|
|||
</emItem>
|
||||
<emItem blockID="i7" id="{2224e955-00e9-4613-a844-ce69fccaae91}">
|
||||
</emItem>
|
||||
<emItem blockID="i84" id="pink@rosaplugin.info">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i67" id="youtube2@youtube2.com">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
|
@ -161,6 +173,10 @@
|
|||
<versionRange minVersion="2.2" maxVersion="2.2">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i82" id="{8f42fb8b-b6f6-45de-81c0-d6d39f54f971}">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i19" id="{46551EC9-40F0-4e47-8E18-8E5CF550CFB8}">
|
||||
<versionRange minVersion="1.1b1" maxVersion="1.1b1">
|
||||
</versionRange>
|
||||
|
@ -196,6 +212,9 @@
|
|||
<pluginItem blockID="p80">
|
||||
<match name="description" exp="[^\d\._]((0(\.\d+(\.\d+([_\.]\d+)?)?)?)|(1\.(([0-5](\.\d+([_\.]\d+)?)?)|(6(\.0([_\.](0?\d|1\d|2\d|30))?)?)|(7(\.0([_\.][0-2])?)?))))([^\d\._]|$)" /> <match name="filename" exp="(npjp2\.dll)|(libnpjp2\.so)" /> <versionRange severity="1"></versionRange>
|
||||
</pluginItem>
|
||||
<pluginItem blockID="p85">
|
||||
<match name="filename" exp="JavaPlugin2_NPAPI\.plugin" /> <versionRange minVersion="0" maxVersion="12.9.0" severity="1"></versionRange>
|
||||
</pluginItem>
|
||||
</pluginItems>
|
||||
|
||||
<gfxItems>
|
||||
|
|
|
@ -45,6 +45,9 @@
|
|||
IDI_APPICON ICON FIREFOX_ICO
|
||||
IDI_DOCUMENT ICON DOCUMENT_ICO
|
||||
IDI_APPLICATION ICON FIREFOX_ICO
|
||||
IDI_NEWWINDOW ICON NEWWINDOW_ICO
|
||||
IDI_NEWTAB ICON NEWTAB_ICO
|
||||
IDI_PBMODE ICON PBMODE_ICO
|
||||
|
||||
STRINGTABLE DISCARDABLE
|
||||
BEGIN
|
||||
|
|
|
@ -32,7 +32,7 @@ function runAltLeftClickTest() {
|
|||
}
|
||||
|
||||
function runShiftLeftClickTest() {
|
||||
let listener = new WindowListener("chrome://browser/content/browser.xul", function(aWindow) {
|
||||
let listener = new WindowListener(getBrowserURL(), function(aWindow) {
|
||||
Services.wm.removeListener(listener);
|
||||
addPageShowListener(aWindow.gBrowser, function() {
|
||||
info("URL should be loaded in a new window");
|
||||
|
|
|
@ -58,6 +58,9 @@ WINDOWS_BRANDING_FILES = \
|
|||
wizHeader.bmp \
|
||||
wizHeaderRTL.bmp \
|
||||
wizWatermark.bmp \
|
||||
newwindow.ico \
|
||||
newtab.ico \
|
||||
pbmode.ico \
|
||||
$(NULL)
|
||||
|
||||
OSX_BRANDING_FILES = \
|
||||
|
|
После Ширина: | Высота: | Размер: 1.1 KiB |
После Ширина: | Высота: | Размер: 1.1 KiB |
После Ширина: | Высота: | Размер: 1.1 KiB |
|
@ -58,6 +58,9 @@ WINDOWS_BRANDING_FILES = \
|
|||
wizHeader.bmp \
|
||||
wizHeaderRTL.bmp \
|
||||
wizWatermark.bmp \
|
||||
newwindow.ico \
|
||||
newtab.ico \
|
||||
pbmode.ico \
|
||||
$(NULL)
|
||||
|
||||
OSX_BRANDING_FILES = \
|
||||
|
|
После Ширина: | Высота: | Размер: 1.1 KiB |
После Ширина: | Высота: | Размер: 1.1 KiB |
После Ширина: | Высота: | Размер: 1.1 KiB |
|
@ -58,6 +58,9 @@ WINDOWS_BRANDING_FILES = \
|
|||
wizHeader.bmp \
|
||||
wizHeaderRTL.bmp \
|
||||
wizWatermark.bmp \
|
||||
newwindow.ico \
|
||||
newtab.ico \
|
||||
pbmode.ico \
|
||||
$(NULL)
|
||||
|
||||
OSX_BRANDING_FILES = \
|
||||
|
|
После Ширина: | Высота: | Размер: 1.1 KiB |
После Ширина: | Высота: | Размер: 1.1 KiB |
После Ширина: | Высота: | Размер: 1.1 KiB |
|
@ -58,6 +58,9 @@ WINDOWS_BRANDING_FILES = \
|
|||
wizHeader.bmp \
|
||||
wizHeaderRTL.bmp \
|
||||
wizWatermark.bmp \
|
||||
newwindow.ico \
|
||||
newtab.ico \
|
||||
pbmode.ico \
|
||||
$(NULL)
|
||||
|
||||
OSX_BRANDING_FILES = \
|
||||
|
|
После Ширина: | Высота: | Размер: 1.1 KiB |
После Ширина: | Высота: | Размер: 1.1 KiB |
После Ширина: | Высота: | Размер: 1.1 KiB |
|
@ -49,6 +49,7 @@ richlistitem[type="download"]:not([selected]) button {
|
|||
.downloadCancelMenuItem,
|
||||
|
||||
.download-state:not(:-moz-any([state="1"], /* Finished */
|
||||
[state="2"], /* Failed */
|
||||
[state="3"], /* Canceled */
|
||||
[state="6"], /* Blocked (parental) */
|
||||
[state="8"], /* Blocked (dirty) */
|
||||
|
|
|
@ -56,18 +56,19 @@ const DownloadsPanel = {
|
|||
//// Initialization and termination
|
||||
|
||||
/**
|
||||
* State of the downloads panel, based on one of the kPanel constants.
|
||||
* Internal state of the downloads panel, based on one of the kState
|
||||
* constants. This is not the same state as the XUL panel element.
|
||||
*/
|
||||
_panelState: 0,
|
||||
_state: 0,
|
||||
|
||||
/** Download data has not been loaded. */
|
||||
get kPanelUninitialized() 0,
|
||||
/** Download data is loading, but the user interface is invisible. */
|
||||
get kPanelHidden() 1,
|
||||
/** The panel is not linked to downloads data yet. */
|
||||
get kStateUninitialized() 0,
|
||||
/** This object is linked to data, but the panel is invisible. */
|
||||
get kStateHidden() 1,
|
||||
/** The panel will be shown as soon as possible. */
|
||||
get kPanelShowing() 2,
|
||||
/** The panel is open, though download data might still be loading. */
|
||||
get kPanelShown() 3,
|
||||
get kStateShowing() 2,
|
||||
/** The panel is open. */
|
||||
get kStateShown() 3,
|
||||
|
||||
/**
|
||||
* Location of the panel overlay.
|
||||
|
@ -84,12 +85,12 @@ const DownloadsPanel = {
|
|||
*/
|
||||
initialize: function DP_initialize(aCallback)
|
||||
{
|
||||
if (this._panelState != this.kPanelUninitialized) {
|
||||
if (this._state != this.kStateUninitialized) {
|
||||
DownloadsOverlayLoader.ensureOverlayLoaded(this.kDownloadsOverlay,
|
||||
aCallback);
|
||||
return;
|
||||
}
|
||||
this._panelState = this.kPanelHidden;
|
||||
this._state = this.kStateHidden;
|
||||
|
||||
window.addEventListener("unload", this.onWindowUnload, false);
|
||||
|
||||
|
@ -115,7 +116,7 @@ const DownloadsPanel = {
|
|||
*/
|
||||
terminate: function DP_terminate()
|
||||
{
|
||||
if (this._panelState == this.kPanelUninitialized) {
|
||||
if (this._state == this.kStateUninitialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -127,7 +128,7 @@ const DownloadsPanel = {
|
|||
DownloadsViewController.terminate();
|
||||
DownloadsCommon.data.removeView(DownloadsView);
|
||||
|
||||
this._panelState = this.kPanelUninitialized;
|
||||
this._state = this.kStateUninitialized;
|
||||
},
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -163,7 +164,7 @@ const DownloadsPanel = {
|
|||
setTimeout(function () DownloadsPanel._openPopupIfDataReady(), 0);
|
||||
}.bind(this));
|
||||
|
||||
this._panelState = this.kPanelShowing;
|
||||
this._state = this.kStateShowing;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -181,7 +182,7 @@ const DownloadsPanel = {
|
|||
// Ensure that we allow the panel to be reopened. Note that, if the popup
|
||||
// was open, then the onPopupHidden event handler has already updated the
|
||||
// current state, otherwise we must update the state ourselves.
|
||||
this._panelState = this.kPanelHidden;
|
||||
this._state = this.kStateHidden;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -189,8 +190,8 @@ const DownloadsPanel = {
|
|||
*/
|
||||
get isPanelShowing()
|
||||
{
|
||||
return this._panelState == this.kPanelShowing ||
|
||||
this._panelState == this.kPanelShown;
|
||||
return this._state == this.kStateShowing ||
|
||||
this._state == this.kStateShown;
|
||||
},
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -220,6 +221,8 @@ const DownloadsPanel = {
|
|||
return;
|
||||
}
|
||||
|
||||
this._state = this.kStateShown;
|
||||
|
||||
// Since at most one popup is open at any given time, we can set globally.
|
||||
DownloadsCommon.indicatorData.attentionSuppressed = true;
|
||||
|
||||
|
@ -246,7 +249,7 @@ const DownloadsPanel = {
|
|||
DownloadsButton.releaseAnchor();
|
||||
|
||||
// Allow the panel to be reopened.
|
||||
this._panelState = this.kPanelHidden;
|
||||
this._state = this.kStateHidden;
|
||||
},
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -275,7 +278,7 @@ const DownloadsPanel = {
|
|||
_focusPanel: function DP_focusPanel()
|
||||
{
|
||||
// We may be invoked while the panel is still waiting to be shown.
|
||||
if (this._panelState != this.kPanelShown) {
|
||||
if (this._state != this.kStateShown) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -295,12 +298,10 @@ const DownloadsPanel = {
|
|||
{
|
||||
// We don't want to open the popup if we already displayed it, or if we are
|
||||
// still loading data.
|
||||
if (this._panelState != this.kPanelShowing || DownloadsView.loading) {
|
||||
if (this._state != this.kStateShowing || DownloadsView.loading) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._panelState = this.kPanelShown;
|
||||
|
||||
// Make sure that clicking outside the popup cannot reopen it accidentally.
|
||||
this.panel.popupBoxObject.setConsumeRollupEvent(Ci.nsIPopupBoxObject
|
||||
.ROLLUP_CONSUME);
|
||||
|
@ -308,6 +309,16 @@ const DownloadsPanel = {
|
|||
// Ensure the anchor is visible. If that is not possible, show the panel
|
||||
// anchored to the top area of the window, near the default anchor position.
|
||||
DownloadsButton.getAnchor(function DP_OPIDR_callback(aAnchor) {
|
||||
// At this point, if the window is minimized, opening the panel could fail
|
||||
// without any notification, and there would be no way to either open or
|
||||
// close the panel anymore. To prevent this, check if the window is
|
||||
// minimized and in that case force the panel to the closed state.
|
||||
if (window.windowState == Ci.nsIDOMChromeWindow.STATE_MINIMIZED) {
|
||||
DownloadsButton.releaseAnchor();
|
||||
this._state = this.kStateHidden;
|
||||
return;
|
||||
}
|
||||
|
||||
if (aAnchor) {
|
||||
this.panel.openPopup(aAnchor, "bottomcenter topright", 0, 0, false,
|
||||
null);
|
||||
|
|
|
@ -394,11 +394,6 @@ const DownloadsData = {
|
|||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// Persistent data loading
|
||||
|
||||
/**
|
||||
* Asynchronous database statement used to read the list of downloads.
|
||||
*/
|
||||
_statement: null,
|
||||
|
||||
/**
|
||||
* Represents an executing statement, allowing its cancellation.
|
||||
*/
|
||||
|
@ -455,10 +450,19 @@ const DownloadsData = {
|
|||
}
|
||||
} else {
|
||||
if (this._loadState != this.kLoadAll) {
|
||||
// Reload the list from the database asynchronously.
|
||||
this._statement = Services.downloads.DBConnection.createAsyncStatement(
|
||||
"SELECT * FROM moz_downloads ORDER BY id DESC");
|
||||
this._pendingStatement = this._statement.executeAsync(this);
|
||||
// Load only the relevant columns from the downloads database. The
|
||||
// columns are read in the init_FromDataRow method of DownloadsDataItem.
|
||||
let statement = Services.downloads.DBConnection.createAsyncStatement(
|
||||
"SELECT id, target, name, source, referrer, state, "
|
||||
+ "startTime, endTime, currBytes, maxBytes "
|
||||
+ "FROM moz_downloads "
|
||||
+ "ORDER BY id DESC"
|
||||
);
|
||||
try {
|
||||
this._pendingStatement = statement.executeAsync(this);
|
||||
} finally {
|
||||
statement.finalize();
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -472,10 +476,6 @@ const DownloadsData = {
|
|||
this._pendingStatement.cancel();
|
||||
this._pendingStatement = null;
|
||||
}
|
||||
if (this._statement) {
|
||||
this._statement.finalize();
|
||||
this._statement = null;
|
||||
}
|
||||
|
||||
// Close all the views on the current data. Create a copy of the array
|
||||
// because some views might unregister while processing this event.
|
||||
|
|
|
@ -78,6 +78,11 @@ DownloadsUI.prototype = {
|
|||
// Show the panel in the most recent browser window, if present.
|
||||
let browserWin = gBrowserGlue.getMostRecentBrowserWindow();
|
||||
if (browserWin) {
|
||||
// The most recent browser window could have been minimized, in that case
|
||||
// it must be restored to allow the panel to open properly.
|
||||
if (browserWin.windowState == Ci.nsIDOMChromeWindow.STATE_MINIMIZED) {
|
||||
browserWin.restore();
|
||||
}
|
||||
browserWin.focus();
|
||||
browserWin.DownloadsPanel.showPanel();
|
||||
return;
|
||||
|
|
|
@ -1366,7 +1366,7 @@ FeedWriter.prototype = {
|
|||
}
|
||||
var faviconURI = makeURI(readerURI.prePath + "/favicon.ico");
|
||||
var self = this;
|
||||
this._faviconService.setAndLoadFaviconForPage(readerURI, faviconURI, false,
|
||||
this._faviconService.setAndFetchFaviconForPage(readerURI, faviconURI, false,
|
||||
function (aURI, aDataLen, aData, aMimeType) {
|
||||
if (aDataLen > 0) {
|
||||
var dataURL = "data:" + aMimeType + ";base64," +
|
||||
|
|
|
@ -448,9 +448,8 @@ WebContentConverterRegistrar.prototype = {
|
|||
// Now Ask the user and provide the proper callback
|
||||
message = this._getFormattedString("addProtocolHandler",
|
||||
[aTitle, uri.host, aProtocol]);
|
||||
var fis = Cc["@mozilla.org/browser/favicon-service;1"].
|
||||
getService(Ci.nsIFaviconService);
|
||||
var notificationIcon = fis.getFaviconLinkForIcon(uri);
|
||||
|
||||
var notificationIcon = uri.prePath + "/favicon.ico";
|
||||
var notificationValue = "Protocol Registration: " + aProtocol;
|
||||
var addButton = {
|
||||
label: this._getString("addProtocolHandlerAddButton"),
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
let bg = Cc["@mozilla.org/browser/browserglue;1"].getService(Ci.nsIObserver);
|
||||
let gOriginalMigrationVersion;
|
||||
const BROWSER_URL = getBrowserURL();
|
||||
|
||||
let localStore = {
|
||||
get RDF() Cc["@mozilla.org/rdf/rdf-service;1"].getService(Ci.nsIRDFService),
|
||||
|
@ -16,10 +17,10 @@ let localStore = {
|
|||
get toolbar()
|
||||
{
|
||||
delete this.toolbar;
|
||||
let toolbar = this.RDF.GetResource("chrome://browser/content/browser.xul#PersonalToolbar");
|
||||
let toolbar = this.RDF.GetResource(BROWSER_URL + "#PersonalToolbar");
|
||||
// Add the entry to the persisted set for this document if it's not there.
|
||||
// See nsXULDocument::Persist.
|
||||
let doc = this.RDF.GetResource("chrome://browser/content/browser.xul");
|
||||
let doc = this.RDF.GetResource(BROWSER_URL);
|
||||
let persist = this.RDF.GetResource("http://home.netscape.com/NC-rdf#persist");
|
||||
if (!this.store.HasAssertion(doc, persist, toolbar, true)) {
|
||||
this.store.Assert(doc, persist, toolbar, true);
|
||||
|
|
|
@ -133,6 +133,10 @@ PrivateBrowsingService.prototype = {
|
|||
// Whether private browsing has been turned on from the command line
|
||||
_lastChangedByCommandLine: false,
|
||||
|
||||
// Telemetry measurements
|
||||
_enterTimestamps: {},
|
||||
_exitTimestamps: {},
|
||||
|
||||
// XPCOM registration
|
||||
classID: Components.ID("{c31f4883-839b-45f6-82ad-a6a9bc5ad599}"),
|
||||
|
||||
|
@ -308,6 +312,7 @@ PrivateBrowsingService.prototype = {
|
|||
// restore has been completed
|
||||
this._currentStatus = STATE_IDLE;
|
||||
this._obs.notifyObservers(null, "private-browsing-transition-complete", "");
|
||||
this._recordTransitionTime("completed");
|
||||
break;
|
||||
case STATE_WAITING_FOR_RESTORE:
|
||||
// too soon to notify...
|
||||
|
@ -323,6 +328,51 @@ PrivateBrowsingService.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
_recordTransitionTime: function PBS__recordTransitionTime(aPhase) {
|
||||
// To record the time spent in private browsing transitions, note that we
|
||||
// cannot use the TelemetryStopwatch module, because it reports its results
|
||||
// immediately when the timer is stopped. In this case, we need to delay
|
||||
// the actual histogram update after we are out of private browsing mode.
|
||||
if (this._inPrivateBrowsing) {
|
||||
this._enterTimestamps[aPhase] = Date.now();
|
||||
} else {
|
||||
if (this._quitting) {
|
||||
// If we are quitting the browser, we don't care collecting the data,
|
||||
// because we wouldn't be able to record it with telemetry.
|
||||
return;
|
||||
}
|
||||
this._exitTimestamps[aPhase] = Date.now();
|
||||
if (aPhase == "completed") {
|
||||
// After we finished exiting the private browsing mode, we can finally
|
||||
// record the telemetry data, for the enter and the exit processes.
|
||||
this._reportTelemetry();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_reportTelemetry: function PBS__reportTelemetry() {
|
||||
function reportTelemetryEntry(aHistogramId, aValue) {
|
||||
try {
|
||||
Services.telemetry.getHistogramById(aHistogramId).add(aValue);
|
||||
} catch (ex) {
|
||||
Cu.reportError(ex);
|
||||
}
|
||||
}
|
||||
|
||||
reportTelemetryEntry(
|
||||
"PRIVATE_BROWSING_TRANSITION_ENTER_PREPARATION_MS",
|
||||
this._enterTimestamps.prepared - this._enterTimestamps.started);
|
||||
reportTelemetryEntry(
|
||||
"PRIVATE_BROWSING_TRANSITION_ENTER_TOTAL_MS",
|
||||
this._enterTimestamps.completed - this._enterTimestamps.started);
|
||||
reportTelemetryEntry(
|
||||
"PRIVATE_BROWSING_TRANSITION_EXIT_PREPARATION_MS",
|
||||
this._exitTimestamps.prepared - this._exitTimestamps.started);
|
||||
reportTelemetryEntry(
|
||||
"PRIVATE_BROWSING_TRANSITION_EXIT_TOTAL_MS",
|
||||
this._exitTimestamps.completed - this._exitTimestamps.started);
|
||||
},
|
||||
|
||||
_canEnterPrivateBrowsingMode: function PBS__canEnterPrivateBrowsingMode() {
|
||||
let cancelEnter = Cc["@mozilla.org/supports-PRBool;1"].
|
||||
createInstance(Ci.nsISupportsPRBool);
|
||||
|
@ -537,6 +587,8 @@ PrivateBrowsingService.prototype = {
|
|||
this._autoStarted = this._prefs.getBoolPref("browser.privatebrowsing.autostart");
|
||||
this._inPrivateBrowsing = val != false;
|
||||
|
||||
this._recordTransitionTime("started");
|
||||
|
||||
let data = val ? "enter" : "exit";
|
||||
|
||||
let quitting = Cc["@mozilla.org/supports-PRBool;1"].
|
||||
|
@ -551,6 +603,8 @@ PrivateBrowsingService.prototype = {
|
|||
|
||||
this._obs.notifyObservers(quitting, "private-browsing", data);
|
||||
|
||||
this._recordTransitionTime("prepared");
|
||||
|
||||
// load the appropriate session
|
||||
this._onAfterPrivateBrowsingModeChange();
|
||||
} catch (ex) {
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
function test() {
|
||||
// We need to open a new window for this so that its docshell would get destroyed
|
||||
// when clearing the PB mode flag.
|
||||
let newWin = window.openDialog("chrome://browser/content/", "_blank", "chrome,all,dialog=no");
|
||||
let newWin = window.openDialog(getBrowserURL(), "_blank", "chrome,all,dialog=no");
|
||||
waitForExplicitFinish();
|
||||
SimpleTest.waitForFocus(function() {
|
||||
let notificationCount = 0;
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gPrivateBrowsing",
|
||||
PRIVATEBROWSING_CONTRACT_ID,
|
||||
"nsIPrivateBrowsingService");
|
||||
|
||||
function waitForTransition(aEnabled, aCallback) {
|
||||
Services.obs.addObserver(function PBT_transition(aSubject, aTopic, aData) {
|
||||
Services.obs.removeObserver(PBT_transition, aTopic, false);
|
||||
// Telemetry data is recorded just after the private browsing transition
|
||||
// observers are notified, thus we must wait for this observer to return.
|
||||
do_execute_soon(aCallback);
|
||||
}, "private-browsing-transition-complete", false);
|
||||
gPrivateBrowsing.privateBrowsingEnabled = aEnabled;
|
||||
}
|
||||
|
||||
function checkHistogram(aId) {
|
||||
// Check that we have data either in the first bucket (that doesn't
|
||||
// count towards the sum) or one of the other buckets, by checking
|
||||
// the sum of the values.
|
||||
let snapshot = Services.telemetry.getHistogramById(aId).snapshot();
|
||||
do_check_true(snapshot.sum > 0 || snapshot.counts[0] > 0);
|
||||
}
|
||||
|
||||
function do_test() {
|
||||
do_test_pending();
|
||||
|
||||
waitForTransition(true, function PBT_enabled() {
|
||||
waitForTransition(false, function PBT_disabled() {
|
||||
checkHistogram("PRIVATE_BROWSING_TRANSITION_ENTER_PREPARATION_MS");
|
||||
checkHistogram("PRIVATE_BROWSING_TRANSITION_ENTER_TOTAL_MS");
|
||||
checkHistogram("PRIVATE_BROWSING_TRANSITION_EXIT_PREPARATION_MS");
|
||||
checkHistogram("PRIVATE_BROWSING_TRANSITION_EXIT_TOTAL_MS");
|
||||
|
||||
do_test_finished();
|
||||
});
|
||||
});
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/* ***** 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) 2008
|
||||
* 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 ***** */
|
||||
|
||||
// Checks that telemetry data for private browsing transitions is recorded.
|
||||
|
||||
function run_test() {
|
||||
PRIVATEBROWSING_CONTRACT_ID = "@mozilla.org/privatebrowsing;1";
|
||||
load("do_test_privatebrowsing_telemetry.js");
|
||||
do_test();
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/* ***** 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 ***** */
|
||||
|
||||
// Checks that telemetry data for private browsing transitions is recorded.
|
||||
|
||||
function run_test() {
|
||||
PRIVATEBROWSING_CONTRACT_ID = "@mozilla.org/privatebrowsing-wrapper;1";
|
||||
load("do_test_privatebrowsing_telemetry.js");
|
||||
do_test();
|
||||
}
|
|
@ -12,12 +12,14 @@ tail = tail_privatebrowsing.js
|
|||
[test_privatebrowsing_autostart.js]
|
||||
[test_privatebrowsing_commandline.js]
|
||||
[test_privatebrowsing_exit.js]
|
||||
[test_privatebrowsing_telemetry.js]
|
||||
[test_privatebrowsingwrapper_autostart.js]
|
||||
[test_privatebrowsingwrapper_commandline.js]
|
||||
[test_privatebrowsingwrapper_exit.js]
|
||||
[test_privatebrowsingwrapper_placesTitleNoUpdate.js]
|
||||
[test_privatebrowsingwrapper_removeDataFromDomain.js]
|
||||
[test_privatebrowsingwrapper_removeDataFromDomain_activeDownloads.js]
|
||||
[test_privatebrowsingwrapper_telemetry.js]
|
||||
[test_removeDataFromDomain.js]
|
||||
[test_removeDataFromDomain_activeDownloads.js]
|
||||
[test_transition_nooffline.js]
|
||||
|
|
|
@ -73,12 +73,15 @@ function test() {
|
|||
let uniqueValue = "unik" + Date.now();
|
||||
let uniqueText = "pi != " + Math.random();
|
||||
|
||||
// Be consistent: let the page actually display, as we are "interacting" with it.
|
||||
Services.prefs.setBoolPref("general.warnOnAboutConfig", false);
|
||||
|
||||
// make sure that the next closed window will increase getClosedWindowCount
|
||||
let max_windows_undo = gPrefService.getIntPref("browser.sessionstore.max_windows_undo");
|
||||
gPrefService.setIntPref("browser.sessionstore.max_windows_undo", max_windows_undo + 1);
|
||||
let max_windows_undo = Services.prefs.getIntPref("browser.sessionstore.max_windows_undo");
|
||||
Services.prefs.setIntPref("browser.sessionstore.max_windows_undo", max_windows_undo + 1);
|
||||
let closedWindowCount = ss.getClosedWindowCount();
|
||||
|
||||
provideWindow(function (newWin) {
|
||||
provideWindow(function onTestURLLoaded(newWin) {
|
||||
newWin.gBrowser.addTab().linkedBrowser.stop();
|
||||
|
||||
// mark the window with some unique data to be restored later on
|
||||
|
@ -105,28 +108,31 @@ function test() {
|
|||
// SSTabRestored will fire more than once, so we need to make sure we count them
|
||||
let restoredTabs = 0;
|
||||
let expectedTabs = data.tabs.length;
|
||||
whenWindowLoaded(newWin2, function () {
|
||||
newWin2.gBrowser.tabContainer.addEventListener("SSTabRestored", function(aEvent) {
|
||||
if (++restoredTabs < expectedTabs)
|
||||
return;
|
||||
newWin2.gBrowser.tabContainer.removeEventListener("SSTabRestored", arguments.callee, true);
|
||||
newWin2.addEventListener("SSTabRestored", function sstabrestoredListener(aEvent) {
|
||||
++restoredTabs;
|
||||
info("Restored tab " + restoredTabs + "/" + expectedTabs);
|
||||
if (restoredTabs < expectedTabs) {
|
||||
return;
|
||||
}
|
||||
|
||||
is(newWin2.gBrowser.tabs.length, 2,
|
||||
"The window correctly restored 2 tabs");
|
||||
is(newWin2.gBrowser.currentURI.spec, testURL,
|
||||
"The window correctly restored the URL");
|
||||
newWin2.removeEventListener("SSTabRestored", sstabrestoredListener, true);
|
||||
|
||||
let textbox = newWin2.content.document.getElementById("textbox");
|
||||
is(textbox.value, uniqueText,
|
||||
"The window correctly restored the form");
|
||||
is(ss.getWindowValue(newWin2, uniqueKey), uniqueValue,
|
||||
"The window correctly restored the data associated with it");
|
||||
is(newWin2.gBrowser.tabs.length, 2,
|
||||
"The window correctly restored 2 tabs");
|
||||
is(newWin2.gBrowser.currentURI.spec, testURL,
|
||||
"The window correctly restored the URL");
|
||||
|
||||
// clean up
|
||||
newWin2.close();
|
||||
gPrefService.clearUserPref("browser.sessionstore.max_windows_undo");
|
||||
finish();
|
||||
}, true);
|
||||
});
|
||||
let textbox = newWin2.content.document.getElementById("textbox");
|
||||
is(textbox.value, uniqueText,
|
||||
"The window correctly restored the form");
|
||||
is(ss.getWindowValue(newWin2, uniqueKey), uniqueValue,
|
||||
"The window correctly restored the data associated with it");
|
||||
|
||||
// clean up
|
||||
newWin2.close();
|
||||
Services.prefs.clearUserPref("browser.sessionstore.max_windows_undo");
|
||||
Services.prefs.clearUserPref("general.warnOnAboutConfig");
|
||||
finish();
|
||||
}, true);
|
||||
}, testURL);
|
||||
}
|
||||
|
|
|
@ -40,10 +40,8 @@
|
|||
|
||||
// Tests that code completion works properly.
|
||||
|
||||
const TEST_URI = "chrome://browser/content/browser.xul";
|
||||
|
||||
function test() {
|
||||
addTab(TEST_URI);
|
||||
addTab(getBrowserURL());
|
||||
browser.addEventListener("DOMContentLoaded", testChrome, false);
|
||||
}
|
||||
|
||||
|
|
|
@ -637,6 +637,7 @@ bin/components/@DLL_PREFIX@nkgnomevfs@DLL_SUFFIX@
|
|||
@BINPATH@/webapprt/chrome/webapprt@JAREXT@
|
||||
@BINPATH@/webapprt/chrome/webapprt.manifest
|
||||
@BINPATH@/webapprt/components/CommandLineHandler.js
|
||||
@BINPATH@/webapprt/components/ContentPolicy.js
|
||||
@BINPATH@/webapprt/components/DirectoryProvider.js
|
||||
@BINPATH@/webapprt/components/components.manifest
|
||||
@BINPATH@/webapprt/defaults/preferences/prefs.js
|
||||
|
|
|
@ -27,6 +27,9 @@ const PREF_NEWTAB_ENABLED = "browser.newtabpage.enabled";
|
|||
// The maximum number of results we want to retrieve from history.
|
||||
const HISTORY_RESULTS_LIMIT = 100;
|
||||
|
||||
// The gather telemetry topic.
|
||||
const TOPIC_GATHER_TELEMETRY = "gather-telemetry";
|
||||
|
||||
/**
|
||||
* Singleton that provides storage functionality.
|
||||
*/
|
||||
|
@ -585,6 +588,47 @@ let Links = {
|
|||
Ci.nsISupportsWeakReference])
|
||||
};
|
||||
|
||||
/**
|
||||
* Singleton used to collect telemetry data.
|
||||
*
|
||||
*/
|
||||
let Telemetry = {
|
||||
/**
|
||||
* Initializes object.
|
||||
*/
|
||||
init: function Telemetry_init() {
|
||||
Services.obs.addObserver(this, TOPIC_GATHER_TELEMETRY, false);
|
||||
},
|
||||
|
||||
/**
|
||||
* Collects data.
|
||||
*/
|
||||
_collect: function Telemetry_collect() {
|
||||
let probes = [
|
||||
{ histogram: "NEWTAB_PAGE_ENABLED",
|
||||
value: AllPages.enabled },
|
||||
{ histogram: "NEWTAB_PAGE_PINNED_SITES_COUNT",
|
||||
value: PinnedLinks.links.length },
|
||||
{ histogram: "NEWTAB_PAGE_BLOCKED_SITES_COUNT",
|
||||
value: Object.keys(BlockedLinks.links).length }
|
||||
];
|
||||
|
||||
probes.forEach(function Telemetry_collect_forEach(aProbe) {
|
||||
Services.telemetry.getHistogramById(aProbe.histogram)
|
||||
.add(aProbe.value);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Listens for gather telemetry topic.
|
||||
*/
|
||||
observe: function Telemetry_observe(aSubject, aTopic, aData) {
|
||||
this._collect();
|
||||
}
|
||||
};
|
||||
|
||||
Telemetry.init();
|
||||
|
||||
/**
|
||||
* Singleton that provides the public API of this JSM.
|
||||
*/
|
||||
|
|
|
@ -141,7 +141,7 @@ var tasksCfg = [
|
|||
get title() _getString("taskbar.tasks.newTab.label"),
|
||||
get description() _getString("taskbar.tasks.newTab.description"),
|
||||
args: "-new-tab about:blank",
|
||||
iconIndex: 0, // Fx app icon
|
||||
iconIndex: 3, // New window icon
|
||||
open: true,
|
||||
close: true, // The jump list already has an app launch icon, but
|
||||
// we don't always update the list on shutdown.
|
||||
|
@ -153,7 +153,7 @@ var tasksCfg = [
|
|||
get title() _getString("taskbar.tasks.newWindow.label"),
|
||||
get description() _getString("taskbar.tasks.newWindow.description"),
|
||||
args: "-browser",
|
||||
iconIndex: 0, // Fx app icon
|
||||
iconIndex: 2, // New tab icon
|
||||
open: true,
|
||||
close: true, // No point, but we don't always update the list on
|
||||
// shutdown. Thus true for consistency.
|
||||
|
@ -174,7 +174,7 @@ var tasksCfg = [
|
|||
return _getString("taskbar.tasks.enterPrivacyMode.description");
|
||||
},
|
||||
args: "-private-toggle",
|
||||
iconIndex: 0, // Fx app icon
|
||||
iconIndex: 4, // Private browsing mode icon
|
||||
get open() {
|
||||
// Don't show when inside permanent private browsing mode
|
||||
return !_privateBrowsingSvc.autoStarted;
|
||||
|
|
|
@ -0,0 +1,232 @@
|
|||
# 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/.
|
||||
|
||||
import automationutils
|
||||
import os
|
||||
import re
|
||||
import socket
|
||||
import shutil
|
||||
import sys
|
||||
import tempfile
|
||||
import time
|
||||
|
||||
from automation import Automation
|
||||
from devicemanager import DeviceManager, NetworkTools
|
||||
|
||||
class B2GRemoteAutomation(Automation):
|
||||
_devicemanager = None
|
||||
|
||||
def __init__(self, deviceManager, appName='', remoteLog=None,
|
||||
marionette=None):
|
||||
self._devicemanager = deviceManager
|
||||
self._appName = appName
|
||||
self._remoteProfile = None
|
||||
self._remoteLog = remoteLog
|
||||
self.marionette = marionette
|
||||
|
||||
# Default our product to b2g
|
||||
self._product = "b2g"
|
||||
Automation.__init__(self)
|
||||
|
||||
def setDeviceManager(self, deviceManager):
|
||||
self._devicemanager = deviceManager
|
||||
|
||||
def setAppName(self, appName):
|
||||
self._appName = appName
|
||||
|
||||
def setRemoteProfile(self, remoteProfile):
|
||||
self._remoteProfile = remoteProfile
|
||||
|
||||
def setProduct(self, product):
|
||||
self._product = product
|
||||
|
||||
def setRemoteLog(self, logfile):
|
||||
self._remoteLog = logfile
|
||||
|
||||
# Set up what we need for the remote environment
|
||||
def environment(self, env=None, xrePath=None, crashreporter=True):
|
||||
# Because we are running remote, we don't want to mimic the local env
|
||||
# so no copying of os.environ
|
||||
if env is None:
|
||||
env = {}
|
||||
|
||||
return env
|
||||
|
||||
def checkForCrashes(self, directory, symbolsPath):
|
||||
# XXX: This will have to be updated after crash reporting on b2g
|
||||
# is in place.
|
||||
dumpDir = tempfile.mkdtemp()
|
||||
self._devicemanager.getDirectory(self._remoteProfile + '/minidumps/', dumpDir)
|
||||
automationutils.checkForCrashes(dumpDir, symbolsPath, self.lastTestSeen)
|
||||
try:
|
||||
shutil.rmtree(dumpDir)
|
||||
except:
|
||||
print "WARNING: unable to remove directory: %s" % (dumpDir)
|
||||
|
||||
def buildCommandLine(self, app, debuggerInfo, profileDir, testURL, extraArgs):
|
||||
# if remote profile is specified, use that instead
|
||||
if (self._remoteProfile):
|
||||
profileDir = self._remoteProfile
|
||||
|
||||
cmd, args = Automation.buildCommandLine(self, app, debuggerInfo, profileDir, testURL, extraArgs)
|
||||
|
||||
return app, args
|
||||
|
||||
def getLanIp(self):
|
||||
nettools = NetworkTools()
|
||||
return nettools.getLanIp()
|
||||
|
||||
def waitForFinish(self, proc, utilityPath, timeout, maxTime, startTime,
|
||||
debuggerInfo, symbolsPath, logger):
|
||||
""" Wait for mochitest to finish (as evidenced by a signature string
|
||||
in logcat), or for a given amount of time to elapse with no
|
||||
output.
|
||||
"""
|
||||
timeout = timeout or 120
|
||||
|
||||
didTimeout = False
|
||||
|
||||
done = time.time() + timeout
|
||||
while True:
|
||||
currentlog = proc.stdout
|
||||
if currentlog:
|
||||
done = time.time() + timeout
|
||||
print currentlog
|
||||
if 'INFO SimpleTest FINISHED' in currentlog:
|
||||
return 0
|
||||
else:
|
||||
if time.time() > done:
|
||||
self.log.info("TEST-UNEXPECTED-FAIL | %s | application timed "
|
||||
"out after %d seconds with no output",
|
||||
self.lastTestSeen, int(timeout))
|
||||
return 1
|
||||
|
||||
def getDeviceStatus(self, serial=None):
|
||||
# Get the current status of the device. If we know the device
|
||||
# serial number, we look for that, otherwise we use the (presumably
|
||||
# only) device shown in 'adb devices'.
|
||||
serial = serial or self._devicemanager.deviceSerial
|
||||
status = 'unknown'
|
||||
|
||||
for line in self._devicemanager.runCmd(['devices']).stdout.readlines():
|
||||
result = re.match('(.*?)\t(.*)', line)
|
||||
if result:
|
||||
thisSerial = result.group(1)
|
||||
if not serial or thisSerial == serial:
|
||||
serial = thisSerial
|
||||
status = result.group(2)
|
||||
|
||||
return (serial, status)
|
||||
|
||||
def rebootDevice(self):
|
||||
# find device's current status and serial number
|
||||
serial, status = self.getDeviceStatus()
|
||||
|
||||
# reboot!
|
||||
self._devicemanager.checkCmd(['reboot'])
|
||||
|
||||
# wait for device to come back to previous status
|
||||
print 'waiting for device to come back online after reboot'
|
||||
start = time.time()
|
||||
rserial, rstatus = self.getDeviceStatus(serial)
|
||||
while rstatus != 'device':
|
||||
if time.time() - start > 120:
|
||||
# device hasn't come back online in 2 minutes, something's wrong
|
||||
raise Exception("Device %s (status: %s) not back online after reboot" % (serial, rstatus))
|
||||
time.sleep(5)
|
||||
rserial, rstatus = self.getDeviceStatus(serial)
|
||||
print 'device:', serial, 'status:', rstatus
|
||||
|
||||
def Process(self, cmd, stdout=None, stderr=None, env=None, cwd=None):
|
||||
# On a desktop or fennec run, the Process method invokes a gecko
|
||||
# process in which to run mochitests. For B2G, we simply
|
||||
# reboot the device (which was configured with a test profile
|
||||
# already), wait for B2G to start up, and then navigate to the
|
||||
# test url using Marionette. There doesn't seem to be any way
|
||||
# to pass env variables into the B2G process, but this doesn't
|
||||
# seem to matter.
|
||||
|
||||
instance = self.B2GInstance(self._devicemanager)
|
||||
|
||||
# reboot device so it starts up with the mochitest profile
|
||||
# XXX: We could potentially use 'stop b2g' + 'start b2g' to achieve
|
||||
# a similar effect; will see which is more stable while attempting
|
||||
# to bring up the continuous integration.
|
||||
self.rebootDevice()
|
||||
|
||||
# Infrequently, gecko comes up before networking does, so wait a little
|
||||
# bit to give the network time to become available.
|
||||
# XXX: need a more robust mechanism for this
|
||||
time.sleep(20)
|
||||
|
||||
# Set up port forwarding again for Marionette, since any that
|
||||
# existed previously got wiped out by the reboot.
|
||||
self._devicemanager.checkCmd(['forward',
|
||||
'tcp:%s' % self.marionette.port,
|
||||
'tcp:%s' % self.marionette.port])
|
||||
|
||||
# start a marionette session
|
||||
session = self.marionette.start_session()
|
||||
if 'b2g' not in session:
|
||||
raise Exception("bad session value %s returned by start_session" % session)
|
||||
|
||||
# start the tests by navigating to the mochitest url
|
||||
self.marionette.execute_script("window.location.href='%s';" % self.testURL)
|
||||
|
||||
return instance
|
||||
|
||||
# be careful here as this inner class doesn't have access to outer class members
|
||||
class B2GInstance(object):
|
||||
"""Represents a B2G instance running on a device, and exposes
|
||||
some process-like methods/properties that are expected by the
|
||||
automation.
|
||||
"""
|
||||
|
||||
def __init__(self, dm):
|
||||
self.dm = dm
|
||||
self.lastloglines = []
|
||||
|
||||
@property
|
||||
def pid(self):
|
||||
# a dummy value to make the automation happy
|
||||
return 0
|
||||
|
||||
@property
|
||||
def stdout(self):
|
||||
# Return any part of logcat output that wasn't returned
|
||||
# previously. This is done by fetching about the last 50
|
||||
# lines of the log (logcat -t 50 generally fetches 50-58 lines),
|
||||
# and comparing against the previous set to find new lines.
|
||||
t = self.dm.runCmd(['logcat', '-t', '50']).stdout.read()
|
||||
if t == None: return ''
|
||||
|
||||
t = t.strip('\n').strip()
|
||||
loglines = t.split('\n')
|
||||
line_index = 0
|
||||
|
||||
# If there are more than 50 lines, we skip the first 20; this
|
||||
# is because the number of lines returned
|
||||
# by logcat -t 50 varies (usually between 50 and 58).
|
||||
log_index = 20 if len(loglines) > 50 else 0
|
||||
|
||||
for index, line in enumerate(loglines[log_index:]):
|
||||
line_index = index + log_index + 1
|
||||
try:
|
||||
self.lastloglines.index(line)
|
||||
except ValueError:
|
||||
break
|
||||
|
||||
newoutput = '\n'.join(loglines[line_index:])
|
||||
self.lastloglines = loglines
|
||||
|
||||
return newoutput
|
||||
|
||||
def wait(self, timeout = None):
|
||||
# this should never happen
|
||||
raise Exception("'wait' called on B2GInstance")
|
||||
|
||||
def kill(self):
|
||||
# this should never happen
|
||||
raise Exception("'kill' called on B2GInstance")
|
||||
|
|
@ -137,7 +137,7 @@ public class DoCommand {
|
|||
String ffxProvider = "org.mozilla.ffxcp";
|
||||
String fenProvider = "org.mozilla.fencp";
|
||||
|
||||
private final String prgVersion = "SUTAgentAndroid Version 1.07";
|
||||
private final String prgVersion = "SUTAgentAndroid Version 1.08";
|
||||
|
||||
public enum Command
|
||||
{
|
||||
|
|
|
@ -5,14 +5,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=246699
|
|||
-->
|
||||
<head>
|
||||
<title>Test for Bug 246699</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=246699">Mozilla Bug 246699</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
<iframe id="load-frame"></iframe>
|
||||
<iframe id="load-frame"></iframe>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
@ -21,9 +21,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=246699
|
|||
** Test for Bug 246699
|
||||
** (should produce stack information for caps errors)
|
||||
**/
|
||||
function isError(e)
|
||||
{
|
||||
return e.constructor.name === "Error" || e.constructor.name === "TypeError";
|
||||
}
|
||||
|
||||
function hasStack(e)
|
||||
{
|
||||
return e.constructor.name === "Error" && /inciteCaps/.test(e.stack);
|
||||
return isError(e) && /inciteCaps/.test(e.stack);
|
||||
}
|
||||
|
||||
function inciteCaps(f)
|
||||
|
|
|
@ -119,6 +119,7 @@ MOZ_ENABLE_PROFILER_SPS = @MOZ_ENABLE_PROFILER_SPS@
|
|||
MOZ_JPROF = @MOZ_JPROF@
|
||||
MOZ_SHARK = @MOZ_SHARK@
|
||||
MOZ_CALLGRIND = @MOZ_CALLGRIND@
|
||||
MOZ_VALGRIND = @MOZ_VALGRIND@
|
||||
MOZ_VTUNE = @MOZ_VTUNE@
|
||||
MOZ_ETW = @MOZ_ETW@
|
||||
MOZ_TRACE_JSCALLS = @MOZ_TRACE_JSCALLS@
|
||||
|
|
|
@ -50,8 +50,5 @@ endif
|
|||
|
||||
AUTO_DEPS +=$(GENERATED_DIRS_DEPS)
|
||||
|
||||
|
||||
# Complain loudly if deps have not loaded so getargv != $(NULL)
|
||||
ifndef getargv
|
||||
$(error config/makefiles/makeutil.mk has not been included)
|
||||
endif
|
||||
$(call requiredfunction,getargv)
|
||||
|
|
|
@ -5,13 +5,6 @@
|
|||
# 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/.
|
||||
|
||||
# Usage: $(call banner,foo bar tans)
|
||||
banner =\
|
||||
$(info )\
|
||||
$(info ***************************************************************************)\
|
||||
$(info ** BANNER: $(1) $(2) $(3) $(4) $(5) $(6) $(7) $(8) $(9))\
|
||||
$(info ***************************************************************************)\
|
||||
|
||||
## Identify function argument types
|
||||
istype =$(if $(value ${1}),list,scalar)
|
||||
isval =$(if $(filter-out list,$(call istype,${1})),true)
|
||||
|
@ -35,6 +28,62 @@ argv +=)
|
|||
## getarglist() would be a more accurate name but is longer to type
|
||||
getargv = $(if $(call isvar,$(1)),$($(1)),$(argv))
|
||||
|
||||
###########################################################################
|
||||
# Strip [n] leading options from an argument list. This will allow passing
|
||||
# extra args to user functions that will not propogate to sub-$(call )'s
|
||||
# Usage: $(call subargv,2)
|
||||
subargv =$(wordlist $(1),$(words $(getargv)),$(getargv))
|
||||
|
||||
###########################################################################
|
||||
# Intent: Display a distinct banner heading in the output stream
|
||||
# Usage: $(call banner,BUILDING: foo bar tans)
|
||||
# Debug:
|
||||
# target-preqs = \
|
||||
# $(call banner,target-preqs-BEGIN) \
|
||||
# foo bar tans \
|
||||
# $(call banner,target-preqs-END) \
|
||||
# $(NULL)
|
||||
# target: $(target-preqs)
|
||||
|
||||
banner =\
|
||||
$(info )\
|
||||
$(info ***************************************************************************)\
|
||||
$(info ** $(getargv))\
|
||||
$(info ***************************************************************************)\
|
||||
$(NULL)
|
||||
|
||||
#####################################################################
|
||||
# Intent: Determine if a string or pattern is contained in a list
|
||||
# Usage: strcmp - $(call if_XinY,clean,$(MAKECMDGOALS))
|
||||
# : pattern - $(call if_XinY,clean%,$(MAKECMDGOALS))
|
||||
is_XinY =$(filter $(1),$(call subargv,3,$(getargv)))
|
||||
|
||||
#####################################################################
|
||||
# Provide an alternate var to support testing
|
||||
ifdef MAKEUTILS_UNIT_TEST
|
||||
mcg_goals=TEST_MAKECMDGOALS
|
||||
else
|
||||
mcg_goals=MAKECMDGOALS
|
||||
endif
|
||||
|
||||
# Intent: Conditionals for detecting common/tier target use
|
||||
# Todo: are check, install, test needed ?
|
||||
isTargetStem = $(sort $(foreach pat, $(1)% %$(1), $(call is_XinY,$(pat),${$(mcg_goals)})))
|
||||
isTargetStemClean = $(call isTargetStem,clean)
|
||||
isTargetStemExport = $(call isTargetStem,export)
|
||||
isTargetStemLibs = $(call isTargetStem,libs)
|
||||
isTargetStemTools = $(call isTargetStem,tools)
|
||||
|
||||
##################################################
|
||||
# Intent: Validation functions / unit test helpers
|
||||
|
||||
errorifneq =$(if $(subst $(strip $(1)),$(NULL),$(strip $(2))),$(error expected [$(1)] but found [$(2)]))
|
||||
|
||||
# Intent: verify function declaration exists
|
||||
requiredfunction =$(foreach func,$(1) $(2) $(3) $(4) $(5) $(6) $(7) $(8) $(9),$(if $(value $(func)),$(NULL),$(error required function [$(func)] is unavailable)))
|
||||
|
||||
|
||||
|
||||
## http://www.gnu.org/software/make/manual/make.html#Call-Function
|
||||
## Usage: o = $(call map,origin,o map $(MAKE))
|
||||
map = $(foreach val,$(2),$(call $(1),$(val)))
|
||||
|
|
|
@ -10,6 +10,8 @@ srcdir = @srcdir@
|
|||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MAKEUTILS_UNIT_TEST = 1
|
||||
include $(topsrcdir)/config/makefiles/makeutils.mk
|
||||
|
||||
##------------------_##
|
||||
|
@ -29,9 +31,10 @@ all::
|
|||
check::
|
||||
@true
|
||||
|
||||
###########################################################################
|
||||
## Logic processed at compile time so be selective about when to test
|
||||
ifneq ($(NULL),$(findstring check,$(MAKECMDGOALS))) #{
|
||||
|
||||
## Verify istype, isval, isvar, getargv, subargv
|
||||
ifneq ($(NULL),$(findstring check,$(MAKECMDGOALS))) #
|
||||
|
||||
ifdef VERBOSE
|
||||
|
||||
|
@ -45,11 +48,14 @@ $(info Running test: istype, getargv)
|
|||
$(info ===========================================================================)
|
||||
endif
|
||||
|
||||
## Silent errors are oh so much fun
|
||||
ifndef istype
|
||||
$(error makeutils.mk was not included)
|
||||
ifndef requiredfunction
|
||||
$(error requiredfunction is not defined)
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/config/makefiles/test/check_XinY.mk
|
||||
|
||||
$(call requiredfunc,istype isvar isval)
|
||||
|
||||
# arg_scalar = [scalar|literal]
|
||||
arg_list = foo bar
|
||||
arg_ref = arg_list
|
||||
|
@ -124,4 +130,13 @@ ifdef MANUAL_TEST #{
|
|||
$(error TEST FAILED: processing should not reach this point)
|
||||
endif #}
|
||||
|
||||
endif #} check in MAKECMDGOALS
|
||||
# Verify subargv expansion
|
||||
##########################
|
||||
subargs=foo bar tans fans
|
||||
subargs_exp=tans fans
|
||||
subargs_found=$(call subargv,4,$(subargs))
|
||||
ifneq ($(subargs_exp),$(subargs_found))
|
||||
$(error subargv(4,$(subargs)): expected [$(subargs_exp)] found [$(subargs_found)])
|
||||
endif
|
||||
|
||||
endif #} unit_test: istype, isvar, isval, getargv, subargv
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
# -*- makefile -*-
|
||||
#
|
||||
# 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/.
|
||||
|
||||
# Verify dependencies are available
|
||||
$(call requiredfunction,getargv subargv is_XinY errorifneq)
|
||||
|
||||
#############################
|
||||
ifdef VERBOSE
|
||||
$(warning )
|
||||
$(call banner,Unit test: is_XinY)
|
||||
endif
|
||||
|
||||
zero := 0
|
||||
one := 1
|
||||
|
||||
# Verify 'invalid' is not matched
|
||||
val := invalid
|
||||
$(call errorifneq,$(zero),$(words $(call is_XinY,foo,$(val))))
|
||||
$(call errorifneq,$(zero),$(words $(call is_XinY,clean,$(val))))
|
||||
$(call errorifneq,$(zero),$(words $(call is_XinY,clean%,$(val))))
|
||||
|
||||
# verify strcmp('clean')
|
||||
val := clean
|
||||
$(call errorifneq,$(zero),$(words $(call is_XinY,foo,$(val))))
|
||||
$(call errorifneq,$(one),$(words $(call is_XinY,clean,$(val))))
|
||||
$(call errorifneq,$(one,$(words $(call is_XinY,clean%,$(val)))))
|
||||
$(call errorifneq,$(one),$(words $(call is_XinY,%clean,$(val))))
|
||||
|
||||
# List match for 'clean'
|
||||
val := blah clean distclean FcleanG clean-level-1
|
||||
wanted := clean distclean clean-level-1
|
||||
$(call errorifneq,$(zero),$(words $(call is_XinY_debug,foo,$(val))))
|
||||
$(call errorifneq,$(one),$(words $(call is_XinY,clean,$(val))))
|
||||
$(call errorifneq,$(one),$(words $(call is_XinY,distclean,$(val))))
|
||||
|
||||
# pattern match 'clean'
|
||||
# match: clean, distclean, clean-level-1
|
||||
# exclude: FcleanG
|
||||
TEST_MAKECMDGOALS := $(val)
|
||||
$(call errorifneq,3,$(words $(call isTargetStemClean)))
|
||||
|
||||
TEST_MAKECMDGOALS := invalid
|
||||
$(call errorifneq,$(zero),$(words $(call isTargetStemClean)))
|
||||
|
21
configure.in
|
@ -4609,15 +4609,7 @@ MOZ_USE_NATIVE_POPUP_WINDOWS=
|
|||
MOZ_ANDROID_HISTORY=
|
||||
MOZ_WEBSMS_BACKEND=
|
||||
MOZ_GRAPHITE=1
|
||||
|
||||
case "${target}" in
|
||||
*darwin*)
|
||||
ACCESSIBILITY=
|
||||
;;
|
||||
*)
|
||||
ACCESSIBILITY=1
|
||||
;;
|
||||
esac
|
||||
ACCESSIBILITY=1
|
||||
|
||||
case "$target_os" in
|
||||
mingw*)
|
||||
|
@ -5550,10 +5542,9 @@ AC_DEFINE(IBMBIDI)
|
|||
|
||||
dnl ========================================================
|
||||
dnl accessibility support on by default on all platforms
|
||||
dnl except OS X.
|
||||
dnl ========================================================
|
||||
MOZ_ARG_DISABLE_BOOL(accessibility,
|
||||
[ --disable-accessibility Disable accessibility support (off by default on OS X)],
|
||||
[ --disable-accessibility Disable accessibility support],
|
||||
ACCESSIBILITY=,
|
||||
ACCESSIBILITY=1 )
|
||||
if test "$ACCESSIBILITY"; then
|
||||
|
@ -5835,14 +5826,10 @@ dnl = Check alsa availability on Linux if using sydneyaudio
|
|||
dnl ========================================================
|
||||
|
||||
dnl If using sydneyaudio with Linux, ensure that the alsa library is available
|
||||
if test -n "$MOZ_SYDNEYAUDIO"; then
|
||||
case "$target_os" in
|
||||
linux*)
|
||||
PKG_CHECK_MODULES(MOZ_ALSA, alsa, ,
|
||||
if test -n "$MOZ_SYDNEYAUDIO" -a "$OS_TARGET" = "Linux"; then
|
||||
PKG_CHECK_MODULES(MOZ_ALSA, alsa, ,
|
||||
[echo "$MOZ_ALSA_PKG_ERRORS"
|
||||
AC_MSG_ERROR([Need alsa for Ogg, Wave or WebM decoding on Linux. Disable with --disable-ogg --disable-wave --disable-webm. (On Ubuntu, you might try installing the package libasound2-dev.)])])
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
dnl ========================================================
|
||||
|
|
|
@ -402,7 +402,7 @@ public:
|
|||
|
||||
/**
|
||||
* Return this node as an Element. Should only be used for nodes
|
||||
* for which IsElement() is true.
|
||||
* for which IsElement() is true. This is defined inline in Element.h.
|
||||
*/
|
||||
mozilla::dom::Element* AsElement();
|
||||
|
||||
|
@ -755,9 +755,9 @@ public:
|
|||
* Get the parent nsINode for this node if it is an Element.
|
||||
* @return the parent node
|
||||
*/
|
||||
nsINode* GetElementParent() const
|
||||
mozilla::dom::Element* GetElementParent() const
|
||||
{
|
||||
return mParent && mParent->IsElement() ? mParent : nsnull;
|
||||
return mParent && mParent->IsElement() ? mParent->AsElement() : nsnull;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -362,12 +362,6 @@ nsCCUncollectableMarker::Observe(nsISupports* aSubject, const char* aTopic,
|
|||
}
|
||||
}
|
||||
|
||||
if (cleanupJS) {
|
||||
nsContentUtils::UnmarkGrayJSListenersInCCGenerationDocuments(sGeneration);
|
||||
MarkMessageManagers();
|
||||
xpc_UnmarkSkippableJSHolders();
|
||||
}
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
nsXULPrototypeCache* xulCache = nsXULPrototypeCache::GetInstance();
|
||||
if (xulCache) {
|
||||
|
@ -375,6 +369,18 @@ nsCCUncollectableMarker::Observe(nsISupports* aSubject, const char* aTopic,
|
|||
}
|
||||
#endif
|
||||
|
||||
static bool previousWasJSCleanup = false;
|
||||
if (cleanupJS) {
|
||||
nsContentUtils::UnmarkGrayJSListenersInCCGenerationDocuments(sGeneration);
|
||||
MarkMessageManagers();
|
||||
previousWasJSCleanup = true;
|
||||
} else if (previousWasJSCleanup) {
|
||||
previousWasJSCleanup = false;
|
||||
if (!prepareForCC) {
|
||||
xpc_UnmarkSkippableJSHolders();
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -132,7 +132,7 @@ public:
|
|||
// Called by the video decoder object, on the main thread,
|
||||
// when it has read the metadata containing video dimensions,
|
||||
// etc.
|
||||
void MetadataLoaded(PRUint32 aChannels, PRUint32 aRate);
|
||||
void MetadataLoaded(PRUint32 aChannels, PRUint32 aRate, bool aHasAudio);
|
||||
|
||||
// Called by the video decoder object, on the main thread,
|
||||
// when it has read the first frame of the video
|
||||
|
@ -794,6 +794,9 @@ protected:
|
|||
|
||||
// The CORS mode when loading the media element
|
||||
mozilla::CORSMode mCORSMode;
|
||||
|
||||
// True if the media has an audio track
|
||||
bool mHasAudio;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -177,7 +177,7 @@ nsHTMLAudioElement::MozSetup(PRUint32 aChannels, PRUint32 aRate)
|
|||
return rv;
|
||||
}
|
||||
|
||||
MetadataLoaded(aChannels, aRate);
|
||||
MetadataLoaded(aChannels, aRate, true);
|
||||
mAudioStream->SetVolume(mVolume);
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -1459,7 +1459,8 @@ nsHTMLMediaElement::nsHTMLMediaElement(already_AddRefed<nsINodeInfo> aNodeInfo)
|
|||
mShuttingDown(false),
|
||||
mLoadIsSuspended(false),
|
||||
mMediaSecurityVerified(false),
|
||||
mCORSMode(CORS_NONE)
|
||||
mCORSMode(CORS_NONE),
|
||||
mHasAudio(false)
|
||||
{
|
||||
#ifdef PR_LOGGING
|
||||
if (!gMediaElementLog) {
|
||||
|
@ -2258,10 +2259,11 @@ void nsHTMLMediaElement::ProcessMediaFragmentURI()
|
|||
}
|
||||
}
|
||||
|
||||
void nsHTMLMediaElement::MetadataLoaded(PRUint32 aChannels, PRUint32 aRate)
|
||||
void nsHTMLMediaElement::MetadataLoaded(PRUint32 aChannels, PRUint32 aRate, bool aHasAudio)
|
||||
{
|
||||
mChannels = aChannels;
|
||||
mRate = aRate;
|
||||
mHasAudio = aHasAudio;
|
||||
ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_METADATA);
|
||||
DispatchAsyncEvent(NS_LITERAL_STRING("durationchange"));
|
||||
DispatchAsyncEvent(NS_LITERAL_STRING("loadedmetadata"));
|
||||
|
|
|
@ -219,3 +219,11 @@ NS_IMETHODIMP nsHTMLVideoElement::GetMozFrameDelay(double *aMozFrameDelay) {
|
|||
*aMozFrameDelay = container ? container->GetFrameDelay() : 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
/* readonly attribute bool mozHasAudio */
|
||||
NS_IMETHODIMP nsHTMLVideoElement::GetMozHasAudio(bool *aHasAudio) {
|
||||
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
|
||||
*aHasAudio = mHasAudio;
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -72,6 +72,7 @@ class nsHTMLDocument : public nsDocument,
|
|||
{
|
||||
public:
|
||||
using nsDocument::SetDocumentURI;
|
||||
using nsDocument::GetPlugins;
|
||||
|
||||
nsHTMLDocument();
|
||||
virtual nsresult Init();
|
||||
|
|
|
@ -408,7 +408,8 @@ void nsBuiltinDecoder::AudioAvailable(float* aFrameBuffer,
|
|||
}
|
||||
|
||||
void nsBuiltinDecoder::MetadataLoaded(PRUint32 aChannels,
|
||||
PRUint32 aRate)
|
||||
PRUint32 aRate,
|
||||
bool aHasAudio)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
|
||||
if (mShuttingDown) {
|
||||
|
@ -435,7 +436,7 @@ void nsBuiltinDecoder::MetadataLoaded(PRUint32 aChannels,
|
|||
// Make sure the element and the frame (if any) are told about
|
||||
// our new size.
|
||||
Invalidate();
|
||||
mElement->MetadataLoaded(aChannels, aRate);
|
||||
mElement->MetadataLoaded(aChannels, aRate, aHasAudio);
|
||||
}
|
||||
|
||||
if (!mResourceLoaded) {
|
||||
|
|
|
@ -555,7 +555,8 @@ public:
|
|||
// Called when the metadata from the media file has been read.
|
||||
// Call on the main thread only.
|
||||
void MetadataLoaded(PRUint32 aChannels,
|
||||
PRUint32 aRate);
|
||||
PRUint32 aRate,
|
||||
bool aHasAudio);
|
||||
|
||||
// Called when the first frame has been loaded.
|
||||
// Call on the main thread only.
|
||||
|
|
|
@ -152,21 +152,23 @@ private:
|
|||
nsCOMPtr<nsBuiltinDecoder> mDecoder;
|
||||
public:
|
||||
nsAudioMetadataEventRunner(nsBuiltinDecoder* aDecoder, PRUint32 aChannels,
|
||||
PRUint32 aRate) :
|
||||
PRUint32 aRate, bool aHasAudio) :
|
||||
mDecoder(aDecoder),
|
||||
mChannels(aChannels),
|
||||
mRate(aRate)
|
||||
mRate(aRate),
|
||||
mHasAudio(aHasAudio)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
mDecoder->MetadataLoaded(mChannels, mRate);
|
||||
mDecoder->MetadataLoaded(mChannels, mRate, mHasAudio);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
const PRUint32 mChannels;
|
||||
const PRUint32 mRate;
|
||||
const bool mHasAudio;
|
||||
};
|
||||
|
||||
// Owns the global state machine thread and counts of
|
||||
|
@ -1515,7 +1517,7 @@ nsresult nsBuiltinDecoderStateMachine::DecodeMetadata()
|
|||
mDecoder->RequestFrameBufferLength(frameBufferLength);
|
||||
}
|
||||
nsCOMPtr<nsIRunnable> metadataLoadedEvent =
|
||||
new nsAudioMetadataEventRunner(mDecoder, mInfo.mAudioChannels, mInfo.mAudioRate);
|
||||
new nsAudioMetadataEventRunner(mDecoder, mInfo.mAudioChannels, mInfo.mAudioRate, HasAudio());
|
||||
NS_DispatchToMainThread(metadataLoadedEvent, NS_DISPATCH_NORMAL);
|
||||
|
||||
if (mState == DECODER_STATE_DECODING_METADATA) {
|
||||
|
|
|
@ -156,6 +156,7 @@ _TEST_FILES = \
|
|||
test_video_to_canvas.html \
|
||||
use_large_cache.js \
|
||||
test_audiowrite.html \
|
||||
test_mozHasAudio.html \
|
||||
$(NULL)
|
||||
|
||||
# Don't run in suite
|
||||
|
|
|
@ -47,6 +47,15 @@ var gPausedAfterEndedTests = gSmallTests.concat([
|
|||
{ name:"small-shot.ogg", type:"video/ogg", duration:0.276 }
|
||||
]);
|
||||
|
||||
// Test the mozHasAudio property
|
||||
var gMozHasAudioTests = [
|
||||
{ name:"big.wav", type:"audio/x-wav", duration:9.278981, size:102444, hasAudio:undefined },
|
||||
{ name:"320x240.ogv", type:"video/ogg", width:320, height:240, duration:0.233, size:28942, hasAudio:false },
|
||||
{ name:"short-video.ogv", type:"video/ogg", duration:1.081, hasAudio:true },
|
||||
{ name:"seek.webm", type:"video/webm", duration:3.966, size:215529, hasAudio:false },
|
||||
{ name:"bogus.duh", type:"bogus/duh" }
|
||||
];
|
||||
|
||||
// These are files that we want to make sure we can play through. We can
|
||||
// also check metadata. Put files of the same type together in this list so if
|
||||
// something crashes we have some idea of which backend is responsible.
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test playback of media files that should play OK</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
<script type="text/javascript" src="manifest.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
var manager = new MediaTestManager;
|
||||
|
||||
function onloadedmetadata(e) {
|
||||
var t = e.target;
|
||||
is(t.mozHasAudio, t.hasAudio, "The element reports the wrong audio property." + t.token);
|
||||
manager.finished(t.token);
|
||||
}
|
||||
|
||||
function startTest(test, token) {
|
||||
var elemType = /^audio/.test(test.type) ? "audio" : "video";
|
||||
var element = document.createElement(elemType);
|
||||
|
||||
element.token = token;
|
||||
manager.started(token);
|
||||
|
||||
element.src = test.name;
|
||||
element.name = test.name;
|
||||
element.hasAudio = test.hasAudio;
|
||||
element.addEventListener("loadedmetadata", onloadedmetadata, false);
|
||||
|
||||
element.load();
|
||||
}
|
||||
|
||||
manager.runTests(gMozHasAudioTests, startTest);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -3896,6 +3896,10 @@ nsDocShell::LoadURI(const PRUnichar * aURI,
|
|||
|
||||
rv = LoadURI(uri, loadInfo, extraFlags, true);
|
||||
|
||||
// Save URI string in case it's needed later when
|
||||
// sending to search engine service in EndPageLoad()
|
||||
mOriginalUriString = uriString;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -6355,27 +6359,33 @@ nsDocShell::EndPageLoad(nsIWebProgress * aProgress,
|
|||
|
||||
if (keywordsEnabled && (kNotFound == dotLoc)) {
|
||||
// only send non-qualified hosts to the keyword server
|
||||
//
|
||||
// If this string was passed through nsStandardURL by
|
||||
// chance, then it may have been converted from UTF-8 to
|
||||
// ACE, which would result in a completely bogus keyword
|
||||
// query. Here we try to recover the original Unicode
|
||||
// value, but this is not 100% correct since the value may
|
||||
// have been normalized per the IDN normalization rules.
|
||||
//
|
||||
// Since we don't have access to the exact original string
|
||||
// that was entered by the user, this will just have to do.
|
||||
bool isACE;
|
||||
nsCAutoString utf8Host;
|
||||
nsCOMPtr<nsIIDNService> idnSrv =
|
||||
do_GetService(NS_IDNSERVICE_CONTRACTID);
|
||||
if (idnSrv &&
|
||||
NS_SUCCEEDED(idnSrv->IsACE(host, &isACE)) && isACE &&
|
||||
NS_SUCCEEDED(idnSrv->ConvertACEtoUTF8(host, utf8Host)))
|
||||
sURIFixup->KeywordToURI(utf8Host,
|
||||
if (!mOriginalUriString.IsEmpty()) {
|
||||
sURIFixup->KeywordToURI(mOriginalUriString,
|
||||
getter_AddRefs(newURI));
|
||||
else
|
||||
sURIFixup->KeywordToURI(host, getter_AddRefs(newURI));
|
||||
}
|
||||
else {
|
||||
//
|
||||
// If this string was passed through nsStandardURL by
|
||||
// chance, then it may have been converted from UTF-8 to
|
||||
// ACE, which would result in a completely bogus keyword
|
||||
// query. Here we try to recover the original Unicode
|
||||
// value, but this is not 100% correct since the value may
|
||||
// have been normalized per the IDN normalization rules.
|
||||
//
|
||||
// Since we don't have access to the exact original string
|
||||
// that was entered by the user, this will just have to do.
|
||||
bool isACE;
|
||||
nsCAutoString utf8Host;
|
||||
nsCOMPtr<nsIIDNService> idnSrv =
|
||||
do_GetService(NS_IDNSERVICE_CONTRACTID);
|
||||
if (idnSrv &&
|
||||
NS_SUCCEEDED(idnSrv->IsACE(host, &isACE)) && isACE &&
|
||||
NS_SUCCEEDED(idnSrv->ConvertACEtoUTF8(host, utf8Host)))
|
||||
sURIFixup->KeywordToURI(utf8Host,
|
||||
getter_AddRefs(newURI));
|
||||
else
|
||||
sURIFixup->KeywordToURI(host, getter_AddRefs(newURI));
|
||||
}
|
||||
} // end keywordsEnabled
|
||||
}
|
||||
|
||||
|
@ -8070,6 +8080,7 @@ nsDocShell::InternalLoad(nsIURI * aURI,
|
|||
nsIRequest** aRequest)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
mOriginalUriString.Truncate();
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
if (gDocShellLeakLog && PR_LOG_TEST(gDocShellLeakLog, PR_LOG_DEBUG)) {
|
||||
|
|
|
@ -848,7 +848,8 @@ private:
|
|||
nsCOMPtr<nsIAtom> mForcedCharset;
|
||||
nsCOMPtr<nsIAtom> mParentCharset;
|
||||
nsTObserverArray<nsWeakPtr> mPrivacyObservers;
|
||||
PRInt32 mParentCharsetSource;
|
||||
PRInt32 mParentCharsetSource;
|
||||
nsCString mOriginalUriString;
|
||||
|
||||
#ifdef DEBUG
|
||||
// We're counting the number of |nsDocShells| to help find leaks
|
||||
|
|
|
@ -535,6 +535,8 @@ using mozilla::dom::indexedDB::IDBWrapperCache;
|
|||
#include "DOMError.h"
|
||||
#include "DOMRequest.h"
|
||||
|
||||
#include "mozilla/Likely.h"
|
||||
|
||||
#undef None // something included above defines this preprocessor symbol, maybe Xlib headers
|
||||
#include "WebGLContext.h"
|
||||
|
||||
|
@ -1968,6 +1970,23 @@ WrapNativeParent(JSContext *cx, JSObject *scope, nsISupports *native,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// Helper to handle torn-down inner windows.
|
||||
static inline nsresult
|
||||
SetParentToWindow(nsGlobalWindow *win, JSObject **parent)
|
||||
{
|
||||
MOZ_ASSERT(win);
|
||||
MOZ_ASSERT(win->IsInnerWindow());
|
||||
*parent = win->FastGetGlobalJSObject();
|
||||
|
||||
if (MOZ_UNLIKELY(!*parent)) {
|
||||
// The only known case where this can happen is when the inner window has
|
||||
// been torn down. See bug 691178 comment 11.
|
||||
MOZ_ASSERT(win->IsClosedOrClosing());
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// static
|
||||
|
||||
nsISupports *
|
||||
|
@ -4629,8 +4648,9 @@ nsDOMClassInfo::PreCreate(nsISupports *nativeObj, JSContext *cx,
|
|||
}
|
||||
|
||||
if (piwin->IsOuterWindow()) {
|
||||
*parentObj = ((nsGlobalWindow *)piwin.get())->
|
||||
GetCurrentInnerWindowInternal()->GetGlobalJSObject();
|
||||
nsGlobalWindow *win = ((nsGlobalWindow *)piwin.get())->
|
||||
GetCurrentInnerWindowInternal();
|
||||
return SetParentToWindow(win, parentObj);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -5165,20 +5185,15 @@ nsWindowSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
|
|||
nsGlobalWindow *win = nsGlobalWindow::FromSupports(nativeObj);
|
||||
NS_ASSERTION(win->IsInnerWindow(), "Should be inner window.");
|
||||
|
||||
JSObject *winObj = win->FastGetGlobalJSObject();
|
||||
if (!winObj) {
|
||||
// We sometimes get a disconnected window during file api test. :-(
|
||||
if (!win->GetOuterWindowInternal())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// See bug 691178 comment 11 for why this is necessary.
|
||||
if (win->IsClosedOrClosing())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
NS_ASSERTION(win->GetOuterWindowInternal()->IsCreatingInnerWindow(),
|
||||
"should have a JS object by this point");
|
||||
// If we're bootstrapping, we don't have a JS object yet.
|
||||
if (win->GetOuterWindowInternal()->IsCreatingInnerWindow())
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
*parentObj = winObj;
|
||||
return NS_OK;
|
||||
return SetParentToWindow(win, parentObj);
|
||||
}
|
||||
|
||||
// This JS class piggybacks on nsHTMLDocumentSH::ReleaseDocument()...
|
||||
|
@ -6029,8 +6044,7 @@ nsDOMConstructor::PreCreate(JSContext *cx, JSObject *globalObj, JSObject **paren
|
|||
}
|
||||
|
||||
nsGlobalWindow *win = static_cast<nsGlobalWindow *>(owner.get());
|
||||
*parentObj = win->FastGetGlobalJSObject();
|
||||
return NS_OK;
|
||||
return SetParentToWindow(win, parentObj);
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -7480,7 +7494,7 @@ nsLocationSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
|
|||
}
|
||||
|
||||
*parentObj = sgo->GetGlobalJSObject();
|
||||
return NS_OK;
|
||||
return *parentObj ? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// DOM Navigator helper
|
||||
|
@ -7579,14 +7593,7 @@ nsNavigatorSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
|
|||
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
JSObject *global = win->GetGlobalJSObject();
|
||||
|
||||
if (global) {
|
||||
*parentObj = global;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
return SetParentToWindow(win, parentObj);
|
||||
}
|
||||
|
||||
// DOM Node helper
|
||||
|
@ -7853,7 +7860,7 @@ nsEventTargetSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
|
|||
|
||||
*parentObj = native_parent ? native_parent->GetGlobalJSObject() : globalObj;
|
||||
|
||||
return NS_OK;
|
||||
return *parentObj ? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -10005,9 +10012,8 @@ nsHistorySH::PreCreate(nsISupports *nativeObj, JSContext *cx,
|
|||
NS_WARNING("refusing to create history object in the wrong scope");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
*parentObj = static_cast<nsGlobalWindow *>(innerWindow.get())->FastGetGlobalJSObject();
|
||||
return NS_OK;
|
||||
return SetParentToWindow(static_cast<nsGlobalWindow *>(innerWindow.get()),
|
||||
parentObj);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -95,6 +95,12 @@ public:
|
|||
nsresult TimeStampToDOMOrFetchStart(mozilla::TimeStamp aStamp,
|
||||
DOMTimeMilliSec* aResult);
|
||||
|
||||
inline DOMHighResTimeStamp TimeStampToDOMHighRes(mozilla::TimeStamp aStamp)
|
||||
{
|
||||
mozilla::TimeDuration duration = aStamp - mNavigationStartTimeStamp;
|
||||
return duration.ToMilliseconds();
|
||||
}
|
||||
|
||||
private:
|
||||
nsDOMNavigationTiming(const nsDOMNavigationTiming &){};
|
||||
~nsDOMNavigationTiming();
|
||||
|
|
|
@ -319,3 +319,11 @@ nsPerformance::GetNavigation(nsIDOMPerformanceNavigation** aNavigation)
|
|||
NS_IF_ADDREF(*aNavigation = mNavigation);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPerformance::Now(DOMHighResTimeStamp* aNow)
|
||||
{
|
||||
*aNow = mDOMTiming->TimeStampToDOMHighRes(mozilla::TimeStamp::Now());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -801,7 +801,8 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
|
|||
properties should be a PropertyArrays instance.
|
||||
"""
|
||||
def __init__(self, descriptor, properties):
|
||||
args = [Argument('JSContext*', 'aCx'), Argument('JSObject*', 'aGlobal')]
|
||||
args = [Argument('JSContext*', 'aCx'), Argument('JSObject*', 'aGlobal'),
|
||||
Argument('JSObject*', 'aReceiver')]
|
||||
CGAbstractMethod.__init__(self, descriptor, 'CreateInterfaceObjects', 'JSObject*', args)
|
||||
self.properties = properties
|
||||
def definition_body(self):
|
||||
|
@ -810,7 +811,7 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
|
|||
getParentProto = "JS_GetObjectPrototype(aCx, aGlobal)"
|
||||
else:
|
||||
parentProtoName = self.descriptor.prototypeChain[-2]
|
||||
getParentProto = "%s::GetProtoObject(aCx, aGlobal)" % (parentProtoName)
|
||||
getParentProto = "%s::GetProtoObject(aCx, aGlobal, aReceiver)" % (parentProtoName)
|
||||
|
||||
needInterfaceObject = self.descriptor.interface.hasInterfaceObject()
|
||||
needInterfacePrototypeObject = self.descriptor.interface.hasInterfacePrototypeObject()
|
||||
|
@ -849,7 +850,7 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
|
|||
" return NULL;\n"
|
||||
"}") % getParentProto
|
||||
|
||||
call = CGGeneric(("return bindings::CreateInterfaceObjects(aCx, aGlobal, parentProto,\n"
|
||||
call = CGGeneric(("return bindings::CreateInterfaceObjects(aCx, aGlobal, aReceiver, parentProto,\n"
|
||||
" %s, %s,\n"
|
||||
" %%(methods)s, %%(attrs)s, %%(consts)s, %%(staticMethods)s,\n"
|
||||
" %s);") % (
|
||||
|
@ -880,12 +881,20 @@ class CGGetPerInterfaceObject(CGAbstractMethod):
|
|||
constructor object).
|
||||
"""
|
||||
def __init__(self, descriptor, name, idPrefix=""):
|
||||
args = [Argument('JSContext*', 'aCx'), Argument('JSObject*', 'aGlobal')]
|
||||
args = [Argument('JSContext*', 'aCx'), Argument('JSObject*', 'aGlobal'),
|
||||
Argument('JSObject*', 'aReceiver')]
|
||||
CGAbstractMethod.__init__(self, descriptor, name,
|
||||
'JSObject*', args, inline=True)
|
||||
self.id = idPrefix + "id::" + self.descriptor.name
|
||||
def definition_body(self):
|
||||
return """
|
||||
|
||||
/* aGlobal and aReceiver are usually the same, but they can be different
|
||||
too. For example a sandbox often has an xray wrapper for a window as the
|
||||
prototype of the sandbox's global. In that case aReceiver is the xray
|
||||
wrapper and aGlobal is the sandbox's global.
|
||||
*/
|
||||
|
||||
/* Make sure our global is sane. Hopefully we can remove this sometime */
|
||||
if (!(js::GetObjectClass(aGlobal)->flags & JSCLASS_DOM_GLOBAL)) {
|
||||
return NULL;
|
||||
|
@ -894,7 +903,7 @@ class CGGetPerInterfaceObject(CGAbstractMethod):
|
|||
JSObject** protoOrIfaceArray = GetProtoOrIfaceArray(aGlobal);
|
||||
JSObject* cachedObject = protoOrIfaceArray[%s];
|
||||
if (!cachedObject) {
|
||||
protoOrIfaceArray[%s] = cachedObject = CreateInterfaceObjects(aCx, aGlobal);
|
||||
protoOrIfaceArray[%s] = cachedObject = CreateInterfaceObjects(aCx, aGlobal, aReceiver);
|
||||
}
|
||||
|
||||
/* cachedObject might _still_ be null, but that's OK */
|
||||
|
@ -905,7 +914,6 @@ class CGGetProtoObjectMethod(CGGetPerInterfaceObject):
|
|||
A method for getting the interface prototype object.
|
||||
"""
|
||||
def __init__(self, descriptor):
|
||||
args = [Argument('JSContext*', 'aCx'), Argument('JSObject*', 'aGlobal')]
|
||||
CGGetPerInterfaceObject.__init__(self, descriptor, "GetProtoObject")
|
||||
def definition_body(self):
|
||||
return """
|
||||
|
@ -917,14 +925,13 @@ class CGGetConstructorObjectMethod(CGGetPerInterfaceObject):
|
|||
A method for getting the interface constructor object.
|
||||
"""
|
||||
def __init__(self, descriptor):
|
||||
args = [Argument('JSContext*', 'aCx'), Argument('JSObject*', 'aGlobal')]
|
||||
CGGetPerInterfaceObject.__init__(self, descriptor, "GetConstructorObject", "constructors::")
|
||||
def definition_body(self):
|
||||
return """
|
||||
/* Get the interface object for this class. This will create the object as
|
||||
needed. */""" + CGGetPerInterfaceObject.definition_body(self)
|
||||
|
||||
def CheckPref(descriptor, scopeName, varName, retval, wrapperCache = None):
|
||||
def CheckPref(descriptor, globalName, varName, retval, wrapperCache = None):
|
||||
"""
|
||||
Check whether bindings should be enabled for this descriptor. If not, set
|
||||
varName to false and return retval.
|
||||
|
@ -932,15 +939,23 @@ def CheckPref(descriptor, scopeName, varName, retval, wrapperCache = None):
|
|||
if not descriptor.prefable:
|
||||
return ""
|
||||
if wrapperCache:
|
||||
wrapperCache = "%s->ClearIsDOMBinding();\n" % (wrapperCache)
|
||||
wrapperCache = " %s->ClearIsDOMBinding();\n" % (wrapperCache)
|
||||
else:
|
||||
wrapperCache = ""
|
||||
return """
|
||||
if (!%s->ExperimentalBindingsEnabled()) {
|
||||
%s %s = false;
|
||||
return %s;
|
||||
{
|
||||
XPCWrappedNativeScope* scope =
|
||||
XPCWrappedNativeScope::FindInJSObjectScope(aCx, %s);
|
||||
if (!scope) {
|
||||
return %s;
|
||||
}
|
||||
|
||||
if (!scope->ExperimentalBindingsEnabled()) {
|
||||
%s %s = false;
|
||||
return %s;
|
||||
}
|
||||
}
|
||||
""" % (scopeName, wrapperCache, varName, retval)
|
||||
""" % (globalName, retval, wrapperCache, varName, retval)
|
||||
|
||||
class CGDefineDOMInterfaceMethod(CGAbstractMethod):
|
||||
"""
|
||||
|
@ -948,7 +963,7 @@ class CGDefineDOMInterfaceMethod(CGAbstractMethod):
|
|||
a given interface.
|
||||
"""
|
||||
def __init__(self, descriptor):
|
||||
args = [Argument('JSContext*', 'aCx'), Argument('XPCWrappedNativeScope*', 'aScope'),
|
||||
args = [Argument('JSContext*', 'aCx'), Argument('JSObject*', 'aReceiver'),
|
||||
Argument('bool*', 'aEnabled')]
|
||||
CGAbstractMethod.__init__(self, descriptor, 'DefineDOMInterface', 'bool', args)
|
||||
|
||||
|
@ -970,9 +985,11 @@ class CGDefineDOMInterfaceMethod(CGAbstractMethod):
|
|||
else:
|
||||
getter = "GetConstructorObject"
|
||||
|
||||
return CheckPref(self.descriptor, "aScope", "*aEnabled", "false") + """
|
||||
return (" JSObject* global = JS_GetGlobalForObject(aCx, aReceiver);\n" +
|
||||
CheckPref(self.descriptor, "global", "*aEnabled", "false") +
|
||||
"""
|
||||
*aEnabled = true;
|
||||
return !!%s(aCx, aScope->GetGlobalJSObject());""" % (getter)
|
||||
return !!%s(aCx, global, aReceiver);""" % (getter))
|
||||
|
||||
class CGNativeToSupportsMethod(CGAbstractStaticMethod):
|
||||
"""
|
||||
|
@ -1022,13 +1039,9 @@ class CGWrapMethod(CGAbstractMethod):
|
|||
}
|
||||
}
|
||||
|
||||
XPCWrappedNativeScope* scope =
|
||||
XPCWrappedNativeScope::FindInJSObjectScope(aCx, parent);
|
||||
if (!scope) {
|
||||
return NULL;
|
||||
}
|
||||
JSObject* global = JS_GetGlobalForObject(aCx, parent);
|
||||
%s
|
||||
JSObject* proto = GetProtoObject(aCx, scope->GetGlobalJSObject());
|
||||
JSObject* proto = GetProtoObject(aCx, global, global);
|
||||
if (!proto) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1043,7 +1056,7 @@ class CGWrapMethod(CGAbstractMethod):
|
|||
|
||||
aObject->SetWrapper(obj);
|
||||
|
||||
return obj;""" % (CheckPref(self.descriptor, "scope", "*aTriedToWrap", "NULL", "aObject"))
|
||||
return obj;""" % (CheckPref(self.descriptor, "global", "*aTriedToWrap", "NULL", "aObject"))
|
||||
|
||||
builtinNames = {
|
||||
IDLType.Tags.bool: 'bool',
|
||||
|
|
|
@ -25,7 +25,7 @@ DefineConstants(JSContext* cx, JSObject* obj, ConstantSpec* cs)
|
|||
}
|
||||
|
||||
static JSObject*
|
||||
CreateInterfaceObject(JSContext* cx, JSObject* global,
|
||||
CreateInterfaceObject(JSContext* cx, JSObject* global, JSObject* receiver,
|
||||
JSClass* constructorClass, JSObject* proto,
|
||||
JSFunctionSpec* staticMethods, ConstantSpec* constants,
|
||||
const char* name)
|
||||
|
@ -54,7 +54,7 @@ CreateInterfaceObject(JSContext* cx, JSObject* global,
|
|||
}
|
||||
|
||||
// This is Enumerable: False per spec.
|
||||
if (!JS_DefineProperty(cx, global, name, OBJECT_TO_JSVAL(constructor), NULL,
|
||||
if (!JS_DefineProperty(cx, receiver, name, OBJECT_TO_JSVAL(constructor), NULL,
|
||||
NULL, 0)) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -91,11 +91,11 @@ CreateInterfacePrototypeObject(JSContext* cx, JSObject* global,
|
|||
}
|
||||
|
||||
JSObject*
|
||||
CreateInterfaceObjects(JSContext *cx, JSObject *global, JSObject *parentProto,
|
||||
JSClass *protoClass, JSClass *constructorClass,
|
||||
JSFunctionSpec *methods, JSPropertySpec *properties,
|
||||
ConstantSpec *constants, JSFunctionSpec *staticMethods,
|
||||
const char* name)
|
||||
CreateInterfaceObjects(JSContext* cx, JSObject* global, JSObject *receiver,
|
||||
JSObject* protoProto, JSClass* protoClass,
|
||||
JSClass* constructorClass, JSFunctionSpec* methods,
|
||||
JSPropertySpec* properties, ConstantSpec* constants,
|
||||
JSFunctionSpec* staticMethods, const char* name)
|
||||
{
|
||||
MOZ_ASSERT(protoClass || constructorClass, "Need at least one class!");
|
||||
MOZ_ASSERT(!(methods || properties) || protoClass,
|
||||
|
@ -107,7 +107,7 @@ CreateInterfaceObjects(JSContext *cx, JSObject *global, JSObject *parentProto,
|
|||
|
||||
JSObject* proto;
|
||||
if (protoClass) {
|
||||
proto = CreateInterfacePrototypeObject(cx, global, parentProto, protoClass,
|
||||
proto = CreateInterfacePrototypeObject(cx, global, protoProto, protoClass,
|
||||
methods, properties, constants);
|
||||
if (!proto) {
|
||||
return NULL;
|
||||
|
@ -119,8 +119,8 @@ CreateInterfaceObjects(JSContext *cx, JSObject *global, JSObject *parentProto,
|
|||
|
||||
JSObject* interface;
|
||||
if (constructorClass) {
|
||||
interface = CreateInterfaceObject(cx, global, constructorClass, proto,
|
||||
staticMethods, constants, name);
|
||||
interface = CreateInterfaceObject(cx, global, receiver, constructorClass,
|
||||
proto, staticMethods, constants, name);
|
||||
if (!interface) {
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -219,7 +219,11 @@ struct ConstantSpec
|
|||
* Create a DOM interface object (if constructorClass is non-null) and/or a
|
||||
* DOM interface prototype object (if protoClass is non-null).
|
||||
*
|
||||
* parentProto is the prototype to use for the interface prototype object.
|
||||
* global is used as the parent of the interface object and the interface
|
||||
* prototype object
|
||||
* receiver is the object on which we need to define the interface object as a
|
||||
* property
|
||||
* protoProto is the prototype to use for the interface prototype object.
|
||||
* protoClass is the JSClass to use for the interface prototype object.
|
||||
* This is null if we should not create an interface prototype
|
||||
* object.
|
||||
|
@ -242,11 +246,11 @@ struct ConstantSpec
|
|||
* returns the interface object.
|
||||
*/
|
||||
JSObject*
|
||||
CreateInterfaceObjects(JSContext* cx, JSObject* global, JSObject* parentProto,
|
||||
JSClass* protoClass, JSClass* constructorClass,
|
||||
JSFunctionSpec* methods, JSPropertySpec* properties,
|
||||
ConstantSpec* constants, JSFunctionSpec* staticMethods,
|
||||
const char* name);
|
||||
CreateInterfaceObjects(JSContext* cx, JSObject* global, JSObject* receiver,
|
||||
JSObject* protoProto, JSClass* protoClass,
|
||||
JSClass* constructorClass, JSFunctionSpec* methods,
|
||||
JSPropertySpec* properties, ConstantSpec* constants,
|
||||
JSFunctionSpec* staticMethods, const char* name);
|
||||
|
||||
template <class T>
|
||||
inline bool
|
||||
|
|
|
@ -47,6 +47,7 @@ class nsWrapperCache;
|
|||
|
||||
typedef unsigned long long DOMTimeStamp;
|
||||
typedef unsigned long long DOMTimeMilliSec;
|
||||
typedef double DOMHighResTimeStamp;
|
||||
|
||||
// Core
|
||||
interface nsIDOMAttr;
|
||||
|
|
|
@ -37,14 +37,16 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
#include "domstubs.idl"
|
||||
interface nsIDOMPerformanceTiming;
|
||||
interface nsIDOMPerformanceNavigation;
|
||||
|
||||
[scriptable, uuid(446faf26-000b-4e66-a5fd-ae37c5ed6beb)]
|
||||
[scriptable, uuid(ac274ec8-ee9f-44ef-b2f0-b13c22225a98)]
|
||||
interface nsIDOMPerformance : nsISupports
|
||||
{
|
||||
readonly attribute nsIDOMPerformanceTiming timing;
|
||||
readonly attribute nsIDOMPerformanceNavigation navigation;
|
||||
|
||||
DOMHighResTimeStamp now();
|
||||
};
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
* @status UNDER_DEVELOPMENT
|
||||
*/
|
||||
|
||||
[scriptable, uuid(E3763903-928B-47C4-AC3B-C47EB43884CA)]
|
||||
[scriptable, uuid(0a1c8b44-12a4-4316-b39f-feeee48475f8)]
|
||||
interface nsIDOMHTMLVideoElement : nsIDOMHTMLMediaElement
|
||||
{
|
||||
attribute long width;
|
||||
|
@ -75,5 +75,8 @@ interface nsIDOMHTMLVideoElement : nsIDOMHTMLMediaElement
|
|||
|
||||
// Time which the last painted video frame was late by, in seconds.
|
||||
readonly attribute double mozFrameDelay;
|
||||
|
||||
// True if the video has an audio track available.
|
||||
readonly attribute bool mozHasAudio;
|
||||
};
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ GRE_MODULE = 1
|
|||
|
||||
XPIDLSRCS = \
|
||||
nsIDOMSettingsManager.idl \
|
||||
nsISettingsService.idl \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
/* 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/. */
|
||||
|
||||
#include "domstubs.idl"
|
||||
|
||||
[scriptable, uuid(83d67430-8516-11e1-b0c4-0800200c9a66)]
|
||||
interface nsISettingsServiceCallback : nsISupports
|
||||
{
|
||||
[implicit_jscontext]
|
||||
void handle(in DOMString aName, in jsval aResult);
|
||||
[implicit_jscontext]
|
||||
void handleError(in DOMString aErrorMessage);
|
||||
};
|
||||
|
||||
[scriptable, uuid(3ab3cbc0-8513-11e1-b0c4-0800200c9a66)]
|
||||
interface nsISettingsServiceLock : nsISupports
|
||||
{
|
||||
void set(in string aName, in jsval aValue, in nsISettingsServiceCallback aCallback);
|
||||
void get(in string aName, in nsISettingsServiceCallback aCallback);
|
||||
};
|
||||
|
||||
[scriptable, uuid(3458e760-8513-11e1-b0c4-0800200c9a66)]
|
||||
interface nsISettingsService : nsISupports
|
||||
{
|
||||
nsISettingsServiceLock getLock();
|
||||
};
|
|
@ -1773,47 +1773,8 @@ bool nsPluginInstanceOwner::AddPluginView(const gfxRect& aRect)
|
|||
return false;
|
||||
}
|
||||
|
||||
JNIEnv* env = GetJNIForThread();
|
||||
if (!env)
|
||||
return false;
|
||||
|
||||
AndroidBridge::AutoLocalJNIFrame frame(env, 1);
|
||||
|
||||
jclass cls = env->FindClass("org/mozilla/gecko/GeckoAppShell");
|
||||
|
||||
#ifdef MOZ_JAVA_COMPOSITOR
|
||||
nsAutoString metadata;
|
||||
nsCOMPtr<nsIAndroidDrawMetadataProvider> metadataProvider =
|
||||
AndroidBridge::Bridge()->GetDrawMetadataProvider();
|
||||
metadataProvider->GetDrawMetadata(metadata);
|
||||
|
||||
jstring jMetadata = env->NewString(nsPromiseFlatString(metadata).get(), metadata.Length());
|
||||
|
||||
jmethodID method = env->GetStaticMethodID(cls,
|
||||
"addPluginView",
|
||||
"(Landroid/view/View;IIIILjava/lang/String;)V");
|
||||
|
||||
env->CallStaticVoidMethod(cls,
|
||||
method,
|
||||
javaSurface,
|
||||
(int)aRect.x,
|
||||
(int)aRect.y,
|
||||
(int)aRect.width,
|
||||
(int)aRect.height,
|
||||
jMetadata);
|
||||
#else
|
||||
jmethodID method = env->GetStaticMethodID(cls,
|
||||
"addPluginView",
|
||||
"(Landroid/view/View;DDDD)V");
|
||||
|
||||
env->CallStaticVoidMethod(cls,
|
||||
method,
|
||||
javaSurface,
|
||||
aRect.x,
|
||||
aRect.y,
|
||||
aRect.width,
|
||||
aRect.height);
|
||||
#endif
|
||||
if (AndroidBridge::Bridge())
|
||||
AndroidBridge::Bridge()->AddPluginView((jobject)javaSurface, aRect);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1827,7 +1788,8 @@ void nsPluginInstanceOwner::RemovePluginView()
|
|||
if (!surface)
|
||||
return;
|
||||
|
||||
AndroidBridge::RemovePluginView(surface);
|
||||
if (AndroidBridge::Bridge())
|
||||
AndroidBridge::Bridge()->RemovePluginView((jobject)surface);
|
||||
}
|
||||
|
||||
void nsPluginInstanceOwner::Invalidate() {
|
||||
|
@ -2913,14 +2875,21 @@ void nsPluginInstanceOwner::Paint(gfxContext* aContext,
|
|||
|
||||
PRInt32 model = mInstance->GetANPDrawingModel();
|
||||
|
||||
float xResolution = mObjectFrame->PresContext()->GetRootPresContext()->PresShell()->GetXResolution();
|
||||
float yResolution = mObjectFrame->PresContext()->GetRootPresContext()->PresShell()->GetYResolution();
|
||||
// Get the offset of the content relative to the page
|
||||
|
||||
gfxRect scaledFrameRect = aFrameRect;
|
||||
scaledFrameRect.Scale(xResolution, yResolution);
|
||||
nsPoint offset = nsPoint(0, 0);
|
||||
nsIFrame* current = (nsIFrame*)mObjectFrame;
|
||||
while (current && current->GetContent() && current->GetContent()->Tag() != nsGkAtoms::html) {
|
||||
offset += current->GetPosition();
|
||||
current = current->GetParent();
|
||||
}
|
||||
|
||||
nsRect bounds = nsRect(offset, mObjectFrame->GetSize());
|
||||
nsIntRect intBounds = bounds.ToNearestPixels(mObjectFrame->PresContext()->AppUnitsPerDevPixel());
|
||||
gfxRect pluginRect(intBounds);
|
||||
|
||||
if (model == kSurface_ANPDrawingModel) {
|
||||
if (!AddPluginView(scaledFrameRect)) {
|
||||
if (!AddPluginView(pluginRect)) {
|
||||
Invalidate();
|
||||
}
|
||||
return;
|
||||
|
@ -2930,9 +2899,13 @@ void nsPluginInstanceOwner::Paint(gfxContext* aContext,
|
|||
if (!mLayer)
|
||||
mLayer = new AndroidMediaLayer();
|
||||
|
||||
mLayer->UpdatePosition(scaledFrameRect, xResolution);
|
||||
mLayer->UpdatePosition(pluginRect);
|
||||
|
||||
SendSize((int)scaledFrameRect.width, (int)scaledFrameRect.height);
|
||||
float xResolution = mObjectFrame->PresContext()->GetRootPresContext()->PresShell()->GetXResolution();
|
||||
float yResolution = mObjectFrame->PresContext()->GetRootPresContext()->PresShell()->GetYResolution();
|
||||
pluginRect.Scale(xResolution, yResolution);
|
||||
|
||||
SendSize((int)pluginRect.width, (int)pluginRect.height);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,13 @@ LIBXUL_LIBRARY = 1
|
|||
EXTRA_COMPONENTS = \
|
||||
SettingsManager.js \
|
||||
SettingsManager.manifest \
|
||||
SettingsService.js \
|
||||
SettingsService.manifest \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_JS_MODULES = \
|
||||
SettingsQueue.jsm \
|
||||
SettingsDB.jsm \
|
||||
$(NULL)
|
||||
|
||||
ifdef ENABLE_TESTS
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
/* 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/. */
|
||||
|
||||
let EXPORTED_SYMBOLS = ["SettingsDB", "SETTINGSDB_NAME", "SETTINGSSTORE_NAME"];
|
||||
|
||||
/* static functions */
|
||||
let DEBUG = 0;
|
||||
if (DEBUG) {
|
||||
debug = function (s) { dump("-*- SettingsDB: " + s + "\n"); }
|
||||
} else {
|
||||
debug = function (s) {}
|
||||
}
|
||||
|
||||
const SETTINGSDB_NAME = "settings";
|
||||
const SETTINGSDB_VERSION = 1;
|
||||
const SETTINGSSTORE_NAME = "settings";
|
||||
|
||||
Components.utils.import("resource://gre/modules/IndexedDBHelper.jsm");
|
||||
|
||||
function SettingsDB() {}
|
||||
|
||||
SettingsDB.prototype = {
|
||||
|
||||
__proto__: IndexedDBHelper.prototype,
|
||||
|
||||
createSchema: function createSchema(aDb) {
|
||||
let objectStore = aDb.createObjectStore(SETTINGSSTORE_NAME, { keyPath: "settingName" });
|
||||
objectStore.createIndex("settingValue", "settingValue", { unique: false });
|
||||
debug("Created object stores and indexes");
|
||||
},
|
||||
|
||||
init: function init(aGlobal) {
|
||||
this.initDBHelper(SETTINGSDB_NAME, SETTINGSDB_VERSION, SETTINGSSTORE_NAME, aGlobal);
|
||||
}
|
||||
}
|
|
@ -11,57 +11,12 @@ if (DEBUG)
|
|||
else
|
||||
debug = function (s) {}
|
||||
|
||||
function Queue() {
|
||||
this._queue = [];
|
||||
this._index = 0;
|
||||
}
|
||||
|
||||
Queue.prototype = {
|
||||
getLength: function() { return (this._queue.length - this._index); },
|
||||
|
||||
isEmpty: function() { return (this._queue.length == 0); },
|
||||
|
||||
enqueue: function(item) { this._queue.push(item); },
|
||||
|
||||
dequeue: function() {
|
||||
if(this.isEmpty())
|
||||
return undefined;
|
||||
|
||||
var item = this._queue[this._index];
|
||||
if (++this._index * 2 >= this._queue.length){
|
||||
this._queue = this._queue.slice(this._index);
|
||||
this._index = 0;
|
||||
}
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/IndexedDBHelper.jsm");
|
||||
|
||||
const DB_NAME = "settings";
|
||||
const DB_VERSION = 1;
|
||||
const STORE_NAME = "settings";
|
||||
|
||||
function SettingsDB() {}
|
||||
|
||||
SettingsDB.prototype = {
|
||||
__proto__: IndexedDBHelper.prototype,
|
||||
|
||||
createSchema: function createSchema(aDb) {
|
||||
let objectStore = aDb.createObjectStore(STORE_NAME, { keyPath: "settingName" });
|
||||
objectStore.createIndex("settingValue", "settingValue", { unique: false });
|
||||
debug("Created object stores and indexes");
|
||||
},
|
||||
|
||||
init: function init(aGlobal) {
|
||||
this.initDBHelper(DB_NAME, DB_VERSION, STORE_NAME, aGlobal);
|
||||
}
|
||||
}
|
||||
|
||||
Cu.import("resource://gre/modules/SettingsQueue.jsm");
|
||||
Cu.import("resource://gre/modules/SettingsDB.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
|
@ -83,7 +38,7 @@ SettingsLock.prototype = {
|
|||
process: function process() {
|
||||
let lock = this;
|
||||
lock._open = false;
|
||||
let store = lock._transaction.objectStore(STORE_NAME);
|
||||
let store = lock._transaction.objectStore(SETTINGSSTORE_NAME);
|
||||
|
||||
while (!lock._requests.isEmpty()) {
|
||||
let info = lock._requests.dequeue();
|
||||
|
@ -152,7 +107,7 @@ SettingsLock.prototype = {
|
|||
var lock;
|
||||
while (lock = this._settingsManager._locks.dequeue()) {
|
||||
if (!lock._transaction) {
|
||||
lock._transaction = lock._settingsManager._settingsDB._db.transaction(STORE_NAME, "readwrite");
|
||||
lock._transaction = lock._settingsManager._settingsDB._db.transaction(SETTINGSSTORE_NAME, "readwrite");
|
||||
}
|
||||
lock.process();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
/* 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/. */
|
||||
|
||||
let EXPORTED_SYMBOLS = ["Queue"];
|
||||
|
||||
function Queue() {
|
||||
this._queue = [];
|
||||
this._index = 0;
|
||||
}
|
||||
|
||||
Queue.prototype = {
|
||||
getLength: function() { return (this._queue.length - this._index); },
|
||||
|
||||
isEmpty: function() { return (this._queue.length == 0); },
|
||||
|
||||
enqueue: function(item) { this._queue.push(item); },
|
||||
|
||||
dequeue: function() {
|
||||
if(this.isEmpty())
|
||||
return undefined;
|
||||
|
||||
var item = this._queue[this._index];
|
||||
if (++this._index * 2 >= this._queue.length){
|
||||
this._queue = this._queue.slice(this._index);
|
||||
this._index = 0;
|
||||
}
|
||||
return item;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,183 @@
|
|||
/* 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"
|
||||
|
||||
/* static functions */
|
||||
let DEBUG = 0;
|
||||
if (DEBUG)
|
||||
debug = function (s) { dump("-*- SettingsService: " + s + "\n"); }
|
||||
else
|
||||
debug = function (s) {}
|
||||
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/SettingsQueue.jsm");
|
||||
Cu.import("resource://gre/modules/SettingsDB.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
const nsIClassInfo = Ci.nsIClassInfo;
|
||||
|
||||
const SETTINGSSERVICELOCK_CONTRACTID = "@mozilla.org/settingsServiceLock;1";
|
||||
const SETTINGSSERVICELOCK_CID = Components.ID("{3ab3cbc0-8513-11e1-b0c4-0800200c9a66}");
|
||||
const nsISettingsServiceLock = Ci.nsISettingsServiceLock;
|
||||
|
||||
function SettingsServiceLock(aSettingsService)
|
||||
{
|
||||
debug("settingsServiceLock constr!");
|
||||
this._open = true;
|
||||
this._requests = new Queue();
|
||||
this._settingsService = aSettingsService;
|
||||
this._transaction = null;
|
||||
}
|
||||
|
||||
SettingsServiceLock.prototype = {
|
||||
|
||||
process: function process() {
|
||||
debug("process!");
|
||||
let lock = this;
|
||||
lock._open = false;
|
||||
let store = lock._transaction.objectStore(SETTINGSSTORE_NAME);
|
||||
|
||||
while (!lock._requests.isEmpty()) {
|
||||
let info = lock._requests.dequeue();
|
||||
debug("info:" + info.intent);
|
||||
let callback = info.callback;
|
||||
let req;
|
||||
let name = info.name;
|
||||
switch (info.intent) {
|
||||
case "set":
|
||||
let value = info.value;
|
||||
if(typeof(value) == 'object')
|
||||
debug("object name:" + name + ", val: " + JSON.stringify(value));
|
||||
req = store.put({settingName: name, settingValue: value});
|
||||
|
||||
req.onsuccess = function() {
|
||||
debug("set on success");
|
||||
lock._open = true;
|
||||
if (callback)
|
||||
callback.handle(name, value);
|
||||
Services.obs.notifyObservers(lock, "mozsettings-changed", JSON.stringify({
|
||||
key: name,
|
||||
value: value
|
||||
}));
|
||||
lock._open = false;
|
||||
};
|
||||
|
||||
req.onerror = function(event) { callback ? callback.handleError(event.target.errorMessage) : null; };
|
||||
break;
|
||||
case "get":
|
||||
req = store.getAll(name);
|
||||
req.onsuccess = function(event) {
|
||||
debug("Request successful. Record count:" + event.target.result.length);
|
||||
debug("result: " + JSON.stringify(event.target.result));
|
||||
this._open = true;
|
||||
if (callback) {
|
||||
if (event.target.result[0]) {
|
||||
if (event.target.result.length > 1) {
|
||||
debug("Warning: overloaded setting:" + name);
|
||||
}
|
||||
callback.handle(name, event.target.result[0].settingValue);
|
||||
} else
|
||||
callback.handle(name, null);
|
||||
} else {
|
||||
debug("no callback defined!");
|
||||
}
|
||||
this._open = false;
|
||||
}.bind(lock);
|
||||
req.onerror = function error(event) { callback ? callback.handleError(event.target.errorMessage) : null; };
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!lock._requests.isEmpty())
|
||||
throw Components.results.NS_ERROR_ABORT;
|
||||
lock._open = true;
|
||||
},
|
||||
|
||||
createTransactionAndProcess: function createTransactionAndProcess() {
|
||||
if (this._settingsService._settingsDB._db) {
|
||||
var lock;
|
||||
while (lock = this._settingsService._locks.dequeue()) {
|
||||
if (!lock._transaction) {
|
||||
lock._transaction = lock._settingsService._settingsDB._db.transaction(SETTINGSSTORE_NAME, "readwrite");
|
||||
}
|
||||
lock.process();
|
||||
}
|
||||
if (!this._requests.isEmpty())
|
||||
this.process();
|
||||
}
|
||||
},
|
||||
|
||||
get: function get(aName, aCallback) {
|
||||
debug("get: " + aName + ", " + aCallback);
|
||||
this._requests.enqueue({ callback: aCallback, intent:"get", name: aName });
|
||||
this.createTransactionAndProcess();
|
||||
},
|
||||
|
||||
set: function set(aName, aValue, aCallback) {
|
||||
debug("set: " + aName + ": " + JSON.stringify(aValue));
|
||||
this._requests.enqueue({ callback: aCallback, intent: "set", name: aName, value: aValue});
|
||||
this.createTransactionAndProcess();
|
||||
},
|
||||
|
||||
classID : SETTINGSSERVICELOCK_CID,
|
||||
QueryInterface : XPCOMUtils.generateQI([nsISettingsServiceLock]),
|
||||
|
||||
classInfo : XPCOMUtils.generateCI({classID: SETTINGSSERVICELOCK_CID,
|
||||
contractID: SETTINGSSERVICELOCK_CONTRACTID,
|
||||
classDescription: "SettingsServiceLock",
|
||||
interfaces: [nsISettingsServiceLock],
|
||||
flags: nsIClassInfo.DOM_OBJECT})
|
||||
};
|
||||
|
||||
const SETTINGSSERVICE_CONTRACTID = "@mozilla.org/settingsService;1";
|
||||
const SETTINGSSERVICE_CID = Components.ID("{3458e760-8513-11e1-b0c4-0800200c9a66}");
|
||||
const nsISettingsService = Ci.nsISettingsService;
|
||||
|
||||
let myGlobal = this;
|
||||
|
||||
function SettingsService()
|
||||
{
|
||||
debug("settingsService Constructor");
|
||||
this._locks = new Queue();
|
||||
var idbManager = Components.classes["@mozilla.org/dom/indexeddb/manager;1"].getService(Ci.nsIIndexedDatabaseManager);
|
||||
idbManager.initWindowless(myGlobal);
|
||||
this._settingsDB = new SettingsDB();
|
||||
this._settingsDB.init(myGlobal);
|
||||
}
|
||||
|
||||
SettingsService.prototype = {
|
||||
|
||||
nextTick: function nextTick(aCallback, thisObj) {
|
||||
if (thisObj)
|
||||
aCallback = aCallback.bind(thisObj);
|
||||
|
||||
Services.tm.currentThread.dispatch(aCallback, Ci.nsIThread.DISPATCH_NORMAL);
|
||||
},
|
||||
|
||||
getLock: function getLock() {
|
||||
debug("get lock!");
|
||||
var lock = new SettingsServiceLock(this);
|
||||
this._locks.enqueue(lock);
|
||||
this._settingsDB.ensureDB(
|
||||
function() { lock.createTransactionAndProcess(); },
|
||||
function() { dump("ensureDB error cb!\n"); },
|
||||
myGlobal );
|
||||
this.nextTick(function() { this._open = false; }, lock);
|
||||
return lock;
|
||||
},
|
||||
|
||||
classID : SETTINGSSERVICE_CID,
|
||||
QueryInterface : XPCOMUtils.generateQI([nsISettingsService]),
|
||||
|
||||
classInfo : XPCOMUtils.generateCI({classID: SETTINGSSERVICE_CID,
|
||||
contractID: SETTINGSSERVICE_CONTRACTID,
|
||||
classDescription: "SettingsService",
|
||||
interfaces: [nsISettingsService],
|
||||
flags: nsIClassInfo.DOM_OBJECT})
|
||||
}
|
||||
|
||||
const NSGetFactory = XPCOMUtils.generateNSGetFactory([SettingsService, SettingsServiceLock])
|
|
@ -0,0 +1,5 @@
|
|||
component {3ab3cbc0-8513-11e1-b0c4-0800200c9a66} SettingsService.js
|
||||
contract @mozilla.org/settingsServiceLock;1 {3ab3cbc0-8513-11e1-b0c4-0800200c9a66}
|
||||
|
||||
component {3458e760-8513-11e1-b0c4-0800200c9a66} SettingsService.js
|
||||
contract @mozilla.org/settingsService;1 {3458e760-8513-11e1-b0c4-0800200c9a66}
|
|
@ -11,9 +11,6 @@ relativesrcdir = dom/settings/tests
|
|||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
DIRS = \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
_TEST_FILES = \
|
||||
|
|
|
@ -78,6 +78,7 @@ _TEST_FILES = \
|
|||
test_callback_wrapping.xul \
|
||||
window_callback_wrapping.xul \
|
||||
test_sandbox_postMessage.html \
|
||||
test_sandbox_bindings.xul \
|
||||
$(NULL)
|
||||
|
||||
ifeq (WINNT,$(OS_ARCH))
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
|
||||
<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=741267
|
||||
-->
|
||||
<window title="Mozilla Bug 741267"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
|
||||
|
||||
<iframe id="t"></iframe>
|
||||
|
||||
<!-- test results are displayed in the html:body -->
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=741267"
|
||||
target="_blank">Mozilla Bug 741267</a>
|
||||
</body>
|
||||
|
||||
<!-- test code goes here -->
|
||||
<script type="application/javascript">
|
||||
<![CDATA[
|
||||
|
||||
/** Test for Bug 741267 **/
|
||||
function doTest() {
|
||||
var win = $("t").contentWindow;
|
||||
var sandbox = Components.utils.Sandbox(win, { sandboxPrototype: win });
|
||||
try {
|
||||
var nl = Components.utils.evalInSandbox("NodeList", sandbox);
|
||||
is(nl, "[object NodeList]", "'NodeList' in a sandbox should return the NodeList interface prototype object");
|
||||
} catch (e) {
|
||||
ok(false, "'NodeList' shouldn't throw in a sandbox");
|
||||
}
|
||||
try {
|
||||
var et = Components.utils.evalInSandbox("EventTarget", sandbox);
|
||||
ok(et, "'EventTarget' in a sandbox should return the EventTarget interface prototype object");
|
||||
} catch (e) {
|
||||
ok(false, "'EventTarget' shouldn't throw in a sandbox");
|
||||
}
|
||||
try {
|
||||
var xhr = Components.utils.evalInSandbox("XMLHttpRequest()", sandbox);
|
||||
is(xhr, "[object XMLHttpRequest]", "'XMLHttpRequest()' in a sandbox should create an XMLHttpRequest object");
|
||||
} catch (e) {
|
||||
ok(false, "'XMLHttpRequest()' shouldn't throw in a sandbox");
|
||||
}
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addLoadEvent(doTest);
|
||||
]]>
|
||||
</script>
|
||||
</window>
|
|
@ -76,6 +76,7 @@ _TEST_FILES = \
|
|||
test_focus_legend_noparent.html \
|
||||
file_clonewrapper.html \
|
||||
file_moving_nodeList.html \
|
||||
test_performance_now.html \
|
||||
$(NULL)
|
||||
|
||||
_CHROME_FILES = \
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for High Resolution Timer</title>
|
||||
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
ok(window.performance);
|
||||
ok(typeof window.performance.now == 'function');
|
||||
var n = window.performance.now();
|
||||
ok(n >= 0);
|
||||
ok(window.performance.now() >= n);
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
setTimeout(function() {
|
||||
ok(window.performance.now() > n);
|
||||
SimpleTest.finish();
|
||||
}, 20);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -37,7 +37,7 @@ struct WrapPrototypeTraits
|
|||
GetProtoObject(JSContext* aCx, JSObject* aGlobal) \
|
||||
{ \
|
||||
using namespace mozilla::dom::bindings::prototypes; \
|
||||
return _class##_workers::GetProtoObject(aCx, aGlobal); \
|
||||
return _class##_workers::GetProtoObject(aCx, aGlobal, aGlobal); \
|
||||
} \
|
||||
};
|
||||
|
||||
|
|
|
@ -449,7 +449,7 @@ ResolveWorkerClasses(JSContext* aCx, JSObject* aObj, jsid aId, unsigned aFlags,
|
|||
return true;
|
||||
}
|
||||
|
||||
JSObject* eventTarget = EventTarget_workers::GetProtoObject(aCx, aObj);
|
||||
JSObject* eventTarget = EventTarget_workers::GetProtoObject(aCx, aObj, aObj);
|
||||
if (!eventTarget) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -958,7 +958,8 @@ CreateDedicatedWorkerGlobalScope(JSContext* aCx)
|
|||
// -> EventTarget
|
||||
// -> Object
|
||||
|
||||
JSObject* eventTargetProto = EventTarget_workers::GetProtoObject(aCx, global);
|
||||
JSObject* eventTargetProto =
|
||||
EventTarget_workers::GetProtoObject(aCx, global, global);
|
||||
if (!eventTargetProto) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1003,8 +1004,9 @@ CreateDedicatedWorkerGlobalScope(JSContext* aCx)
|
|||
}
|
||||
|
||||
// Init other paris-bindings.
|
||||
if (!XMLHttpRequest_workers::CreateInterfaceObjects(aCx, global) ||
|
||||
!XMLHttpRequestUpload_workers::CreateInterfaceObjects(aCx, global)) {
|
||||
if (!XMLHttpRequest_workers::CreateInterfaceObjects(aCx, global, global) ||
|
||||
!XMLHttpRequestUpload_workers::CreateInterfaceObjects(aCx, global,
|
||||
global)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -1826,9 +1826,6 @@ public class GeckoAppShell
|
|||
return false;
|
||||
}
|
||||
|
||||
public static void emitGeckoAccessibilityEvent (int eventType, String[] textList, String description, boolean enabled, boolean checked, boolean password) {
|
||||
}
|
||||
|
||||
public static double[] getCurrentNetworkInformation() {
|
||||
return GeckoNetworkManager.getInstance().getCurrentInformation();
|
||||
}
|
||||
|
|
|
@ -641,6 +641,11 @@ GLContext::CanUploadSubTextures()
|
|||
if (!mWorkAroundDriverBugs)
|
||||
return true;
|
||||
|
||||
// Lock surface feature allows to mmap texture memory and modify it directly
|
||||
// this feature allow us modify texture partially without full upload
|
||||
if (HasLockSurface())
|
||||
return true;
|
||||
|
||||
// There are certain GPUs that we don't want to use glTexSubImage2D on
|
||||
// because that function can be very slow and/or buggy
|
||||
if (Renderer() == RendererAdreno200 || Renderer() == RendererAdreno205)
|
||||
|
|
|
@ -731,6 +731,7 @@ public:
|
|||
bool CanUploadSubTextures();
|
||||
bool CanUploadNonPowerOfTwo();
|
||||
bool WantsSmallTiles();
|
||||
virtual bool HasLockSurface() { return false; }
|
||||
|
||||
/**
|
||||
* If this context wraps a double-buffered target, swap the back
|
||||
|
|
|
@ -597,6 +597,10 @@ public:
|
|||
return h;
|
||||
}
|
||||
|
||||
virtual bool HasLockSurface() {
|
||||
return sEGLLibrary.HasKHRLockSurface();
|
||||
}
|
||||
|
||||
protected:
|
||||
friend class GLContextProviderEGL;
|
||||
|
||||
|
|
|
@ -817,8 +817,13 @@ LayerManagerOGL::Render()
|
|||
|
||||
mGLContext->fEnable(LOCAL_GL_SCISSOR_TEST);
|
||||
|
||||
// If the Java compositor is being used, this clear will be done in
|
||||
// DrawWindowUnderlay. Make sure the bits used here match up with those used
|
||||
// in mobile/android/base/gfx/LayerRenderer.java
|
||||
#ifndef MOZ_JAVA_COMPOSITOR
|
||||
mGLContext->fClearColor(0.0, 0.0, 0.0, 0.0);
|
||||
mGLContext->fClear(LOCAL_GL_COLOR_BUFFER_BIT | LOCAL_GL_DEPTH_BUFFER_BIT);
|
||||
#endif
|
||||
|
||||
// Allow widget to render a custom background.
|
||||
mWidget->DrawWindowUnderlay(this, rect);
|
||||
|
|