mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge m-c to inbound.
This commit is contained in:
commit
72c57be9ea
@ -1,4 +1,4 @@
|
||||
{
|
||||
"revision": "7343851c97c278a338434d2632098a263e19bbb6",
|
||||
"revision": "d5f4a104c0b79b8fe13b7883dd531249ed251146",
|
||||
"repo_path": "/integration/gaia-central"
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
MOZ_APP_BASENAME=B2G
|
||||
MOZ_APP_VENDOR=Mozilla
|
||||
|
||||
MOZ_APP_VERSION=28.0a1
|
||||
MOZ_APP_VERSION=29.0a1
|
||||
MOZ_APP_UA_NAME=Firefox
|
||||
|
||||
MOZ_UA_OS_AGNOSTIC=1
|
||||
@ -56,7 +56,9 @@ MOZ_TOOLKIT_SEARCH=
|
||||
MOZ_PLACES=
|
||||
MOZ_B2G=1
|
||||
|
||||
#MOZ_NUWA_PROCESS=1
|
||||
if test "$OS_TARGET" = "Android"; then
|
||||
MOZ_NUWA_PROCESS=1
|
||||
fi
|
||||
MOZ_FOLD_LIBS=1
|
||||
|
||||
MOZ_JSDOWNLOADS=1
|
||||
|
@ -477,7 +477,7 @@ let CustomizableUIInternal = {
|
||||
|
||||
this.insertWidgetBefore(node, currentNode, container, aArea);
|
||||
if (gResetting) {
|
||||
this.notifyListeners("onWidgetReset", id, aArea);
|
||||
this.notifyListeners("onWidgetReset", node, container);
|
||||
}
|
||||
}
|
||||
|
||||
@ -527,7 +527,7 @@ let CustomizableUIInternal = {
|
||||
}
|
||||
|
||||
if (gResetting) {
|
||||
this.notifyListeners("onAreaReset", aArea);
|
||||
this.notifyListeners("onAreaReset", aArea, container);
|
||||
}
|
||||
} finally {
|
||||
this.endBatchUpdate();
|
||||
@ -668,6 +668,8 @@ let CustomizableUIInternal = {
|
||||
}
|
||||
|
||||
let area = gAreas.get(aArea);
|
||||
let isToolbar = area.get("type") == CustomizableUI.TYPE_TOOLBAR;
|
||||
let isOverflowable = isToolbar && area.get("overflowable");
|
||||
let showInPrivateBrowsing = gPalette.has(aWidgetId)
|
||||
? gPalette.get(aWidgetId).showInPrivateBrowsing
|
||||
: true;
|
||||
@ -679,12 +681,15 @@ let CustomizableUIInternal = {
|
||||
continue;
|
||||
}
|
||||
|
||||
let container = areaNode.customizationTarget;
|
||||
let widgetNode = container.ownerDocument.getElementById(aWidgetId);
|
||||
let widgetNode = window.document.getElementById(aWidgetId);
|
||||
if (!widgetNode) {
|
||||
ERROR("Widget not found, unable to remove");
|
||||
continue;
|
||||
}
|
||||
let container = areaNode.customizationTarget;
|
||||
if (isOverflowable) {
|
||||
container = areaNode.overflowable.getContainerFor(widgetNode);
|
||||
}
|
||||
|
||||
this.notifyListeners("onWidgetBeforeDOMChange", widgetNode, null, container, true);
|
||||
|
||||
@ -702,7 +707,7 @@ let CustomizableUIInternal = {
|
||||
}
|
||||
this.notifyListeners("onWidgetAfterDOMChange", widgetNode, null, container, true);
|
||||
|
||||
if (area.get("type") == CustomizableUI.TYPE_TOOLBAR) {
|
||||
if (isToolbar) {
|
||||
areaNode.setAttribute("currentset", gPlacements.get(aArea).join(','));
|
||||
}
|
||||
|
||||
@ -2094,47 +2099,330 @@ this.CustomizableUI = {
|
||||
get WIDE_PANEL_CLASS() "panel-wide-item",
|
||||
get PANEL_COLUMN_COUNT() 3,
|
||||
|
||||
/**
|
||||
* Add a listener object that will get fired for various events regarding
|
||||
* customization.
|
||||
*
|
||||
* @param aListener the listener object to add
|
||||
*
|
||||
* Not all event handler methods need to be defined.
|
||||
* CustomizableUI will catch exceptions. Events are dispatched
|
||||
* synchronously on the UI thread, so if you can delay any/some of your
|
||||
* processing, that is advisable. The following event handlers are supported:
|
||||
* - onWidgetAdded(aWidgetId, aArea, aPosition)
|
||||
* Fired when a widget is added to an area. aWidgetId is the widget that
|
||||
* was added, aArea the area it was added to, and aPosition the position
|
||||
* in which it was added.
|
||||
* - onWidgetMoved(aWidgetId, aArea, aOldPosition, aNewPosition)
|
||||
* Fired when a widget is moved within its area. aWidgetId is the widget
|
||||
* that was moved, aArea the area it was moved in, aOldPosition its old
|
||||
* position, and aNewPosition its new position.
|
||||
* - onWidgetRemoved(aWidgetId, aArea)
|
||||
* Fired when a widget is removed from its area. aWidgetId is the widget
|
||||
* that was removed, aArea the area it was removed from.
|
||||
*
|
||||
* - onWidgetBeforeDOMChange(aNode, aNextNode, aContainer, aIsRemoval)
|
||||
* Fired *before* a widget's DOM node is acted upon by CustomizableUI
|
||||
* (to add, move or remove it). aNode is the DOM node changed, aNextNode
|
||||
* the DOM node (if any) before which a widget will be inserted,
|
||||
* aContainer the *actual* DOM container (could be an overflow panel in
|
||||
* case of an overflowable toolbar), and aWasRemoval is true iff the
|
||||
* action about to happen is the removal of the DOM node.
|
||||
* - onWidgetAfterDOMChange(aNode, aNextNode, aContainer, aWasRemoval)
|
||||
* Like onWidgetBeforeDOMChange, but fired after the change to the DOM
|
||||
* node of the widget.
|
||||
*
|
||||
* - onWidgetReset(aNode, aContainer)
|
||||
* Fired after a reset to default placements moves a widget's node to a
|
||||
* different location. aNode is the widget's node, aContainer is the
|
||||
* area it was moved into (NB: it might already have been there and been
|
||||
* moved to a different position!)
|
||||
* - onAreaReset(aArea, aContainer)
|
||||
* Fired after a reset to default placements is complete on an area's
|
||||
* DOM node. Note that this is fired for each DOM node. aArea is the area
|
||||
* that was reset, aContainer the DOM node that was reset.
|
||||
*
|
||||
* - onWidgetCreated(aWidgetId)
|
||||
* Fired when a widget with id aWidgetId has been created, but before it
|
||||
* is added to any placements or any DOM nodes have been constructed.
|
||||
* Only fired for API-based widgets.
|
||||
* - onWidgetAfterCreation(aWidgetId, aArea)
|
||||
* Fired after a widget with id aWidgetId has been created, and has been
|
||||
* added to either its default area or the area in which it was placed
|
||||
* previously. If the widget has no default area and/or it has never
|
||||
* been placed anywhere, aArea may be null. Only fired for API-based
|
||||
* widgets.
|
||||
* - onWidgetDestroyed(aWidgetId)
|
||||
* Fired when widgets are destroyed. aWidgetId is the widget that is
|
||||
* being destroyed. Only fired for API-based widgets.
|
||||
* - onWidgetInstanceRemoved(aWidgetId, aDocument)
|
||||
* Fired when a window is unloaded and a widget's instance is destroyed
|
||||
* because of this. Only fired for API-based widgets.
|
||||
*
|
||||
* - onWidgetDrag(aWidgetId, aArea)
|
||||
* Fired both when and after customize mode drag handling system tries
|
||||
* to determine the width and height of widget aWidgetId when dragged to a
|
||||
* different area. aArea will be the area the item is dragged to, or
|
||||
* undefined after the measurements have been done and the node has been
|
||||
* moved back to its 'regular' area.
|
||||
*
|
||||
* - onCustomizeStart(aWindow)
|
||||
* Fired when opening customize mode in aWindow.
|
||||
* - onCustomizeEnd(aWindow)
|
||||
* Fired when exiting customize mode in aWindow.
|
||||
*/
|
||||
addListener: function(aListener) {
|
||||
CustomizableUIInternal.addListener(aListener);
|
||||
},
|
||||
/**
|
||||
* Remove a listener added with addListener
|
||||
* @param aListener the listener object to remove
|
||||
*/
|
||||
removeListener: function(aListener) {
|
||||
CustomizableUIInternal.removeListener(aListener);
|
||||
},
|
||||
|
||||
/**
|
||||
* Register a customizable area with CustomizableUI.
|
||||
* @param aName the name of the area to register. Can only contain
|
||||
* alphanumeric characters, dashes (-) and underscores (_).
|
||||
* @param aProps the properties of the area. The following properties are
|
||||
* recognized:
|
||||
* - type: the type of area. Either TYPE_TOOLBAR (default) or
|
||||
* TYPE_MENU_PANEL;
|
||||
* - anchor: for a menu panel or overflowable toolbar, the
|
||||
* anchoring node for the panel.
|
||||
* - legacy: set to true if you want customizableui to
|
||||
* automatically migrate the currentset attribute
|
||||
* - overflowable: set to true if your toolbar is overflowable.
|
||||
* This requires an anchor, and only has an
|
||||
* effect for toolbars.
|
||||
* - defaultPlacements: an array of widget IDs making up the
|
||||
* default contents of the area
|
||||
*/
|
||||
registerArea: function(aName, aProperties) {
|
||||
CustomizableUIInternal.registerArea(aName, aProperties);
|
||||
},
|
||||
/**
|
||||
* Register a concrete node for a registered area. This method is automatically
|
||||
* called from any toolbar in the main browser window that has its
|
||||
* "customizable" attribute set to true. There should normally be no need to
|
||||
* call it yourself.
|
||||
*
|
||||
* Note that ideally, you should register your toolbar using registerArea
|
||||
* before any of the toolbars have their XBL bindings constructed (which
|
||||
* will happen when they're added to the DOM and are not hidden). If you
|
||||
* don't, and your toolbar has a defaultset attribute, CustomizableUI will
|
||||
* register it automatically. If your toolbar does not have a defaultset
|
||||
* attribute, the node will be saved for processing when you call
|
||||
* registerArea. Note that CustomizableUI won't restore state in the area,
|
||||
* allow the user to customize it in customize mode, or otherwise deal
|
||||
* with it, until the area has been registered.
|
||||
*/
|
||||
registerToolbarNode: function(aToolbar, aExistingChildren) {
|
||||
CustomizableUIInternal.registerToolbarNode(aToolbar, aExistingChildren);
|
||||
},
|
||||
/**
|
||||
* Register the menu panel node. This method should not be called by anyone
|
||||
* apart from the built-in PanelUI.
|
||||
* @param aPanel the panel DOM node being registered.
|
||||
*/
|
||||
registerMenuPanel: function(aPanel) {
|
||||
CustomizableUIInternal.registerMenuPanel(aPanel);
|
||||
},
|
||||
/**
|
||||
* Unregister a customizable area. The inverse of registerArea.
|
||||
*
|
||||
* Unregistering an area will remove all the (removable) widgets in the
|
||||
* area, which will return to the panel, and destroy all other traces
|
||||
* of the area within CustomizableUI. Note that this means the *contents*
|
||||
* of the area's DOM nodes will be moved to the panel or removed, but
|
||||
* the area's DOM nodes *themselves* will stay.
|
||||
*
|
||||
* Furthermore, by default the placements of the area will be kept in the
|
||||
* saved state (!) and restored if you re-register the area at a later
|
||||
* point. This is useful for e.g. add-ons that get disabled and then
|
||||
* re-enabled (e.g. when they update).
|
||||
*
|
||||
* You can override this last behaviour (and destroy the placements
|
||||
* information in the saved state) by passing true for aDestroyPlacements.
|
||||
*
|
||||
* @param aName the name of the area to unregister
|
||||
* @param aDestroyPlacements whether to destroy the placements information
|
||||
* for the area, too.
|
||||
*/
|
||||
unregisterArea: function(aName, aDestroyPlacements) {
|
||||
CustomizableUIInternal.unregisterArea(aName, aDestroyPlacements);
|
||||
},
|
||||
/**
|
||||
* Add a widget to an area.
|
||||
* If the area to which you try to add is not known to CustomizableUI,
|
||||
* this will throw.
|
||||
* If the area to which you try to add has not yet been restored from its
|
||||
* legacy state, this will postpone the addition.
|
||||
* If the area to which you try to add is the same as the area in which
|
||||
* the widget is currently placed, this will do the same as
|
||||
* moveWidgetWithinArea.
|
||||
* If the widget cannot be removed from its original location, this will
|
||||
* no-op.
|
||||
*
|
||||
* This will fire an onWidgetAdded notification,
|
||||
* and an onWidgetBeforeDOMChange and onWidgetAfterDOMChange notification
|
||||
* for each window CustomizableUI knows about.
|
||||
*
|
||||
* @param aWidgetId the widget to add
|
||||
* @param aArea the area to add the widget to
|
||||
* @param aPosition the position at which to add the widget. If you do not
|
||||
* pass a position, the widget will be added to the end
|
||||
* of the area.
|
||||
*/
|
||||
addWidgetToArea: function(aWidgetId, aArea, aPosition) {
|
||||
CustomizableUIInternal.addWidgetToArea(aWidgetId, aArea, aPosition);
|
||||
},
|
||||
/**
|
||||
* Remove a widget from its area. If the widget cannot be removed from its
|
||||
* area, or is not in any area, this will no-op. Otherwise, this will fire an
|
||||
* onWidgetRemoved notification, and an onWidgetBeforeDOMChange and
|
||||
* onWidgetAfterDOMChange notification for each window CustomizableUI knows
|
||||
* about.
|
||||
*
|
||||
* @param aWidgetId the widget to remove
|
||||
*/
|
||||
removeWidgetFromArea: function(aWidgetId) {
|
||||
CustomizableUIInternal.removeWidgetFromArea(aWidgetId);
|
||||
},
|
||||
/**
|
||||
* Move a widget within an area.
|
||||
* If the widget is not in any area, this will no-op.
|
||||
* If the widget is already at the indicated position, this will no-op.
|
||||
*
|
||||
* Otherwise, this will move the widget and fire an onWidgetMoved notification,
|
||||
* and an onWidgetBeforeDOMChange and onWidgetAfterDOMChange notification for
|
||||
* each window CustomizableUI knows about.
|
||||
*
|
||||
* @param aWidgetid the widget to move
|
||||
* @param aPosition the position to move the widget to.
|
||||
* Negative values or values greater than the number of
|
||||
* widgets will be interpreted to mean moving the widget to
|
||||
* respectively the first or last position.
|
||||
*/
|
||||
moveWidgetWithinArea: function(aWidgetId, aPosition) {
|
||||
CustomizableUIInternal.moveWidgetWithinArea(aWidgetId, aPosition);
|
||||
},
|
||||
/**
|
||||
* Ensure a XUL-based widget created in a window after areas were
|
||||
* initialized moves to its correct position.
|
||||
* This is roughly equivalent to manually looking up the position and using
|
||||
* insertItem in the old API, but a lot less work for consumers.
|
||||
* Always prefer this over using toolbar.insertItem (which might no-op
|
||||
* because it delegates to addWidgetToArea) or, worse, moving items in the
|
||||
* DOM yourself.
|
||||
*
|
||||
* @param aWidgetId the widget that was just created
|
||||
* @param aWindow the window in which you want to ensure it was added.
|
||||
*
|
||||
* NB: why is this API per-window, you wonder? Because if you need this,
|
||||
* presumably you yourself need to create the widget in all the windows
|
||||
* and need to loop through them anyway.
|
||||
*/
|
||||
ensureWidgetPlacedInWindow: function(aWidgetId, aWindow) {
|
||||
return CustomizableUIInternal.ensureWidgetPlacedInWindow(aWidgetId, aWindow);
|
||||
},
|
||||
/**
|
||||
* Start a batch update of items.
|
||||
* During a batch update, the customization state is not saved to the user's
|
||||
* preferences file, in order to reduce (possibly sync) IO.
|
||||
* Calls to begin/endBatchUpdate may be nested.
|
||||
*
|
||||
* Callers should ensure that NO MATTER WHAT they call endBatchUpdate once
|
||||
* for each call to endBatchUpdate, even if there are exceptions in the
|
||||
* code in the batch update. Otherwise, for the duration of the
|
||||
* Firefox session, customization state is never saved. Typically, you
|
||||
* would do this using a try...finally block.
|
||||
*/
|
||||
beginBatchUpdate: function() {
|
||||
CustomizableUIInternal.beginBatchUpdate();
|
||||
},
|
||||
/**
|
||||
* End a batch update. See the documentation for beginBatchUpdate above.
|
||||
*
|
||||
* State is not saved if we believe it is identical to the last known
|
||||
* saved state. State is only ever saved when all batch updates have
|
||||
* finished (ie there has been 1 endBatchUpdate call for each
|
||||
* beginBatchUpdate call). If any of the endBatchUpdate calls pass
|
||||
* aForceDirty=true, we will flush to the prefs file.
|
||||
*
|
||||
* @param aForceDirty force CustomizableUI to flush to the prefs file when
|
||||
* all batch updates have finished.
|
||||
*/
|
||||
endBatchUpdate: function(aForceDirty) {
|
||||
CustomizableUIInternal.endBatchUpdate(aForceDirty);
|
||||
},
|
||||
/**
|
||||
* Create a widget.
|
||||
*
|
||||
* To create a widget, you should pass an object with its desired
|
||||
* properties. The following properties are supported:
|
||||
*
|
||||
* - id: the ID of the widget (required).
|
||||
* - type: a string indicating the type of widget. Possible types
|
||||
* are:
|
||||
* 'button' - for simple button widgets (the default)
|
||||
* 'view' - for buttons that open a panel or subview,
|
||||
* depending on where they are placed.
|
||||
* 'custom' - for fine-grained control over the creation
|
||||
* of the widget.
|
||||
* - viewId: Only useful for views (and required there): the id of the
|
||||
* <panelview> that should be shown when clicking the widget.
|
||||
* - onBuild(aDoc): Only useful for custom widgets (and required there); a
|
||||
* function that will be invoked with the document in which
|
||||
* to build a widget. Should return the DOM node that has
|
||||
* been constructed.
|
||||
* - onCreated(aNode): Attached to all widgets; a function that will be invoked
|
||||
* whenever the widget has a DOM node constructed, passing the
|
||||
* constructed node as an argument.
|
||||
* - onCommand(aEvt): Only useful for button widgets; a function that will be
|
||||
* invoked when the user activates the button.
|
||||
* - onClick(aEvt): Attached to all widgets; a function that will be invoked
|
||||
* when the user clicks the widget.
|
||||
* - onViewShowing(aEvt): Only useful for views; a function that will be
|
||||
* invoked when a user shows your view.
|
||||
* - onViewHiding(aEvt): Only useful for views; a function that will be
|
||||
* invoked when a user hides your view.
|
||||
* - tooltiptext: string to use for the tooltip of the widget
|
||||
* - label: string to use for the label of the widget
|
||||
* - removable: whether the widget is removable (optional, default: false)
|
||||
* - overflows: whether widget can overflow when in an overflowable
|
||||
* toolbar (optional, default: true)
|
||||
* - defaultArea: default area to add the widget to
|
||||
* (optional, default: none)
|
||||
* - shortcutId: id of an element that has a shortcut for this widget
|
||||
* (optional, default: null). This is only used to display
|
||||
* the shortcut as part of the tooltip for builtin widgets
|
||||
* (which have strings inside
|
||||
* customizableWidgets.properties). If you're in an add-on,
|
||||
* you should not set this property.
|
||||
* - showInPrivateBrowsing: whether to show the widget in private browsing
|
||||
* mode (optional, default: true)
|
||||
*
|
||||
* @param aProperties the specifications for the widget.
|
||||
*/
|
||||
createWidget: function(aProperties) {
|
||||
return CustomizableUIInternal.wrapWidget(
|
||||
CustomizableUIInternal.createWidget(aProperties)
|
||||
);
|
||||
},
|
||||
/**
|
||||
* Destroy a widget
|
||||
*
|
||||
* If the widget is part of the default placements in an area, this will
|
||||
* remove it from there. It will also remove any DOM instances. However,
|
||||
* it will keep the widget in the placements for whatever area it was
|
||||
* in at the time. You can remove it from there yourself by calling
|
||||
* CustomizableUI.removeWidgetFromArea(aWidgetId).
|
||||
*
|
||||
* @param aWidgetId the widget to destroy
|
||||
*/
|
||||
destroyWidget: function(aWidgetId) {
|
||||
CustomizableUIInternal.destroyWidget(aWidgetId);
|
||||
},
|
||||
@ -2765,7 +3053,14 @@ OverflowableToolbar.prototype = {
|
||||
return [this._target, null];
|
||||
}
|
||||
return [this._list, nextNode];
|
||||
}
|
||||
},
|
||||
|
||||
getContainerFor: function(aNode) {
|
||||
if (aNode.classList.contains("overflowedItem")) {
|
||||
return this._list;
|
||||
}
|
||||
return this._target;
|
||||
},
|
||||
};
|
||||
|
||||
// When IDs contain special characters, we need to escape them for use with querySelector:
|
||||
|
@ -406,8 +406,8 @@ const CustomizableWidgets = [{
|
||||
updateZoomResetButton();
|
||||
}.bind(this),
|
||||
|
||||
onWidgetReset: function(aWidgetId) {
|
||||
if (aWidgetId != this.id)
|
||||
onWidgetReset: function(aWidgetNode) {
|
||||
if (aWidgetNode != node)
|
||||
return;
|
||||
updateCombinedWidgetStyle(node, this.currentArea, true);
|
||||
updateZoomResetButton();
|
||||
@ -506,8 +506,8 @@ const CustomizableWidgets = [{
|
||||
updateCombinedWidgetStyle(node);
|
||||
}.bind(this),
|
||||
|
||||
onWidgetReset: function(aWidgetId) {
|
||||
if (aWidgetId != this.id)
|
||||
onWidgetReset: function(aWidgetNode) {
|
||||
if (aWidgetNode != node)
|
||||
return;
|
||||
updateCombinedWidgetStyle(node, this.currentArea);
|
||||
}.bind(this),
|
||||
@ -814,4 +814,4 @@ if (isWin8OrHigher()) {
|
||||
});
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
@ -101,7 +101,7 @@ AreaPositionManager.prototype = {
|
||||
let doc = aContainer.ownerDocument;
|
||||
let draggedItem = doc.getElementById(aDraggedItemId);
|
||||
// If dragging a wide item, always pick the first item in a row:
|
||||
if (draggedItem &&
|
||||
if (this._inPanel && draggedItem &&
|
||||
draggedItem.classList.contains(CustomizableUI.WIDE_PANEL_CLASS)) {
|
||||
return this._firstInRow(closest);
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
28.0a1
|
||||
29.0a1
|
||||
|
@ -149,7 +149,8 @@ ToolbarView.prototype = {
|
||||
_onStepOverPressed: function() {
|
||||
if (DebuggerController.activeThread.paused) {
|
||||
DebuggerController.StackFrames.currentFrameDepth = -1;
|
||||
DebuggerController.activeThread.stepOver();
|
||||
let warn = DebuggerController._ensureResumptionOrder;
|
||||
DebuggerController.activeThread.stepOver(warn);
|
||||
}
|
||||
},
|
||||
|
||||
@ -159,7 +160,8 @@ ToolbarView.prototype = {
|
||||
_onStepInPressed: function() {
|
||||
if (DebuggerController.activeThread.paused) {
|
||||
DebuggerController.StackFrames.currentFrameDepth = -1;
|
||||
DebuggerController.activeThread.stepIn();
|
||||
let warn = DebuggerController._ensureResumptionOrder;
|
||||
DebuggerController.activeThread.stepIn(warn);
|
||||
}
|
||||
},
|
||||
|
||||
@ -169,7 +171,8 @@ ToolbarView.prototype = {
|
||||
_onStepOutPressed: function() {
|
||||
if (DebuggerController.activeThread.paused) {
|
||||
DebuggerController.StackFrames.currentFrameDepth = -1;
|
||||
DebuggerController.activeThread.stepOut();
|
||||
let warn = DebuggerController._ensureResumptionOrder;
|
||||
DebuggerController.activeThread.stepOut(warn);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -484,22 +484,22 @@ function testOriginalRawDataIntegrity(arr, obj) {
|
||||
function testAnonymousHeaders(fooScope, anonymousVar, anonymousScope, barVar, bazProperty) {
|
||||
is(fooScope.header, true,
|
||||
"A named scope should have a header visible.");
|
||||
is(fooScope.target.hasAttribute("non-header"), false,
|
||||
is(fooScope.target.hasAttribute("untitled"), false,
|
||||
"The non-header attribute should not be applied to scopes with headers.");
|
||||
|
||||
is(anonymousScope.header, false,
|
||||
"An anonymous scope should have a header visible.");
|
||||
is(anonymousScope.target.hasAttribute("non-header"), true,
|
||||
is(anonymousScope.target.hasAttribute("untitled"), true,
|
||||
"The non-header attribute should not be applied to scopes without headers.");
|
||||
|
||||
is(barVar.header, true,
|
||||
"A named variable should have a header visible.");
|
||||
is(barVar.target.hasAttribute("non-header"), false,
|
||||
is(barVar.target.hasAttribute("untitled"), false,
|
||||
"The non-header attribute should not be applied to variables with headers.");
|
||||
|
||||
is(anonymousVar.header, false,
|
||||
"An anonymous variable should have a header visible.");
|
||||
is(anonymousVar.target.hasAttribute("non-header"), true,
|
||||
is(anonymousVar.target.hasAttribute("untitled"), true,
|
||||
"The non-header attribute should not be applied to variables without headers.");
|
||||
}
|
||||
|
||||
|
@ -72,29 +72,29 @@ function testVariablesAndPropertiesFiltering() {
|
||||
is(constr2Var.expanded, true,
|
||||
"The constr2Var should be expanded.");
|
||||
|
||||
is(localScope.target.querySelectorAll(".variables-view-variable:not([non-match])").length, 1,
|
||||
is(localScope.target.querySelectorAll(".variables-view-variable:not([unmatched])").length, 1,
|
||||
"There should be 1 variable displayed in the local scope.");
|
||||
is(withScope.target.querySelectorAll(".variables-view-variable:not([non-match])").length, 0,
|
||||
is(withScope.target.querySelectorAll(".variables-view-variable:not([unmatched])").length, 0,
|
||||
"There should be 0 variables displayed in the with scope.");
|
||||
is(functionScope.target.querySelectorAll(".variables-view-variable:not([non-match])").length, 0,
|
||||
is(functionScope.target.querySelectorAll(".variables-view-variable:not([unmatched])").length, 0,
|
||||
"There should be 0 variables displayed in the function scope.");
|
||||
isnot(globalScope.target.querySelectorAll(".variables-view-variable:not([non-match])").length, 0,
|
||||
isnot(globalScope.target.querySelectorAll(".variables-view-variable:not([unmatched])").length, 0,
|
||||
"There should be some variables displayed in the global scope.");
|
||||
|
||||
is(withScope.target.querySelectorAll(".variables-view-property:not([non-match])").length, 0,
|
||||
is(withScope.target.querySelectorAll(".variables-view-property:not([unmatched])").length, 0,
|
||||
"There should be 0 properties displayed in the with scope.");
|
||||
is(functionScope.target.querySelectorAll(".variables-view-property:not([non-match])").length, 0,
|
||||
is(functionScope.target.querySelectorAll(".variables-view-property:not([unmatched])").length, 0,
|
||||
"There should be 0 properties displayed in the function scope.");
|
||||
is(globalScope.target.querySelectorAll(".variables-view-property:not([non-match])").length, 0,
|
||||
is(globalScope.target.querySelectorAll(".variables-view-property:not([unmatched])").length, 0,
|
||||
"There should be 0 properties displayed in the global scope.");
|
||||
|
||||
is(localScope.target.querySelectorAll(".variables-view-variable:not([non-match]) > .title > .name")[0].getAttribute("value"),
|
||||
is(localScope.target.querySelectorAll(".variables-view-variable:not([unmatched]) > .title > .name")[0].getAttribute("value"),
|
||||
"__proto__", "The only inner variable displayed should be '__proto__'");
|
||||
is(localScope.target.querySelectorAll(".variables-view-property:not([non-match]) > .title > .name")[0].getAttribute("value"),
|
||||
is(localScope.target.querySelectorAll(".variables-view-property:not([unmatched]) > .title > .name")[0].getAttribute("value"),
|
||||
"constructor", "The first inner property displayed should be 'constructor'");
|
||||
is(localScope.target.querySelectorAll(".variables-view-property:not([non-match]) > .title > .name")[1].getAttribute("value"),
|
||||
is(localScope.target.querySelectorAll(".variables-view-property:not([unmatched]) > .title > .name")[1].getAttribute("value"),
|
||||
"__proto__", "The second inner property displayed should be '__proto__'");
|
||||
is(localScope.target.querySelectorAll(".variables-view-property:not([non-match]) > .title > .name")[2].getAttribute("value"),
|
||||
is(localScope.target.querySelectorAll(".variables-view-property:not([unmatched]) > .title > .name")[2].getAttribute("value"),
|
||||
"constructor", "The third inner property displayed should be 'constructor'");
|
||||
}
|
||||
|
||||
|
@ -72,36 +72,36 @@ function testVariablesAndPropertiesFiltering() {
|
||||
is(constr2Var.expanded, true,
|
||||
"The constr2Var should be expanded.");
|
||||
|
||||
is(localScope.target.querySelectorAll(".variables-view-variable:not([non-match])").length, 1,
|
||||
is(localScope.target.querySelectorAll(".variables-view-variable:not([unmatched])").length, 1,
|
||||
"There should be 1 variable displayed in the local scope.");
|
||||
is(withScope.target.querySelectorAll(".variables-view-variable:not([non-match])").length, 0,
|
||||
is(withScope.target.querySelectorAll(".variables-view-variable:not([unmatched])").length, 0,
|
||||
"There should be 0 variables displayed in the with scope.");
|
||||
is(functionScope.target.querySelectorAll(".variables-view-variable:not([non-match])").length, 0,
|
||||
is(functionScope.target.querySelectorAll(".variables-view-variable:not([unmatched])").length, 0,
|
||||
"There should be 0 variables displayed in the function scope.");
|
||||
is(globalScope.target.querySelectorAll(".variables-view-variable:not([non-match])").length, 0,
|
||||
is(globalScope.target.querySelectorAll(".variables-view-variable:not([unmatched])").length, 0,
|
||||
"There should be no variables displayed in the global scope.");
|
||||
|
||||
is(localScope.target.querySelectorAll(".variables-view-property:not([non-match])").length, 4,
|
||||
is(localScope.target.querySelectorAll(".variables-view-property:not([unmatched])").length, 4,
|
||||
"There should be 4 properties displayed in the local scope.");
|
||||
is(withScope.target.querySelectorAll(".variables-view-property:not([non-match])").length, 0,
|
||||
is(withScope.target.querySelectorAll(".variables-view-property:not([unmatched])").length, 0,
|
||||
"There should be 0 properties displayed in the with scope.");
|
||||
is(functionScope.target.querySelectorAll(".variables-view-property:not([non-match])").length, 0,
|
||||
is(functionScope.target.querySelectorAll(".variables-view-property:not([unmatched])").length, 0,
|
||||
"There should be 0 properties displayed in the function scope.");
|
||||
is(globalScope.target.querySelectorAll(".variables-view-property:not([non-match])").length, 0,
|
||||
is(globalScope.target.querySelectorAll(".variables-view-property:not([unmatched])").length, 0,
|
||||
"There should be 0 properties displayed in the global scope.");
|
||||
|
||||
is(localScope.target.querySelectorAll(".variables-view-variable:not([non-match]) > .title > .name")[0].getAttribute("value"),
|
||||
is(localScope.target.querySelectorAll(".variables-view-variable:not([unmatched]) > .title > .name")[0].getAttribute("value"),
|
||||
"__proto__", "The only inner variable displayed should be '__proto__'");
|
||||
is(localScope.target.querySelectorAll(".variables-view-property:not([non-match]) > .title > .name")[0].getAttribute("value"),
|
||||
is(localScope.target.querySelectorAll(".variables-view-property:not([unmatched]) > .title > .name")[0].getAttribute("value"),
|
||||
"constructor", "The first inner property displayed should be 'constructor'");
|
||||
is(localScope.target.querySelectorAll(".variables-view-property:not([non-match]) > .title > .name")[1].getAttribute("value"),
|
||||
is(localScope.target.querySelectorAll(".variables-view-property:not([unmatched]) > .title > .name")[1].getAttribute("value"),
|
||||
"__proto__", "The second inner property displayed should be '__proto__'");
|
||||
is(localScope.target.querySelectorAll(".variables-view-property:not([non-match]) > .title > .name")[2].getAttribute("value"),
|
||||
is(localScope.target.querySelectorAll(".variables-view-property:not([unmatched]) > .title > .name")[2].getAttribute("value"),
|
||||
"constructor", "The third inner property displayed should be 'constructor'");
|
||||
|
||||
is(localScope.target.querySelectorAll(".variables-view-property:not([non-match]) > .title > .name")[3].getAttribute("value"),
|
||||
is(localScope.target.querySelectorAll(".variables-view-property:not([unmatched]) > .title > .name")[3].getAttribute("value"),
|
||||
"name", "The fourth inner property displayed should be 'name'");
|
||||
is(localScope.target.querySelectorAll(".variables-view-property:not([non-match]) > .title > .value")[3].getAttribute("value"),
|
||||
is(localScope.target.querySelectorAll(".variables-view-property:not([unmatched]) > .title > .value")[3].getAttribute("value"),
|
||||
"\"Function\"", "The fourth inner property displayed should be '\"Function\"'");
|
||||
}
|
||||
|
||||
|
@ -58,20 +58,20 @@ function testVariablesAndPropertiesFiltering() {
|
||||
is(globalScope.expanded, true,
|
||||
"The globalScope should be expanded.");
|
||||
|
||||
is(localScope.target.querySelectorAll(".variables-view-variable:not([non-match])").length, 1,
|
||||
is(localScope.target.querySelectorAll(".variables-view-variable:not([unmatched])").length, 1,
|
||||
"There should be 1 variable displayed in the local scope.");
|
||||
is(withScope.target.querySelectorAll(".variables-view-variable:not([non-match])").length, 0,
|
||||
is(withScope.target.querySelectorAll(".variables-view-variable:not([unmatched])").length, 0,
|
||||
"There should be 0 variables displayed in the with scope.");
|
||||
is(functionScope.target.querySelectorAll(".variables-view-variable:not([non-match])").length, 0,
|
||||
is(functionScope.target.querySelectorAll(".variables-view-variable:not([unmatched])").length, 0,
|
||||
"There should be 0 variables displayed in the function scope.");
|
||||
|
||||
is(localScope.target.querySelectorAll(".variables-view-property:not([non-match])").length, 0,
|
||||
is(localScope.target.querySelectorAll(".variables-view-property:not([unmatched])").length, 0,
|
||||
"There should be 0 properties displayed in the local scope.");
|
||||
is(withScope.target.querySelectorAll(".variables-view-property:not([non-match])").length, 0,
|
||||
is(withScope.target.querySelectorAll(".variables-view-property:not([unmatched])").length, 0,
|
||||
"There should be 0 properties displayed in the with scope.");
|
||||
is(functionScope.target.querySelectorAll(".variables-view-property:not([non-match])").length, 0,
|
||||
is(functionScope.target.querySelectorAll(".variables-view-property:not([unmatched])").length, 0,
|
||||
"There should be 0 properties displayed in the function scope.");
|
||||
is(globalScope.target.querySelectorAll(".variables-view-property:not([non-match])").length, 0,
|
||||
is(globalScope.target.querySelectorAll(".variables-view-property:not([unmatched])").length, 0,
|
||||
"There should be 0 properties displayed in the global scope.");
|
||||
}
|
||||
|
||||
@ -79,9 +79,9 @@ function testVariablesAndPropertiesFiltering() {
|
||||
typeText(gSearchBox, "*one");
|
||||
testFiltered("one");
|
||||
|
||||
isnot(globalScope.target.querySelectorAll(".variables-view-variable:not([non-match])").length, 0,
|
||||
isnot(globalScope.target.querySelectorAll(".variables-view-variable:not([unmatched])").length, 0,
|
||||
"There should be some variables displayed in the global scope.");
|
||||
is(localScope.target.querySelectorAll(".variables-view-variable:not([non-match]) > .title > .name")[0].getAttribute("value"),
|
||||
is(localScope.target.querySelectorAll(".variables-view-variable:not([unmatched]) > .title > .name")[0].getAttribute("value"),
|
||||
"one", "The only inner variable displayed should be 'one'");
|
||||
}
|
||||
|
||||
@ -104,9 +104,9 @@ function testVariablesAndPropertiesFiltering() {
|
||||
typeText(gSearchBox, "*two");
|
||||
testFiltered("two");
|
||||
|
||||
is(globalScope.target.querySelectorAll(".variables-view-variable:not([non-match])").length, 0,
|
||||
is(globalScope.target.querySelectorAll(".variables-view-variable:not([unmatched])").length, 0,
|
||||
"There should be no variables displayed in the global scope.");
|
||||
is(localScope.target.querySelectorAll(".variables-view-variable:not([non-match]) > .title > .name")[0].getAttribute("value"),
|
||||
is(localScope.target.querySelectorAll(".variables-view-variable:not([unmatched]) > .title > .name")[0].getAttribute("value"),
|
||||
"two", "The only inner variable displayed should be 'two'");
|
||||
}
|
||||
|
||||
|
@ -58,7 +58,7 @@ function testVariablesAndPropertiesFiltering() {
|
||||
assertScopeExpansion([true, true, true, true]);
|
||||
assertVariablesCountAtLeast([0, 0, 1, 0]);
|
||||
|
||||
is(functionScope.target.querySelectorAll(".variables-view-variable:not([non-match]) > .title > .name")[0].getAttribute("value"),
|
||||
is(functionScope.target.querySelectorAll(".variables-view-variable:not([unmatched]) > .title > .name")[0].getAttribute("value"),
|
||||
"arguments", "The arguments pseudoarray should be visible.");
|
||||
is(functionScope.get("arguments").expanded, false,
|
||||
"The arguments pseudoarray in functionScope should not be expanded.");
|
||||
@ -69,12 +69,12 @@ function testVariablesAndPropertiesFiltering() {
|
||||
assertScopeExpansion([true, true, true, true]);
|
||||
assertVariablesCountAtLeast([0, 0, 1, 1]);
|
||||
|
||||
is(functionScope.target.querySelectorAll(".variables-view-variable:not([non-match]) > .title > .name")[0].getAttribute("value"),
|
||||
is(functionScope.target.querySelectorAll(".variables-view-variable:not([unmatched]) > .title > .name")[0].getAttribute("value"),
|
||||
"arguments", "The arguments pseudoarray should be visible.");
|
||||
is(functionScope.get("arguments").expanded, false,
|
||||
"The arguments pseudoarray in functionScope should not be expanded.");
|
||||
|
||||
is(globalScope.target.querySelectorAll(".variables-view-variable:not([non-match]) > .title > .name")[0].getAttribute("value"),
|
||||
is(globalScope.target.querySelectorAll(".variables-view-variable:not([unmatched]) > .title > .name")[0].getAttribute("value"),
|
||||
"EventTarget", "The EventTarget object should be visible.");
|
||||
is(globalScope.get("EventTarget").expanded, false,
|
||||
"The EventTarget object in globalScope should not be expanded.");
|
||||
@ -85,17 +85,17 @@ function testVariablesAndPropertiesFiltering() {
|
||||
assertScopeExpansion([true, true, true, true]);
|
||||
assertVariablesCountAtLeast([0, 1, 3, 1]);
|
||||
|
||||
is(functionScope.target.querySelectorAll(".variables-view-variable:not([non-match]) > .title > .name")[0].getAttribute("value"),
|
||||
is(functionScope.target.querySelectorAll(".variables-view-variable:not([unmatched]) > .title > .name")[0].getAttribute("value"),
|
||||
"aNumber", "The aNumber param should be visible.");
|
||||
is(functionScope.get("aNumber").expanded, false,
|
||||
"The aNumber param in functionScope should not be expanded.");
|
||||
|
||||
is(functionScope.target.querySelectorAll(".variables-view-variable:not([non-match]) > .title > .name")[1].getAttribute("value"),
|
||||
is(functionScope.target.querySelectorAll(".variables-view-variable:not([unmatched]) > .title > .name")[1].getAttribute("value"),
|
||||
"a", "The a variable should be visible.");
|
||||
is(functionScope.get("a").expanded, false,
|
||||
"The a variable in functionScope should not be expanded.");
|
||||
|
||||
is(functionScope.target.querySelectorAll(".variables-view-variable:not([non-match]) > .title > .name")[2].getAttribute("value"),
|
||||
is(functionScope.target.querySelectorAll(".variables-view-variable:not([unmatched]) > .title > .name")[2].getAttribute("value"),
|
||||
"arguments", "The arguments pseudoarray should be visible.");
|
||||
is(functionScope.get("arguments").expanded, false,
|
||||
"The arguments pseudoarray in functionScope should not be expanded.");
|
||||
@ -106,37 +106,37 @@ function testVariablesAndPropertiesFiltering() {
|
||||
assertScopeExpansion([true, true, true, true]);
|
||||
assertVariablesCountAtLeast([4, 1, 3, 1]);
|
||||
|
||||
is(localScope.target.querySelectorAll(".variables-view-variable:not([non-match]) > .title > .name")[0].getAttribute("value"),
|
||||
is(localScope.target.querySelectorAll(".variables-view-variable:not([unmatched]) > .title > .name")[0].getAttribute("value"),
|
||||
"this", "The this reference should be visible.");
|
||||
is(localScope.get("this").expanded, false,
|
||||
"The this reference in localScope should not be expanded.");
|
||||
|
||||
is(localScope.target.querySelectorAll(".variables-view-variable:not([non-match]) > .title > .name")[1].getAttribute("value"),
|
||||
is(localScope.target.querySelectorAll(".variables-view-variable:not([unmatched]) > .title > .name")[1].getAttribute("value"),
|
||||
"one", "The one variable should be visible.");
|
||||
is(localScope.get("one").expanded, false,
|
||||
"The one variable in localScope should not be expanded.");
|
||||
|
||||
is(localScope.target.querySelectorAll(".variables-view-variable:not([non-match]) > .title > .name")[2].getAttribute("value"),
|
||||
is(localScope.target.querySelectorAll(".variables-view-variable:not([unmatched]) > .title > .name")[2].getAttribute("value"),
|
||||
"two", "The two variable should be visible.");
|
||||
is(localScope.get("two").expanded, false,
|
||||
"The two variable in localScope should not be expanded.");
|
||||
|
||||
is(localScope.target.querySelectorAll(".variables-view-variable:not([non-match]) > .title > .name")[3].getAttribute("value"),
|
||||
is(localScope.target.querySelectorAll(".variables-view-variable:not([unmatched]) > .title > .name")[3].getAttribute("value"),
|
||||
"__proto__", "The __proto__ reference should be visible.");
|
||||
is(localScope.get("__proto__").expanded, false,
|
||||
"The __proto__ reference in localScope should not be expanded.");
|
||||
|
||||
is(functionScope.target.querySelectorAll(".variables-view-variable:not([non-match]) > .title > .name")[0].getAttribute("value"),
|
||||
is(functionScope.target.querySelectorAll(".variables-view-variable:not([unmatched]) > .title > .name")[0].getAttribute("value"),
|
||||
"aNumber", "The aNumber param should be visible.");
|
||||
is(functionScope.get("aNumber").expanded, false,
|
||||
"The aNumber param in functionScope should not be expanded.");
|
||||
|
||||
is(functionScope.target.querySelectorAll(".variables-view-variable:not([non-match]) > .title > .name")[1].getAttribute("value"),
|
||||
is(functionScope.target.querySelectorAll(".variables-view-variable:not([unmatched]) > .title > .name")[1].getAttribute("value"),
|
||||
"a", "The a variable should be visible.");
|
||||
is(functionScope.get("a").expanded, false,
|
||||
"The a variable in functionScope should not be expanded.");
|
||||
|
||||
is(functionScope.target.querySelectorAll(".variables-view-variable:not([non-match]) > .title > .name")[2].getAttribute("value"),
|
||||
is(functionScope.target.querySelectorAll(".variables-view-variable:not([unmatched]) > .title > .name")[2].getAttribute("value"),
|
||||
"arguments", "The arguments pseudoarray should be visible.");
|
||||
is(functionScope.get("arguments").expanded, false,
|
||||
"The arguments pseudoarray in functionScope should not be expanded.");
|
||||
@ -162,19 +162,19 @@ function testVariablesAndPropertiesFiltering() {
|
||||
}
|
||||
|
||||
function assertVariablesCountAtLeast(aCounts) {
|
||||
ok(localScope.target.querySelectorAll(".variables-view-variable:not([non-match])").length >= aCounts[0],
|
||||
ok(localScope.target.querySelectorAll(".variables-view-variable:not([unmatched])").length >= aCounts[0],
|
||||
"There should be " + aCounts[0] +
|
||||
" variable displayed in the local scope (" + step + ").");
|
||||
|
||||
ok(withScope.target.querySelectorAll(".variables-view-variable:not([non-match])").length >= aCounts[1],
|
||||
ok(withScope.target.querySelectorAll(".variables-view-variable:not([unmatched])").length >= aCounts[1],
|
||||
"There should be " + aCounts[1] +
|
||||
" variable displayed in the with scope (" + step + ").");
|
||||
|
||||
ok(functionScope.target.querySelectorAll(".variables-view-variable:not([non-match])").length >= aCounts[2],
|
||||
ok(functionScope.target.querySelectorAll(".variables-view-variable:not([unmatched])").length >= aCounts[2],
|
||||
"There should be " + aCounts[2] +
|
||||
" variable displayed in the function scope (" + step + ").");
|
||||
|
||||
ok(globalScope.target.querySelectorAll(".variables-view-variable:not([non-match])").length >= aCounts[3],
|
||||
ok(globalScope.target.querySelectorAll(".variables-view-variable:not([unmatched])").length >= aCounts[3],
|
||||
"There should be " + aCounts[3] +
|
||||
" variable displayed in the global scope (" + step + ").");
|
||||
|
||||
|
@ -19,9 +19,9 @@ function test() {
|
||||
is(tooltip.querySelectorAll(".variables-view-container").length, 1,
|
||||
"There should be one variables view container added to the tooltip.");
|
||||
|
||||
is(tooltip.querySelectorAll(".variables-view-scope[non-header]").length, 1,
|
||||
is(tooltip.querySelectorAll(".variables-view-scope[untitled]").length, 1,
|
||||
"There should be one scope with no header displayed.");
|
||||
is(tooltip.querySelectorAll(".variables-view-variable[non-header]").length, 1,
|
||||
is(tooltip.querySelectorAll(".variables-view-variable[untitled]").length, 1,
|
||||
"There should be one variable with no header displayed.");
|
||||
|
||||
is(tooltip.querySelectorAll(".variables-view-property").length, 2,
|
||||
|
@ -19,9 +19,9 @@ function test() {
|
||||
is(tooltip.querySelectorAll(".variables-view-container").length, 1,
|
||||
"There should be one variables view container added to the tooltip.");
|
||||
|
||||
is(tooltip.querySelectorAll(".variables-view-scope[non-header]").length, 1,
|
||||
is(tooltip.querySelectorAll(".variables-view-scope[untitled]").length, 1,
|
||||
"There should be one scope with no header displayed.");
|
||||
is(tooltip.querySelectorAll(".variables-view-variable[non-header]").length, 1,
|
||||
is(tooltip.querySelectorAll(".variables-view-variable[untitled]").length, 1,
|
||||
"There should be one variable with no header displayed.");
|
||||
|
||||
is(tooltip.querySelectorAll(".variables-view-property").length, 7,
|
||||
|
@ -33,9 +33,9 @@ function test() {
|
||||
is(tooltip.querySelectorAll(".devtools-tooltip-simple-text").length, 0,
|
||||
"There should be no simple text node added to the tooltip.");
|
||||
|
||||
is(tooltip.querySelectorAll(".variables-view-scope[non-header]").length, 1,
|
||||
is(tooltip.querySelectorAll(".variables-view-scope[untitled]").length, 1,
|
||||
"There should be one scope with no header displayed.");
|
||||
is(tooltip.querySelectorAll(".variables-view-variable[non-header]").length, 1,
|
||||
is(tooltip.querySelectorAll(".variables-view-variable[untitled]").length, 1,
|
||||
"There should be one variable with no header displayed.");
|
||||
|
||||
ok(tooltip.querySelectorAll(".variables-view-property").length >= propertyCount,
|
||||
|
@ -1476,7 +1476,7 @@ Scope.prototype = {
|
||||
if (this._isHeaderVisible || !this._nameString) {
|
||||
return;
|
||||
}
|
||||
this._target.removeAttribute("non-header");
|
||||
this._target.removeAttribute("untitled");
|
||||
this._isHeaderVisible = true;
|
||||
},
|
||||
|
||||
@ -1489,7 +1489,7 @@ Scope.prototype = {
|
||||
return;
|
||||
}
|
||||
this.expand();
|
||||
this._target.setAttribute("non-header", "");
|
||||
this._target.setAttribute("untitled", "");
|
||||
this._isHeaderVisible = false;
|
||||
},
|
||||
|
||||
@ -1928,10 +1928,10 @@ Scope.prototype = {
|
||||
}
|
||||
if (aStatus) {
|
||||
this._isMatch = true;
|
||||
this.target.removeAttribute("non-match");
|
||||
this.target.removeAttribute("unmatched");
|
||||
} else {
|
||||
this._isMatch = false;
|
||||
this.target.setAttribute("non-match", "");
|
||||
this.target.setAttribute("unmatched", "");
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -50,9 +50,9 @@
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.variables-view-scope[non-header] > .title,
|
||||
.variable-or-property[non-header] > .title,
|
||||
.variable-or-property[non-match] > .title {
|
||||
.variables-view-scope[untitled] > .title,
|
||||
.variable-or-property[untitled] > .title,
|
||||
.variable-or-property[unmatched] > .title {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
af
|
||||
ak
|
||||
an
|
||||
ar
|
||||
ast
|
||||
be
|
||||
@ -79,6 +80,7 @@ th
|
||||
tr
|
||||
uk
|
||||
vi
|
||||
xh
|
||||
zh-CN
|
||||
zh-TW
|
||||
zu
|
||||
|
@ -308,10 +308,11 @@ var BrowserUI = {
|
||||
|
||||
isStartURI: function isStartURI(aURI) {
|
||||
aURI = aURI || Browser.selectedBrowser.currentURI.spec;
|
||||
return aURI == kStartURI;
|
||||
return aURI == kStartURI || aURI == "about:home";
|
||||
},
|
||||
|
||||
updateStartURIAttributes: function (aURI) {
|
||||
let wasStart = Elements.windowState.hasAttribute("startpage");
|
||||
aURI = aURI || Browser.selectedBrowser.currentURI.spec;
|
||||
if (this.isStartURI(aURI)) {
|
||||
ContextUI.displayNavbar();
|
||||
@ -319,6 +320,13 @@ var BrowserUI = {
|
||||
} else if (aURI != "about:blank") { // about:blank is loaded briefly for new tabs; ignore it
|
||||
Elements.windowState.removeAttribute("startpage");
|
||||
}
|
||||
|
||||
let isStart = Elements.windowState.hasAttribute("startpage");
|
||||
if (wasStart != isStart) {
|
||||
let event = document.createEvent("Events");
|
||||
event.initEvent("StartUIChange", true, true);
|
||||
Browser.selectedBrowser.dispatchEvent(event);
|
||||
}
|
||||
},
|
||||
|
||||
getDisplayURI: function(browser) {
|
||||
|
@ -1305,6 +1305,7 @@ Tab.prototype = {
|
||||
}
|
||||
browser.addEventListener("pageshow", onPageShowEvent, true);
|
||||
browser.addEventListener("DOMWindowCreated", this, false);
|
||||
browser.addEventListener("StartUIChange", this, false);
|
||||
Elements.browsers.addEventListener("SizeChanged", this, false);
|
||||
|
||||
browser.messageManager.addMessageListener("Content:StateChange", this);
|
||||
@ -1316,12 +1317,19 @@ Tab.prototype = {
|
||||
|
||||
updateViewport: function (aEvent) {
|
||||
// <meta name=viewport> is not yet supported; just use the browser size.
|
||||
this.browser.setWindowSize(this.browser.clientWidth, this.browser.clientHeight);
|
||||
let browser = this.browser;
|
||||
|
||||
// On the start page we add padding to keep the browser above the navbar.
|
||||
let paddingBottom = parseInt(getComputedStyle(browser).paddingBottom, 10);
|
||||
let height = browser.clientHeight - paddingBottom;
|
||||
|
||||
browser.setWindowSize(browser.clientWidth, height);
|
||||
},
|
||||
|
||||
handleEvent: function (aEvent) {
|
||||
switch (aEvent.type) {
|
||||
case "DOMWindowCreated":
|
||||
case "StartUIChange":
|
||||
this.updateViewport();
|
||||
break;
|
||||
case "SizeChanged":
|
||||
@ -1354,6 +1362,7 @@ Tab.prototype = {
|
||||
destroy: function destroy() {
|
||||
this._browser.messageManager.removeMessageListener("Content:StateChange", this);
|
||||
this._browser.removeEventListener("DOMWindowCreated", this, false);
|
||||
this._browser.removeEventListener("StartUIChange", this, false);
|
||||
Elements.browsers.removeEventListener("SizeChanged", this, false);
|
||||
clearTimeout(this._updateThumbnailTimeout);
|
||||
|
||||
|
@ -18,8 +18,7 @@ var MetroDownloadsView = {
|
||||
_inited: false,
|
||||
_progressAlert: null,
|
||||
_lastSec: Infinity,
|
||||
_notificationBox: null,
|
||||
_progressNotification: null,
|
||||
|
||||
_progressNotificationInfo: new Map(),
|
||||
_runDownloadBooleanMap: new Map(),
|
||||
|
||||
@ -56,11 +55,12 @@ var MetroDownloadsView = {
|
||||
Services.obs.addObserver(this, "dl-run", true);
|
||||
Services.obs.addObserver(this, "dl-failed", true);
|
||||
|
||||
this._notificationBox = Browser.getNotificationBox();
|
||||
|
||||
this._progress = new DownloadProgressListener(this);
|
||||
this.manager.addListener(this._progress);
|
||||
|
||||
Elements.tabList.addEventListener("TabClose", this, false);
|
||||
|
||||
this._downloadProgressIndicator = document.getElementById("download-progress");
|
||||
|
||||
if (this.manager.activeDownloadCount) {
|
||||
@ -74,10 +74,54 @@ var MetroDownloadsView = {
|
||||
Services.obs.removeObserver(this, "dl-done");
|
||||
Services.obs.removeObserver(this, "dl-run");
|
||||
Services.obs.removeObserver(this, "dl-failed");
|
||||
if (Elements && Elements.tabList)
|
||||
Elements.tabList.removeEventListener("TabClose", this);
|
||||
}
|
||||
},
|
||||
|
||||
_restartWithActiveDownloads: function() {
|
||||
get _notificationBox() {
|
||||
return Browser.getNotificationBox(Browser.selectedBrowser);
|
||||
},
|
||||
|
||||
get _notificationBoxes() {
|
||||
let currentBox = this._notificationBox;
|
||||
let boxes = [
|
||||
currentBox
|
||||
];
|
||||
for (let { linkedBrowser } of Elements.tabList.children) {
|
||||
if (linkedBrowser !== Browser.selectedBrowser) {
|
||||
let notificationBox = Browser.getNotificationBox(linkedBrowser);
|
||||
if (notificationBox)
|
||||
boxes.push(notificationBox);
|
||||
}
|
||||
}
|
||||
return boxes;
|
||||
},
|
||||
|
||||
get _progressNotification() {
|
||||
let notn = this._getNotificationWithValue("download-progress");
|
||||
let currentBox = this._notificationBox;
|
||||
// move the progress notification if attached to a different browser
|
||||
if (notn && notn.parentNode !== currentBox) {
|
||||
notn.parentNode.removeNotification(notn);
|
||||
currentBox.insertBefore(notn, currentBox.firstChild);
|
||||
}
|
||||
return notn;
|
||||
},
|
||||
|
||||
_getNotificationWithValue: function(aValue) {
|
||||
let notn;
|
||||
let allNotificationBoxes = this._notificationBoxes;
|
||||
for(let box of allNotificationBoxes) {
|
||||
notn = box.getNotificationWithValue(aValue);
|
||||
if (notn) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return notn;
|
||||
},
|
||||
|
||||
_restartWithActiveDownloads: function() {
|
||||
let activeDownloads = this.manager.activeDownloads;
|
||||
|
||||
while (activeDownloads.hasMoreElements()) {
|
||||
@ -140,9 +184,9 @@ var MetroDownloadsView = {
|
||||
this._runDownloadBooleanMap.delete(aDownload.targetFile.path);
|
||||
this._downloadCount--;
|
||||
this._downloadsInProgress--;
|
||||
if (this._downloadsInProgress <= 0) {
|
||||
this._notificationBox.removeNotification(this._progressNotification);
|
||||
this._progressNotification = null;
|
||||
let notn = this._progressNotification;
|
||||
if (notn && this._downloadsInProgress <= 0) {
|
||||
this._notificationBox.removeNotification(notn);
|
||||
}
|
||||
} catch (ex) {
|
||||
Util.dumpLn("Failed to cancel download, with id: "+aDownload.id+", download target URI spec: " + fileURI.spec);
|
||||
@ -384,32 +428,35 @@ var MetroDownloadsView = {
|
||||
},
|
||||
|
||||
onDownloadButton: function dv_onDownloadButton() {
|
||||
if (this._downloadsInProgress) {
|
||||
if (!this._removeNotification("download-progress")) {
|
||||
this.updateInfobar();
|
||||
}
|
||||
} else if (this._downloadCount) {
|
||||
if (!this._removeNotification("download-complete")) {
|
||||
this._showDownloadCompleteNotification();
|
||||
}
|
||||
let progressNotification = this._getNotificationWithValue("download-progress");
|
||||
let wasProgressVisible = (progressNotification &&
|
||||
progressNotification.parentNode == this._notificationBox);
|
||||
let completeNotification = this._getNotificationWithValue("download-complete");
|
||||
let wasCompleteVisible = (completeNotification &&
|
||||
completeNotification.parentNode == this._notificationBox);
|
||||
|
||||
this._removeNotification("download-complete");
|
||||
this._removeNotification("download-progress");
|
||||
|
||||
if (this._downloadsInProgress && !wasProgressVisible) {
|
||||
this.updateInfobar();
|
||||
} else if (this._downloadCount && !wasCompleteVisible) {
|
||||
this._showDownloadCompleteNotification();
|
||||
}
|
||||
},
|
||||
|
||||
_removeNotification: function (aValue) {
|
||||
let notification = this._notificationBox.getNotificationWithValue(aValue);
|
||||
if (!notification) {
|
||||
return false;
|
||||
}
|
||||
this._notificationBox.removeNotification(notification);
|
||||
return true;
|
||||
let notification = this._getNotificationWithValue(aValue);
|
||||
return notification &&
|
||||
notification.parentNode.removeNotification(notification);
|
||||
},
|
||||
|
||||
updateInfobar: function dv_updateInfobar() {
|
||||
let message = this._computeDownloadProgressString();
|
||||
this._updateCircularProgressMeter();
|
||||
|
||||
if (this._progressNotification == null ||
|
||||
!this._notificationBox.getNotificationWithValue("download-progress")) {
|
||||
let notn = this._progressNotification;
|
||||
if (!notn) {
|
||||
let cancelButtonText =
|
||||
Strings.browser.GetStringFromName("downloadCancel");
|
||||
|
||||
@ -425,23 +472,23 @@ var MetroDownloadsView = {
|
||||
}
|
||||
];
|
||||
|
||||
this._progressNotification =
|
||||
this.showNotification("download-progress", message, buttons,
|
||||
this._notificationBox.PRIORITY_WARNING_LOW);
|
||||
notn = this.showNotification("download-progress", message, buttons,
|
||||
this._notificationBox.PRIORITY_WARNING_LOW);
|
||||
|
||||
ContextUI.displayNavbar();
|
||||
} else {
|
||||
this._progressNotification.label = message;
|
||||
notn.label = message;
|
||||
}
|
||||
},
|
||||
|
||||
updateDownload: function dv_updateDownload(aDownload) {
|
||||
if (this._progressNotification != null) {
|
||||
this._saveDownloadData(aDownload);
|
||||
this._progressNotification.label =
|
||||
this._saveDownloadData(aDownload);
|
||||
let notn = this._progressNotification;
|
||||
if (notn) {
|
||||
notn.label =
|
||||
this._computeDownloadProgressString(aDownload);
|
||||
this._updateCircularProgressMeter();
|
||||
}
|
||||
this._updateCircularProgressMeter();
|
||||
},
|
||||
|
||||
watchDownload: function dv_watchDownload(aDownload) {
|
||||
@ -486,8 +533,9 @@ var MetroDownloadsView = {
|
||||
this._showDownloadCompleteToast();
|
||||
this._showDownloadCompleteNotification();
|
||||
}
|
||||
this._notificationBox.removeNotification(this._progressNotification);
|
||||
this._progressNotification = null;
|
||||
let notn = this._progressNotification;
|
||||
if (notn)
|
||||
this._notificationBox.removeNotification(notn);
|
||||
}
|
||||
break;
|
||||
case "dl-failed":
|
||||
@ -497,6 +545,22 @@ var MetroDownloadsView = {
|
||||
}
|
||||
},
|
||||
|
||||
handleEvent: function(aEvent) {
|
||||
switch (aEvent.type) {
|
||||
case 'TabClose': {
|
||||
let browser = aEvent.originalTarget.linkedBrowser;
|
||||
dump("DownloadNotificationsView handleEvent, got TabClose event for browser: "+browser+"\n");
|
||||
let notn = this._getNotificationWithValue("download-progress");
|
||||
if (notn && notn.defaultView == browser.contentWindow) {
|
||||
let nextTab = Browser.getNextTab(aEvent.originalTarget);
|
||||
let box = Browser.getNotificationBox(nextTab.linkedBrowser);
|
||||
box.insertBefore(notn, box.firstChild);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
QueryInterface: function (aIID) {
|
||||
if (!aIID.equals(Ci.nsIObserver) &&
|
||||
!aIID.equals(Ci.nsISupportsWeakReference) &&
|
||||
|
@ -467,7 +467,7 @@
|
||||
cursor: text;
|
||||
}
|
||||
|
||||
.variable-or-property:not([non-header]) > .variables-view-element-details {
|
||||
.variable-or-property:not([untitled]) > .variables-view-element-details {
|
||||
-moz-margin-start: 10px;
|
||||
}
|
||||
|
||||
@ -632,7 +632,7 @@
|
||||
min-height: 24px;
|
||||
}
|
||||
|
||||
.variable-or-property[non-match] {
|
||||
.variable-or-property[unmatched] {
|
||||
border: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
@ -461,7 +461,7 @@
|
||||
cursor: text;
|
||||
}
|
||||
|
||||
.variable-or-property:not([non-header]) > .variables-view-element-details {
|
||||
.variable-or-property:not([untitled]) > .variables-view-element-details {
|
||||
-moz-margin-start: 10px;
|
||||
}
|
||||
|
||||
@ -626,7 +626,7 @@
|
||||
min-height: 24px;
|
||||
}
|
||||
|
||||
.variable-or-property[non-match] {
|
||||
.variable-or-property[unmatched] {
|
||||
border: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
@ -488,16 +488,16 @@
|
||||
color: #b6babf;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border-left: 1px solid #42484f;
|
||||
-moz-border-start: 1px solid #42484f;
|
||||
-moz-box-align: center;
|
||||
}
|
||||
|
||||
.devtools-tab:first-child {
|
||||
border-left-width: 0;
|
||||
-moz-border-start-width: 0;
|
||||
}
|
||||
|
||||
.devtools-tab:last-child {
|
||||
border-right: 1px solid #5a6169;
|
||||
-moz-border-end: 1px solid #42484f;
|
||||
}
|
||||
|
||||
.devtools-tab > image {
|
||||
@ -522,7 +522,7 @@
|
||||
}
|
||||
|
||||
.devtools-tab:active > image,
|
||||
.devtools-tab[selected=true] > label {
|
||||
.devtools-tab[selected=true] > image {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
@ -546,12 +546,16 @@
|
||||
}
|
||||
|
||||
.devtools-tab[selected=true]:not(:first-child) {
|
||||
padding-left: 1px;
|
||||
-moz-padding-start: 1px;
|
||||
}
|
||||
|
||||
.devtools-tab[selected=true]:last-child {
|
||||
-moz-padding-end: 1px;
|
||||
}
|
||||
|
||||
.devtools-tab[selected=true] + .devtools-tab {
|
||||
border-left-width: 0;
|
||||
padding-left: 1px;
|
||||
-moz-border-start-width: 0;
|
||||
-moz-padding-start: 1px;
|
||||
}
|
||||
|
||||
.devtools-tab:not([selected=true]).highlighted {
|
||||
|
@ -464,7 +464,7 @@
|
||||
cursor: text;
|
||||
}
|
||||
|
||||
.variable-or-property:not([non-header]) > .variables-view-element-details {
|
||||
.variable-or-property:not([untitled]) > .variables-view-element-details {
|
||||
-moz-margin-start: 10px;
|
||||
}
|
||||
|
||||
@ -629,7 +629,7 @@
|
||||
min-height: 24px;
|
||||
}
|
||||
|
||||
.variable-or-property[non-match] {
|
||||
.variable-or-property[unmatched] {
|
||||
border: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
@ -10,4 +10,4 @@
|
||||
# hardcoded milestones in the tree from these two files.
|
||||
#--------------------------------------------------------
|
||||
|
||||
28.0a1
|
||||
29.0a1
|
||||
|
@ -1763,7 +1763,29 @@ HTMLMediaElement::CaptureStreamInternal(bool aFinishWhenEnded)
|
||||
}
|
||||
|
||||
OutputMediaStream* out = mOutputStreams.AppendElement();
|
||||
#ifdef DEBUG
|
||||
// Estimate hints based on the type of the media element
|
||||
// under the preference media.capturestream_hints for the
|
||||
// debug builds only. This allows WebRTC Peer Connection
|
||||
// to behave appropriately when media streams generated
|
||||
// via mozCaptureStream*() are added to the Peer Connection.
|
||||
// This functionality is planned to be used as part of Audio
|
||||
// Quality Performance testing for WebRTC.
|
||||
// Bug932845: Revisit this once hints mechanism is dealt with
|
||||
// holistically.
|
||||
uint8_t hints = 0;
|
||||
if (Preferences::GetBool("media.capturestream_hints.enabled")) {
|
||||
nsCOMPtr<nsIDOMHTMLVideoElement> video = do_QueryObject(this);
|
||||
if (video && GetVideoFrameContainer()) {
|
||||
hints = DOMMediaStream::HINT_CONTENTS_VIDEO | DOMMediaStream::HINT_CONTENTS_AUDIO;
|
||||
} else {
|
||||
hints = DOMMediaStream::HINT_CONTENTS_AUDIO;
|
||||
}
|
||||
}
|
||||
out->mStream = DOMMediaStream::CreateTrackUnionStream(window, hints);
|
||||
#else
|
||||
out->mStream = DOMMediaStream::CreateTrackUnionStream(window);
|
||||
#endif
|
||||
nsRefPtr<nsIPrincipal> principal = GetCurrentPrincipal();
|
||||
out->mStream->CombineWithPrincipal(principal);
|
||||
out->mFinishWhenEnded = aFinishWhenEnded;
|
||||
|
@ -25,7 +25,7 @@ public:
|
||||
}
|
||||
|
||||
static BluetoothHidManager* Get();
|
||||
~BluetoothHidManager();
|
||||
virtual ~BluetoothHidManager();
|
||||
|
||||
// HID-specific functions
|
||||
void HandleInputPropertyChanged(const BluetoothSignal& aSignal);
|
||||
|
@ -187,9 +187,9 @@ BluetoothProfileController::Next()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!mDeviceAddress.IsEmpty());
|
||||
MOZ_ASSERT(mProfilesIndex < mProfiles.Length());
|
||||
MOZ_ASSERT(mProfilesIndex < (int)mProfiles.Length());
|
||||
|
||||
if (++mProfilesIndex < mProfiles.Length()) {
|
||||
if (++mProfilesIndex < (int)mProfiles.Length()) {
|
||||
BT_LOGR_PROFILE(mProfiles[mProfilesIndex], "");
|
||||
|
||||
if (mConnect) {
|
||||
|
@ -26,6 +26,7 @@ public:
|
||||
NS_DECL_NSIICCLISTENER
|
||||
|
||||
IccListener() { }
|
||||
virtual ~IccListener() { }
|
||||
|
||||
bool Listen(bool aStart);
|
||||
void SetOwner(BluetoothRilListener *aOwner);
|
||||
@ -42,6 +43,7 @@ public:
|
||||
|
||||
MobileConnectionListener(uint32_t aClientId)
|
||||
: mClientId(aClientId) { }
|
||||
virtual ~MobileConnectionListener() { }
|
||||
|
||||
bool Listen(bool aStart);
|
||||
|
||||
@ -56,6 +58,7 @@ public:
|
||||
NS_DECL_NSITELEPHONYLISTENER
|
||||
|
||||
TelephonyListener() { }
|
||||
virtual ~TelephonyListener() { }
|
||||
|
||||
bool Listen(bool aStart);
|
||||
};
|
||||
|
@ -172,20 +172,6 @@ public:
|
||||
const BluetoothNamedValue& aValue,
|
||||
BluetoothReplyRunnable* aRunnable) = 0;
|
||||
|
||||
/**
|
||||
* Get the path of a device
|
||||
*
|
||||
* @param aAdapterPath Path to the Adapter that's communicating with the device
|
||||
* @param aDeviceAddress Device address (XX:XX:XX:XX:XX:XX format)
|
||||
* @param aDevicePath Return value of path
|
||||
*
|
||||
* @return True if path set correctly, false otherwise
|
||||
*/
|
||||
virtual bool
|
||||
GetDevicePath(const nsAString& aAdapterPath,
|
||||
const nsAString& aDeviceAddress,
|
||||
nsAString& aDevicePath) = 0;
|
||||
|
||||
virtual nsresult
|
||||
CreatePairedDeviceInternal(const nsAString& aAddress,
|
||||
int aTimeout,
|
||||
@ -195,12 +181,6 @@ public:
|
||||
RemoveDeviceInternal(const nsAString& aObjectPath,
|
||||
BluetoothReplyRunnable* aRunnable) = 0;
|
||||
|
||||
virtual nsresult
|
||||
GetScoSocket(const nsAString& aObjectPath,
|
||||
bool aAuth,
|
||||
bool aEncrypt,
|
||||
mozilla::ipc::UnixSocketConsumer* aConsumer) = 0;
|
||||
|
||||
/**
|
||||
* Get corresponding service channel of specific service on remote device.
|
||||
* It's usually the very first step of establishing an outbound connection.
|
||||
|
@ -95,7 +95,7 @@ GetAddressFromObjectPath(const nsAString& aObjectPath)
|
||||
nsString address(aObjectPath);
|
||||
int addressHead = address.RFind("/") + 5;
|
||||
|
||||
MOZ_ASSERT(addressHead + BLUETOOTH_ADDRESS_LENGTH == address.Length());
|
||||
MOZ_ASSERT(addressHead + BLUETOOTH_ADDRESS_LENGTH == (int)address.Length());
|
||||
|
||||
address.Cut(0, addressHead);
|
||||
address.ReplaceChar('_', ':');
|
||||
|
@ -32,7 +32,7 @@ public:
|
||||
};
|
||||
|
||||
static BluetoothA2dpManager* Get();
|
||||
~BluetoothA2dpManager();
|
||||
virtual ~BluetoothA2dpManager();
|
||||
void ResetA2dp();
|
||||
void ResetAvrcp();
|
||||
|
||||
|
@ -84,7 +84,7 @@ public:
|
||||
}
|
||||
|
||||
static BluetoothHfpManager* Get();
|
||||
~BluetoothHfpManager();
|
||||
virtual ~BluetoothHfpManager();
|
||||
|
||||
bool ConnectSco();
|
||||
bool DisconnectSco();
|
||||
|
@ -261,7 +261,7 @@ BluetoothOppManager::ConnectInternal(const nsAString& aDeviceAddress)
|
||||
}
|
||||
|
||||
mSocket =
|
||||
new BluetoothSocket(this, BluetoothSocketType::RFCOMM, true, true);
|
||||
new BluetoothSocket(this, BluetoothSocketType::RFCOMM, false, true);
|
||||
mSocket->Connect(aDeviceAddress, -1);
|
||||
}
|
||||
|
||||
@ -295,7 +295,7 @@ BluetoothOppManager::Listen()
|
||||
}
|
||||
|
||||
mServerSocket =
|
||||
new BluetoothSocket(this, BluetoothSocketType::RFCOMM, true, true);
|
||||
new BluetoothSocket(this, BluetoothSocketType::RFCOMM, false, true);
|
||||
|
||||
if (!mServerSocket->Listen(BluetoothReservedChannels::CHANNEL_OPUSH)) {
|
||||
BT_WARNING("[OPP] Can't listen on RFCOMM socket!");
|
||||
@ -315,7 +315,7 @@ BluetoothOppManager::StartSendingNextFile()
|
||||
|
||||
MOZ_ASSERT(!IsConnected());
|
||||
MOZ_ASSERT(!mBatches.IsEmpty());
|
||||
MOZ_ASSERT(mBatches[0].mBlobs.Length() > mCurrentBlobIndex + 1);
|
||||
MOZ_ASSERT((int)mBatches[0].mBlobs.Length() > mCurrentBlobIndex + 1);
|
||||
|
||||
mBlob = mBatches[0].mBlobs[++mCurrentBlobIndex];
|
||||
|
||||
|
@ -45,7 +45,7 @@ public:
|
||||
static const int DEFAULT_OPP_CHANNEL = 10;
|
||||
static const int MAX_PACKET_LENGTH = 0xFFFE;
|
||||
|
||||
~BluetoothOppManager();
|
||||
virtual ~BluetoothOppManager();
|
||||
static BluetoothOppManager* Get();
|
||||
void ClientDataHandler(mozilla::ipc::UnixSocketRawData* aMessage);
|
||||
void ServerDataHandler(mozilla::ipc::UnixSocketRawData* aMessage);
|
||||
|
@ -965,13 +965,6 @@ BluetoothServiceBluedroid::StopDiscoveryInternal(
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
BluetoothServiceBluedroid::GetDevicePropertiesInternal(
|
||||
const BluetoothSignal& aSignal)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
BluetoothServiceBluedroid::SetProperty(BluetoothObjectType aType,
|
||||
const BluetoothNamedValue& aValue,
|
||||
@ -1033,56 +1026,6 @@ BluetoothServiceBluedroid::SetProperty(BluetoothObjectType aType,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
BluetoothServiceBluedroid::GetDevicePath(const nsAString& aAdapterPath,
|
||||
const nsAString& aDeviceAddress,
|
||||
nsAString& aDevicePath)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BluetoothServiceBluedroid::AddServiceRecords(const char* serviceName,
|
||||
unsigned long long uuidMsb,
|
||||
unsigned long long uuidLsb,
|
||||
int channel)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BluetoothServiceBluedroid::RemoveServiceRecords(const char* serviceName,
|
||||
unsigned long long uuidMsb,
|
||||
unsigned long long uuidLsb,
|
||||
int channel)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BluetoothServiceBluedroid::AddReservedServicesInternal(
|
||||
const nsTArray<uint32_t>& aServices,
|
||||
nsTArray<uint32_t>& aServiceHandlesContainer)
|
||||
{
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
bool
|
||||
BluetoothServiceBluedroid::RemoveReservedServicesInternal(
|
||||
const nsTArray<uint32_t>& aServiceHandles)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
nsresult
|
||||
BluetoothServiceBluedroid::GetScoSocket(
|
||||
const nsAString& aObjectPath, bool aAuth, bool aEncrypt,
|
||||
mozilla::ipc::UnixSocketConsumer* aConsumer)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
BluetoothServiceBluedroid::GetServiceChannel(
|
||||
const nsAString& aDeviceAddress,
|
||||
|
@ -49,44 +49,11 @@ public:
|
||||
virtual nsresult StartDiscoveryInternal(BluetoothReplyRunnable* aRunnable);
|
||||
virtual nsresult StopDiscoveryInternal(BluetoothReplyRunnable* aRunnable);
|
||||
|
||||
virtual nsresult
|
||||
GetDevicePropertiesInternal(const BluetoothSignal& aSignal);
|
||||
|
||||
virtual nsresult
|
||||
SetProperty(BluetoothObjectType aType,
|
||||
const BluetoothNamedValue& aValue,
|
||||
BluetoothReplyRunnable* aRunnable);
|
||||
|
||||
virtual bool
|
||||
GetDevicePath(const nsAString& aAdapterPath,
|
||||
const nsAString& aDeviceAddress,
|
||||
nsAString& aDevicePath);
|
||||
|
||||
static bool
|
||||
AddServiceRecords(const char* serviceName,
|
||||
unsigned long long uuidMsb,
|
||||
unsigned long long uuidLsb,
|
||||
int channel);
|
||||
|
||||
static bool
|
||||
RemoveServiceRecords(const char* serviceName,
|
||||
unsigned long long uuidMsb,
|
||||
unsigned long long uuidLsb,
|
||||
int channel);
|
||||
|
||||
static bool
|
||||
AddReservedServicesInternal(const nsTArray<uint32_t>& aServices,
|
||||
nsTArray<uint32_t>& aServiceHandlesContainer);
|
||||
|
||||
static bool
|
||||
RemoveReservedServicesInternal(const nsTArray<uint32_t>& aServiceHandles);
|
||||
|
||||
virtual nsresult
|
||||
GetScoSocket(const nsAString& aObjectPath,
|
||||
bool aAuth,
|
||||
bool aEncrypt,
|
||||
mozilla::ipc::UnixSocketConsumer* aConsumer);
|
||||
|
||||
virtual nsresult
|
||||
GetServiceChannel(const nsAString& aDeviceAddress,
|
||||
const nsAString& aServiceUuid,
|
||||
|
@ -33,7 +33,7 @@ public:
|
||||
};
|
||||
|
||||
static BluetoothA2dpManager* Get();
|
||||
~BluetoothA2dpManager();
|
||||
virtual ~BluetoothA2dpManager();
|
||||
void ResetA2dp();
|
||||
void ResetAvrcp();
|
||||
|
||||
|
@ -1018,7 +1018,7 @@ BluetoothHfpManager::ReceiveSocketData(BluetoothSocket* aSocket,
|
||||
|
||||
for (uint8_t i = 0; i < atCommandValues.Length(); i++) {
|
||||
CINDType indicatorType = (CINDType) (i + 1);
|
||||
if (indicatorType >= ArrayLength(sCINDItems)) {
|
||||
if (indicatorType >= (int)ArrayLength(sCINDItems)) {
|
||||
// Ignore excess parameters at the end
|
||||
break;
|
||||
}
|
||||
@ -1802,15 +1802,8 @@ BluetoothHfpManager::ConnectSco(BluetoothReplyRunnable* aRunnable)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (sInShutdown) {
|
||||
BT_WARNING("ConnecteSco called while in shutdown!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IsConnected()) {
|
||||
BT_WARNING("BluetoothHfpManager is not connected");
|
||||
return false;
|
||||
}
|
||||
NS_ENSURE_TRUE(!sInShutdown, false);
|
||||
NS_ENSURE_TRUE(IsConnected(), false);
|
||||
|
||||
SocketConnectionStatus status = mScoSocket->GetConnectionStatus();
|
||||
if (status == SocketConnectionStatus::SOCKET_CONNECTED ||
|
||||
@ -1828,16 +1821,14 @@ BluetoothHfpManager::ConnectSco(BluetoothReplyRunnable* aRunnable)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Stop listening
|
||||
mScoSocket->Disconnect();
|
||||
|
||||
mScoRunnable = aRunnable;
|
||||
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
NS_ENSURE_TRUE(bs, false);
|
||||
nsresult rv = bs->GetScoSocket(mDeviceAddress, true, false, mScoSocket);
|
||||
|
||||
mScoSocket->Connect(NS_ConvertUTF16toUTF8(mDeviceAddress), -1);
|
||||
mScoSocketStatus = mScoSocket->GetConnectionStatus();
|
||||
return NS_SUCCEEDED(rv);
|
||||
|
||||
mScoRunnable = aRunnable;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -331,7 +331,7 @@ BluetoothOppManager::StartSendingNextFile()
|
||||
|
||||
MOZ_ASSERT(!IsConnected());
|
||||
MOZ_ASSERT(!mBatches.IsEmpty());
|
||||
MOZ_ASSERT(mBatches[0].mBlobs.Length() > mCurrentBlobIndex + 1);
|
||||
MOZ_ASSERT((int)mBatches[0].mBlobs.Length() > mCurrentBlobIndex + 1);
|
||||
|
||||
mBlob = mBatches[0].mBlobs[++mCurrentBlobIndex];
|
||||
|
||||
|
@ -45,7 +45,7 @@ public:
|
||||
static const int DEFAULT_OPP_CHANNEL = 10;
|
||||
static const int MAX_PACKET_LENGTH = 0xFFFE;
|
||||
|
||||
~BluetoothOppManager();
|
||||
virtual ~BluetoothOppManager();
|
||||
static BluetoothOppManager* Get();
|
||||
void ClientDataHandler(mozilla::ipc::UnixSocketRawData* aMessage);
|
||||
void ServerDataHandler(mozilla::ipc::UnixSocketRawData* aMessage);
|
||||
|
@ -174,7 +174,7 @@ static const char* sBluetoothDBusSignals[] =
|
||||
static nsRefPtr<RawDBusConnection> gThreadConnection;
|
||||
|
||||
// Only A2DP and HID are authorized.
|
||||
static nsTArray<uint32_t> sAuthorizedServiceClass;
|
||||
static nsTArray<BluetoothServiceClass> sAuthorizedServiceClass;
|
||||
|
||||
// The object path of adpater which should be updated after switching Bluetooth.
|
||||
static nsString sAdapterPath;
|
||||
@ -2366,7 +2366,7 @@ BluetoothDBusService::SetProperty(BluetoothObjectType aType,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(aType < ArrayLength(sBluetoothDBusIfaces));
|
||||
MOZ_ASSERT(aType < (int)ArrayLength(sBluetoothDBusIfaces));
|
||||
MOZ_ASSERT(!sAdapterPath.IsEmpty());
|
||||
const char* interface = sBluetoothDBusIfaces[aType];
|
||||
|
||||
@ -2439,15 +2439,6 @@ BluetoothDBusService::SetProperty(BluetoothObjectType aType,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
BluetoothDBusService::GetDevicePath(const nsAString& aAdapterPath,
|
||||
const nsAString& aDeviceAddress,
|
||||
nsAString& aDevicePath)
|
||||
{
|
||||
aDevicePath = GetObjectPathFromAddress(aAdapterPath, aDeviceAddress);
|
||||
return true;
|
||||
}
|
||||
|
||||
nsresult
|
||||
BluetoothDBusService::CreatePairedDeviceInternal(
|
||||
const nsAString& aDeviceAddress,
|
||||
@ -2979,32 +2970,6 @@ BluetoothDBusService::UpdateSdpRecords(const nsAString& aDeviceAddress,
|
||||
DBUS_TYPE_INVALID);
|
||||
}
|
||||
|
||||
nsresult
|
||||
BluetoothDBusService::GetScoSocket(const nsAString& aAddress,
|
||||
bool aAuth,
|
||||
bool aEncrypt,
|
||||
mozilla::ipc::UnixSocketConsumer* aConsumer)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (!mConnection || !gThreadConnection) {
|
||||
NS_ERROR("Bluetooth service not started yet!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
BluetoothUnixSocketConnector* c =
|
||||
new BluetoothUnixSocketConnector(BluetoothSocketType::SCO, -1,
|
||||
aAuth, aEncrypt);
|
||||
|
||||
if (!aConsumer->ConnectSocket(c, NS_ConvertUTF16toUTF8(aAddress).get())) {
|
||||
nsAutoString replyError;
|
||||
replyError.AssignLiteral("SocketConnectionError");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothDBusService::SendFile(const nsAString& aDeviceAddress,
|
||||
BlobParent* aBlobParent,
|
||||
|
@ -54,21 +54,6 @@ public:
|
||||
const BluetoothNamedValue& aValue,
|
||||
BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
GetDevicePath(const nsAString& aAdapterPath,
|
||||
const nsAString& aDeviceAddress,
|
||||
nsAString& aDevicePath) MOZ_OVERRIDE;
|
||||
|
||||
static bool
|
||||
AddReservedServicesInternal(const nsTArray<uint32_t>& aServices,
|
||||
nsTArray<uint32_t>& aServiceHandlesContainer);
|
||||
|
||||
virtual nsresult
|
||||
GetScoSocket(const nsAString& aObjectPath,
|
||||
bool aAuth,
|
||||
bool aEncrypt,
|
||||
mozilla::ipc::UnixSocketConsumer* aConsumer) MOZ_OVERRIDE;
|
||||
|
||||
virtual nsresult
|
||||
GetServiceChannel(const nsAString& aDeviceAddress,
|
||||
const nsAString& aServiceUuid,
|
||||
|
@ -148,25 +148,6 @@ BluetoothServiceChildProcess::SetProperty(BluetoothObjectType aType,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
BluetoothServiceChildProcess::GetDevicePath(const nsAString& aAdapterPath,
|
||||
const nsAString& aDeviceAddress,
|
||||
nsAString& aDevicePath)
|
||||
{
|
||||
// XXXbent Right now this is adapted from BluetoothDBusService's
|
||||
// GetObjectPathFromAddress. This is basically a sync call that cannot
|
||||
// be forwarded to the parent process without blocking. Hopefully this
|
||||
// can be reworked.
|
||||
nsAutoString path(aAdapterPath);
|
||||
path.AppendLiteral("/dev_");
|
||||
path.Append(aDeviceAddress);
|
||||
path.ReplaceChar(':', '_');
|
||||
|
||||
aDevicePath = path;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
nsresult
|
||||
BluetoothServiceChildProcess::CreatePairedDeviceInternal(
|
||||
const nsAString& aAddress,
|
||||
@ -188,16 +169,6 @@ BluetoothServiceChildProcess::RemoveDeviceInternal(
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
BluetoothServiceChildProcess::GetScoSocket(
|
||||
const nsAString& aObjectPath,
|
||||
bool aAuth,
|
||||
bool aEncrypt,
|
||||
mozilla::ipc::UnixSocketConsumer* aConsumer)
|
||||
{
|
||||
MOZ_CRASH("This should never be called!");
|
||||
}
|
||||
|
||||
nsresult
|
||||
BluetoothServiceChildProcess::GetServiceChannel(const nsAString& aDeviceAddress,
|
||||
const nsAString& aServiceUuid,
|
||||
|
@ -66,11 +66,6 @@ public:
|
||||
const BluetoothNamedValue& aValue,
|
||||
BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
GetDevicePath(const nsAString& aAdapterPath,
|
||||
const nsAString& aDeviceAddress,
|
||||
nsAString& aDevicePath) MOZ_OVERRIDE;
|
||||
|
||||
virtual nsresult
|
||||
CreatePairedDeviceInternal(const nsAString& aAddress,
|
||||
int aTimeout,
|
||||
@ -80,12 +75,6 @@ public:
|
||||
RemoveDeviceInternal(const nsAString& aObjectPath,
|
||||
BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
|
||||
|
||||
virtual nsresult
|
||||
GetScoSocket(const nsAString& aObjectPath,
|
||||
bool aAuth,
|
||||
bool aEncrypt,
|
||||
mozilla::ipc::UnixSocketConsumer* aConsumer) MOZ_OVERRIDE;
|
||||
|
||||
virtual nsresult
|
||||
GetServiceChannel(const nsAString& aDeviceAddress,
|
||||
const nsAString& aServiceUuid,
|
||||
|
@ -23,12 +23,31 @@ docShell.QueryInterface(Ci.nsIDocShellTreeItem).name = infos.name;
|
||||
docShell.setFullscreenAllowed(infos.fullscreenAllowed);
|
||||
|
||||
|
||||
if (!('BrowserElementIsPreloaded' in this)) {
|
||||
try {
|
||||
if (Services.prefs.getBoolPref("dom.mozInputMethod.enabled")) {
|
||||
Services.scriptloader.loadSubScript("chrome://global/content/forms.js");
|
||||
function parentDocShell(docshell) {
|
||||
if (!docshell) {
|
||||
return null;
|
||||
}
|
||||
let treeitem = docshell.QueryInterface(Ci.nsIDocShellTreeItem);
|
||||
return treeitem.parent ? treeitem.parent.QueryInterface(Ci.nsIDocShell) : null;
|
||||
}
|
||||
|
||||
function isTopBrowserElement(docShell) {
|
||||
while (docShell) {
|
||||
docShell = parentDocShell(docShell);
|
||||
if (docShell && docShell.isBrowserOrApp) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!('BrowserElementIsPreloaded' in this)) {
|
||||
if (isTopBrowserElement(docShell) &&
|
||||
Services.prefs.getBoolPref("dom.mozInputMethod.enabled")) {
|
||||
try {
|
||||
Services.scriptloader.loadSubScript("chrome://global/content/forms.js");
|
||||
} catch (e) {
|
||||
}
|
||||
} catch (e) {
|
||||
}
|
||||
// Those are produc-specific files that's sometimes unavailable.
|
||||
try {
|
||||
|
@ -400,7 +400,7 @@ ContactManager.prototype = {
|
||||
},
|
||||
|
||||
_convertContacts: function(aContacts) {
|
||||
let contacts = [];
|
||||
let contacts = new this._window.Array();
|
||||
for (let i in aContacts) {
|
||||
contacts.push(this._convertContact(aContacts[i]));
|
||||
}
|
||||
|
@ -9,7 +9,6 @@ this.EXPORTED_SYMBOLS = ['Keyboard'];
|
||||
const Cu = Components.utils;
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const kFormsFrameScript = 'chrome://global/content/forms.js';
|
||||
|
||||
Cu.import('resource://gre/modules/Services.jsm');
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
@ -80,16 +79,6 @@ this.Keyboard = {
|
||||
mm.addMessageListener('Forms:GetContext:Result:OK', this);
|
||||
mm.addMessageListener('Forms:SetComposition:Result:OK', this);
|
||||
mm.addMessageListener('Forms:EndComposition:Result:OK', this);
|
||||
|
||||
// When not running apps OOP, we need to load forms.js here since this
|
||||
// won't happen from dom/ipc/preload.js
|
||||
try {
|
||||
if (Services.prefs.getBoolPref("dom.ipc.tabs.disabled") === true) {
|
||||
mm.loadFrameScript(kFormsFrameScript, true);
|
||||
}
|
||||
} catch (e) {
|
||||
dump('Error loading ' + kFormsFrameScript + ' as frame script: ' + e + '\n');
|
||||
}
|
||||
},
|
||||
|
||||
receiveMessage: function keyboardReceiveMessage(msg) {
|
||||
|
@ -26,7 +26,6 @@ XPCOMUtils.defineLazyGetter(this, "domWindowUtils", function () {
|
||||
const RESIZE_SCROLL_DELAY = 20;
|
||||
|
||||
let HTMLDocument = Ci.nsIDOMHTMLDocument;
|
||||
let HTMLElement = Ci.nsIDOMHTMLElement;
|
||||
let HTMLHtmlElement = Ci.nsIDOMHTMLHtmlElement;
|
||||
let HTMLBodyElement = Ci.nsIDOMHTMLBodyElement;
|
||||
let HTMLIFrameElement = Ci.nsIDOMHTMLIFrameElement;
|
||||
@ -346,12 +345,6 @@ let FormAssistant = {
|
||||
break;
|
||||
}
|
||||
|
||||
// Only handle the event from our descendants
|
||||
if (target instanceof HTMLElement &&
|
||||
content.window != target.ownerDocument.defaultView.top) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (isContentEditable(target)) {
|
||||
this.showKeyboard(this.getTopLevelEditable(target));
|
||||
this.updateSelection();
|
||||
|
@ -1348,17 +1348,6 @@ PreloadSlowThings()
|
||||
|
||||
TabChild::PreloadSlowThings();
|
||||
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
// After preload of slow things, start freezing threads.
|
||||
if (IsNuwaProcess()) {
|
||||
// Perform GC before freezing the Nuwa process to reduce memory usage.
|
||||
ContentChild::GetSingleton()->RecvGarbageCollect();
|
||||
|
||||
MessageLoop::current()->
|
||||
PostTask(FROM_HERE,
|
||||
NewRunnableFunction(OnFinishNuwaPreparation));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
@ -1369,15 +1358,32 @@ ContentChild::RecvAppInfo(const nsCString& version, const nsCString& buildID,
|
||||
mAppInfo.buildID.Assign(buildID);
|
||||
mAppInfo.name.Assign(name);
|
||||
mAppInfo.UAName.Assign(UAName);
|
||||
|
||||
if (!Preferences::GetBool("dom.ipc.processPrelaunch.enabled", false)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If we're part of the mozbrowser machinery, go ahead and start
|
||||
// preloading things. We can only do this for mozbrowser because
|
||||
// PreloadSlowThings() may set the docshell of the first TabChild
|
||||
// inactive, and we can only safely restore it to active from
|
||||
// BrowserElementChild.js.
|
||||
if ((mIsForApp || mIsForBrowser) &&
|
||||
Preferences::GetBool("dom.ipc.processPrelaunch.enabled", false)) {
|
||||
if ((mIsForApp || mIsForBrowser)
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
&& !IsNuwaProcess()
|
||||
#endif
|
||||
) {
|
||||
PreloadSlowThings();
|
||||
}
|
||||
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
if (IsNuwaProcess()) {
|
||||
ContentChild::GetSingleton()->RecvGarbageCollect();
|
||||
MessageLoop::current()->PostTask(
|
||||
FROM_HERE, NewRunnableFunction(OnFinishNuwaPreparation));
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1249,93 +1249,13 @@ ContentParent::ContentParent(mozIApplication* aApp,
|
||||
|
||||
Open(mSubprocess->GetChannel(), mSubprocess->GetOwnedChildProcessHandle());
|
||||
|
||||
// Set the subprocess's priority. We do this early on because we're likely
|
||||
// /lowering/ the process's CPU and memory priority, which it has inherited
|
||||
// from this process.
|
||||
//
|
||||
// This call can cause us to send IPC messages to the child process, so it
|
||||
// must come after the Open() call above.
|
||||
ProcessPriorityManager::SetProcessPriority(this, aInitialPriority);
|
||||
|
||||
// NB: internally, this will send an IPC message to the child
|
||||
// process to get it to create the CompositorChild. This
|
||||
// message goes through the regular IPC queue for this
|
||||
// channel, so delivery will happen-before any other messages
|
||||
// we send. The CompositorChild must be created before any
|
||||
// PBrowsers are created, because they rely on the Compositor
|
||||
// already being around. (Creation is async, so can't happen
|
||||
// on demand.)
|
||||
bool useOffMainThreadCompositing = !!CompositorParent::CompositorLoop();
|
||||
if (useOffMainThreadCompositing) {
|
||||
DebugOnly<bool> opened = PCompositor::Open(this);
|
||||
MOZ_ASSERT(opened);
|
||||
|
||||
if (Preferences::GetBool("layers.async-video.enabled",false)) {
|
||||
opened = PImageBridge::Open(this);
|
||||
MOZ_ASSERT(opened);
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIChromeRegistry> registrySvc = nsChromeRegistry::GetService();
|
||||
nsChromeRegistryChrome* chromeRegistry =
|
||||
static_cast<nsChromeRegistryChrome*>(registrySvc.get());
|
||||
chromeRegistry->SendRegisteredChrome(this);
|
||||
mMessageManager = nsFrameMessageManager::NewProcessMessageManager(this);
|
||||
|
||||
if (gAppData) {
|
||||
nsCString version(gAppData->version);
|
||||
nsCString buildID(gAppData->buildID);
|
||||
nsCString name(gAppData->name);
|
||||
nsCString UAName(gAppData->UAName);
|
||||
|
||||
// Sending all information to content process.
|
||||
unused << SendAppInfo(version, buildID, name, UAName);
|
||||
}
|
||||
|
||||
nsStyleSheetService *sheetService = nsStyleSheetService::GetInstance();
|
||||
if (sheetService) {
|
||||
// This looks like a lot of work, but in a normal browser session we just
|
||||
// send two loads.
|
||||
|
||||
nsCOMArray<nsIStyleSheet>& agentSheets = *sheetService->AgentStyleSheets();
|
||||
for (uint32_t i = 0; i < agentSheets.Length(); i++) {
|
||||
URIParams uri;
|
||||
SerializeURI(agentSheets[i]->GetSheetURI(), uri);
|
||||
unused << SendLoadAndRegisterSheet(uri, nsIStyleSheetService::AGENT_SHEET);
|
||||
}
|
||||
|
||||
nsCOMArray<nsIStyleSheet>& userSheets = *sheetService->UserStyleSheets();
|
||||
for (uint32_t i = 0; i < userSheets.Length(); i++) {
|
||||
URIParams uri;
|
||||
SerializeURI(userSheets[i]->GetSheetURI(), uri);
|
||||
unused << SendLoadAndRegisterSheet(uri, nsIStyleSheetService::USER_SHEET);
|
||||
}
|
||||
|
||||
nsCOMArray<nsIStyleSheet>& authorSheets = *sheetService->AuthorStyleSheets();
|
||||
for (uint32_t i = 0; i < authorSheets.Length(); i++) {
|
||||
URIParams uri;
|
||||
SerializeURI(authorSheets[i]->GetSheetURI(), uri);
|
||||
unused << SendLoadAndRegisterSheet(uri, nsIStyleSheetService::AUTHOR_SHEET);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MOZ_CONTENT_SANDBOX
|
||||
// Bug 921817. We enable the sandbox in RecvSetProcessPrivileges,
|
||||
// which is where a preallocated process drops unnecessary privileges,
|
||||
// but a non-preallocated process will already have changed its
|
||||
// uid/gid/etc immediately after forking. Thus, we send this message,
|
||||
// which is otherwise a no-op, to sandbox it at an appropriate point
|
||||
// during startup.
|
||||
if (aOSPrivileges != base::PRIVILEGES_INHERIT) {
|
||||
if (!SendSetProcessPrivileges(base::PRIVILEGES_INHERIT)) {
|
||||
KillHard();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
InitInternal(aInitialPriority,
|
||||
true, /* Setup off-main thread compositing */
|
||||
true /* Send registered chrome */);
|
||||
}
|
||||
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
static const FileDescriptor*
|
||||
static const mozilla::ipc::FileDescriptor*
|
||||
FindFdProtocolFdMapping(const nsTArray<ProtocolFdMapping>& aFds,
|
||||
ProtocolId aProtoId)
|
||||
{
|
||||
@ -1401,8 +1321,9 @@ ContentParent::ContentParent(ContentParent* aTemplate,
|
||||
priority = PROCESS_PRIORITY_FOREGROUND;
|
||||
}
|
||||
|
||||
ProcessPriorityManager::SetProcessPriority(this, priority);
|
||||
mMessageManager = nsFrameMessageManager::NewProcessMessageManager(this);
|
||||
InitInternal(priority,
|
||||
false, /* Setup Off-main thread compositing */
|
||||
false /* Send registered chrome */);
|
||||
}
|
||||
#endif // MOZ_NUWA_PROCESS
|
||||
|
||||
@ -1432,6 +1353,101 @@ ContentParent::~ContentParent()
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ContentParent::InitInternal(ProcessPriority aInitialPriority,
|
||||
bool aSetupOffMainThreadCompositing,
|
||||
bool aSendRegisteredChrome)
|
||||
{
|
||||
// Set the subprocess's priority. We do this early on because we're likely
|
||||
// /lowering/ the process's CPU and memory priority, which it has inherited
|
||||
// from this process.
|
||||
//
|
||||
// This call can cause us to send IPC messages to the child process, so it
|
||||
// must come after the Open() call above.
|
||||
ProcessPriorityManager::SetProcessPriority(this, aInitialPriority);
|
||||
|
||||
if (aSetupOffMainThreadCompositing) {
|
||||
// NB: internally, this will send an IPC message to the child
|
||||
// process to get it to create the CompositorChild. This
|
||||
// message goes through the regular IPC queue for this
|
||||
// channel, so delivery will happen-before any other messages
|
||||
// we send. The CompositorChild must be created before any
|
||||
// PBrowsers are created, because they rely on the Compositor
|
||||
// already being around. (Creation is async, so can't happen
|
||||
// on demand.)
|
||||
bool useOffMainThreadCompositing = !!CompositorParent::CompositorLoop();
|
||||
if (useOffMainThreadCompositing) {
|
||||
DebugOnly<bool> opened = PCompositor::Open(this);
|
||||
MOZ_ASSERT(opened);
|
||||
|
||||
if (Preferences::GetBool("layers.async-video.enabled",false)) {
|
||||
opened = PImageBridge::Open(this);
|
||||
MOZ_ASSERT(opened);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (aSendRegisteredChrome) {
|
||||
nsCOMPtr<nsIChromeRegistry> registrySvc = nsChromeRegistry::GetService();
|
||||
nsChromeRegistryChrome* chromeRegistry =
|
||||
static_cast<nsChromeRegistryChrome*>(registrySvc.get());
|
||||
chromeRegistry->SendRegisteredChrome(this);
|
||||
}
|
||||
|
||||
mMessageManager = nsFrameMessageManager::NewProcessMessageManager(this);
|
||||
|
||||
if (gAppData) {
|
||||
nsCString version(gAppData->version);
|
||||
nsCString buildID(gAppData->buildID);
|
||||
nsCString name(gAppData->name);
|
||||
nsCString UAName(gAppData->UAName);
|
||||
|
||||
// Sending all information to content process.
|
||||
unused << SendAppInfo(version, buildID, name, UAName);
|
||||
}
|
||||
|
||||
nsStyleSheetService *sheetService = nsStyleSheetService::GetInstance();
|
||||
if (sheetService) {
|
||||
// This looks like a lot of work, but in a normal browser session we just
|
||||
// send two loads.
|
||||
|
||||
nsCOMArray<nsIStyleSheet>& agentSheets = *sheetService->AgentStyleSheets();
|
||||
for (uint32_t i = 0; i < agentSheets.Length(); i++) {
|
||||
URIParams uri;
|
||||
SerializeURI(agentSheets[i]->GetSheetURI(), uri);
|
||||
unused << SendLoadAndRegisterSheet(uri, nsIStyleSheetService::AGENT_SHEET);
|
||||
}
|
||||
|
||||
nsCOMArray<nsIStyleSheet>& userSheets = *sheetService->UserStyleSheets();
|
||||
for (uint32_t i = 0; i < userSheets.Length(); i++) {
|
||||
URIParams uri;
|
||||
SerializeURI(userSheets[i]->GetSheetURI(), uri);
|
||||
unused << SendLoadAndRegisterSheet(uri, nsIStyleSheetService::USER_SHEET);
|
||||
}
|
||||
|
||||
nsCOMArray<nsIStyleSheet>& authorSheets = *sheetService->AuthorStyleSheets();
|
||||
for (uint32_t i = 0; i < authorSheets.Length(); i++) {
|
||||
URIParams uri;
|
||||
SerializeURI(authorSheets[i]->GetSheetURI(), uri);
|
||||
unused << SendLoadAndRegisterSheet(uri, nsIStyleSheetService::AUTHOR_SHEET);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MOZ_CONTENT_SANDBOX
|
||||
// Bug 921817. We enable the sandbox in RecvSetProcessPrivileges,
|
||||
// which is where a preallocated process drops unnecessary privileges,
|
||||
// but a non-preallocated process will already have changed its
|
||||
// uid/gid/etc immediately after forking. Thus, we send this message,
|
||||
// which is otherwise a no-op, to sandbox it at an appropriate point
|
||||
// during startup.
|
||||
if (mOSPrivileges != base::PRIVILEGES_INHERIT) {
|
||||
if (!SendSetProcessPrivileges(base::PRIVILEGES_INHERIT)) {
|
||||
KillHard();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::IsAlive()
|
||||
{
|
||||
|
@ -265,6 +265,11 @@ private:
|
||||
// The common initialization for the constructors.
|
||||
void InitializeMembers();
|
||||
|
||||
// The common initialization logic shared by all constuctors.
|
||||
void InitInternal(ProcessPriority aPriority,
|
||||
bool aSetupOffMainThreadCompositing,
|
||||
bool aSendRegisteredChrome);
|
||||
|
||||
virtual ~ContentParent();
|
||||
|
||||
void Init();
|
||||
|
@ -88,6 +88,7 @@ private:
|
||||
void ObserveProcessShutdown(nsISupports* aSubject);
|
||||
|
||||
bool mEnabled;
|
||||
bool mShutdown;
|
||||
nsRefPtr<ContentParent> mPreallocatedAppProcess;
|
||||
};
|
||||
|
||||
@ -114,6 +115,7 @@ PreallocatedProcessManagerImpl::PreallocatedProcessManagerImpl()
|
||||
, mPreallocateAppProcessTask(nullptr)
|
||||
, mIsNuwaReady(false)
|
||||
#endif
|
||||
, mShutdown(false)
|
||||
{}
|
||||
|
||||
void
|
||||
@ -124,6 +126,8 @@ PreallocatedProcessManagerImpl::Init()
|
||||
if (os) {
|
||||
os->AddObserver(this, "ipc:content-shutdown",
|
||||
/* weakRef = */ false);
|
||||
os->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID,
|
||||
/* weakRef = */ false);
|
||||
}
|
||||
RereadPrefs();
|
||||
}
|
||||
@ -138,6 +142,8 @@ PreallocatedProcessManagerImpl::Observe(nsISupports* aSubject,
|
||||
} else if (!strcmp("nsPref:changed", aTopic)) {
|
||||
// The only other observer we registered was for our prefs.
|
||||
RereadPrefs();
|
||||
} else if (!strcmp(NS_XPCOM_SHUTDOWN_OBSERVER_ID, aTopic)) {
|
||||
mShutdown = true;
|
||||
} else {
|
||||
MOZ_ASSERT(false);
|
||||
}
|
||||
@ -240,7 +246,7 @@ PreallocatedProcessManagerImpl::DelayedNuwaFork()
|
||||
mPreallocateAppProcessTask = nullptr;
|
||||
|
||||
if (!mIsNuwaReady) {
|
||||
if (!mPreallocatedAppProcess) {
|
||||
if (!mPreallocatedAppProcess && !mShutdown) {
|
||||
mPreallocatedAppProcess = ContentParent::RunNuwaProcess();
|
||||
}
|
||||
// else mPreallocatedAppProcess is starting. It will NuwaFork() when ready.
|
||||
@ -281,6 +287,15 @@ PreallocatedProcessManagerImpl::PublishSpareProcess(ContentParent* aContent)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (Preferences::GetBool("dom.ipc.processPriorityManager.testMode")) {
|
||||
AutoJSContext cx;
|
||||
nsCOMPtr<nsIMessageBroadcaster> ppmm =
|
||||
do_GetService("@mozilla.org/parentprocessmessagemanager;1");
|
||||
nsresult rv = ppmm->BroadcastAsyncMessage(
|
||||
NS_LITERAL_STRING("TEST-ONLY:nuwa-add-new-process"),
|
||||
JSVAL_NULL, JSVAL_NULL, cx, 1);
|
||||
}
|
||||
|
||||
if (!mNuwaForkWaitTasks.IsEmpty()) {
|
||||
mNuwaForkWaitTasks.ElementAt(0)->Cancel();
|
||||
mNuwaForkWaitTasks.RemoveElementAt(0);
|
||||
@ -312,6 +327,14 @@ PreallocatedProcessManagerImpl::OnNuwaReady()
|
||||
ProcessPriorityManager::SetProcessPriority(mPreallocatedAppProcess,
|
||||
hal::PROCESS_PRIORITY_FOREGROUND);
|
||||
mIsNuwaReady = true;
|
||||
if (Preferences::GetBool("dom.ipc.processPriorityManager.testMode")) {
|
||||
AutoJSContext cx;
|
||||
nsCOMPtr<nsIMessageBroadcaster> ppmm =
|
||||
do_GetService("@mozilla.org/parentprocessmessagemanager;1");
|
||||
nsresult rv = ppmm->BroadcastAsyncMessage(
|
||||
NS_LITERAL_STRING("TEST-ONLY:nuwa-ready"),
|
||||
JSVAL_NULL, JSVAL_NULL, cx, 1);
|
||||
}
|
||||
NuwaFork();
|
||||
}
|
||||
|
||||
|
2
dom/ipc/tests/mochitest.ini
Normal file
2
dom/ipc/tests/mochitest.ini
Normal file
@ -0,0 +1,2 @@
|
||||
[test_NuwaProcessCreation.html]
|
||||
run-if = toolkit == 'gonk'
|
@ -5,4 +5,5 @@
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
MOCHITEST_CHROME_MANIFESTS += ['chrome.ini']
|
||||
MOCHITEST_MANIFESTS += ['mochitest.ini']
|
||||
|
||||
|
99
dom/ipc/tests/test_NuwaProcessCreation.html
Normal file
99
dom/ipc/tests/test_NuwaProcessCreation.html
Normal file
@ -0,0 +1,99 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
Test if Nuwa process created successfully.
|
||||
-->
|
||||
<head>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<script type="application/javascript;version=1.7">
|
||||
"use strict";
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function TestLoader() {}
|
||||
|
||||
TestLoader.prototype = {
|
||||
_waitingTask: 0,
|
||||
onTestReady: null,
|
||||
unlockTestReady: function() {
|
||||
this._waitingTask--;
|
||||
this._maybeLoadTest();
|
||||
},
|
||||
lockTestReady: function() {
|
||||
this._waitingTask++;
|
||||
},
|
||||
_maybeLoadTest: function() {
|
||||
if (this._waitingTask == 0) {
|
||||
this.onTestReady();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var testLoader = new TestLoader();
|
||||
testLoader.lockTestReady();
|
||||
window.addEventListener('load', function() {
|
||||
testLoader.unlockTestReady();
|
||||
});
|
||||
|
||||
function setPref(pref, value) {
|
||||
testLoader.lockTestReady();
|
||||
if (value !== undefined && value !== null) {
|
||||
SpecialPowers.pushPrefEnv({'set': [[pref, value]]}, function() { testLoader.unlockTestReady(); });
|
||||
} else {
|
||||
SpecialPowers.pushPrefEnv({'clear': [[pref]]}, function() { testLoader.unlockTestReady(); });
|
||||
}
|
||||
}
|
||||
|
||||
setPref('dom.ipc.processPriorityManager.testMode', true);
|
||||
setPref('dom.ipc.processPriorityManager.enabled', true);
|
||||
setPref('dom.ipc.processPriorityManager.backgroundLRUPoolLevels', 2);
|
||||
|
||||
function runTest()
|
||||
{
|
||||
// Shutdown preallocated process.
|
||||
SpecialPowers.setBoolPref('dom.ipc.processPrelaunch.enabled', false);
|
||||
let cpmm = SpecialPowers.Cc["@mozilla.org/childprocessmessagemanager;1"]
|
||||
.getService(SpecialPowers.Ci.nsISyncMessageSender);
|
||||
let seenNuwaReady = false;
|
||||
let msgHandler = {
|
||||
receiveMessage: function receiveMessage(msg) {
|
||||
msg = SpecialPowers.wrap(msg);
|
||||
if (msg.name == 'TEST-ONLY:nuwa-ready') {
|
||||
ok(true, "Got nuwa-ready");
|
||||
is(seenNuwaReady, false, "Already received nuwa ready");
|
||||
seenNuwaReady = true;
|
||||
} else if (msg.name == 'TEST-ONLY:nuwa-add-new-process') {
|
||||
ok(true, "Got nuwa-add-new-process");
|
||||
is(seenNuwaReady, true, "Receive nuwa-add-new-process before nuwa-ready");
|
||||
testEnd();
|
||||
}
|
||||
}
|
||||
};
|
||||
let timeout = setTimeout(function() {
|
||||
ok(false, "Nuwa process is not launched");
|
||||
testEnd();
|
||||
}, 60000);
|
||||
|
||||
function testEnd() {
|
||||
cpmm.removeMessageListener("TEST-ONLY:nuwa-ready", msgHandler);
|
||||
cpmm.removeMessageListener("TEST-ONLY:nuwa-add-new-process", msgHandler);
|
||||
clearTimeout(timeout);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
cpmm.addMessageListener("TEST-ONLY:nuwa-ready", msgHandler);
|
||||
cpmm.addMessageListener("TEST-ONLY:nuwa-add-new-process", msgHandler);
|
||||
|
||||
|
||||
// Setting this pref to true should cause us to prelaunch a process.
|
||||
SpecialPowers.setBoolPref('dom.ipc.processPrelaunch.enabled', true);
|
||||
}
|
||||
|
||||
testLoader.onTestReady = runTest;
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -7,3 +7,9 @@ ifdef MOZ_WEBRTC_LEAKING_TESTS
|
||||
MOCHITEST_FILES += \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
ifdef MOZ_B2G_CAMERA
|
||||
MOCHITEST_FILES += \
|
||||
test_getUserMedia_permission.html \
|
||||
$(NULL)
|
||||
endif
|
||||
|
75
dom/media/tests/mochitest/test_getUserMedia_permission.html
Normal file
75
dom/media/tests/mochitest/test_getUserMedia_permission.html
Normal file
@ -0,0 +1,75 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=853356
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>mozGetUserMedia Permission Test</title>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="head.js"></script>
|
||||
<script type="application/javascript" src="mediaStreamPlayback.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=853356">Display camera/microphone permission acquisition prompt</a>
|
||||
<script type="application/javascript">
|
||||
|
||||
var gCount = 0;
|
||||
var gTests = [
|
||||
{
|
||||
constraints: {video: true, audio: false}
|
||||
}
|
||||
,
|
||||
{
|
||||
constraints: {video: false, audio: true}
|
||||
}
|
||||
,
|
||||
{
|
||||
constraints: {video: true, audio: true},
|
||||
}
|
||||
];
|
||||
|
||||
function gUM(data) {
|
||||
var gum_success = function (stream) {
|
||||
SimpleTest.info("TEST-INFO | Got succss callback for " + JSON.stringify(data.constraints));
|
||||
|
||||
var hasAudioTrack = stream.getAudioTracks().length > 0;
|
||||
var hasVideoTrack = stream.getVideoTracks().length > 0;
|
||||
|
||||
is(data.constraints.audio, hasAudioTrack, "Request audio track:" +
|
||||
data.constraints.audio + " contain audio track:" + hasAudioTrack);
|
||||
is(data.constraints.video, hasVideoTrack, "Request video track:" +
|
||||
data.constraints.video + " contain audio track:" + hasVideoTrack);
|
||||
gCount++;
|
||||
if (gCount < gTests.length) {
|
||||
gUM(gTests[gCount]);
|
||||
} else {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
var gum_fail = function () {
|
||||
ok(false, "permission not granted for " + JSON.stringify(data.constraints));
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.info("TEST-INFO | Call getUserMedia for " + JSON.stringify(data.constraints));
|
||||
navigator.mozGetUserMedia(data.constraints, gum_success, gum_fail);
|
||||
}
|
||||
|
||||
SpecialPowers.pushPrefEnv({"set": [["media.navigator.permission.disabled", false]]},
|
||||
function () {
|
||||
SpecialPowers.addPermission('video-capture',
|
||||
Ci.nsIPermissionManager.ALLOW_ACTION, document);
|
||||
SpecialPowers.addPermission('audio-capture',
|
||||
Ci.nsIPermissionManager.ALLOW_ACTION, document);
|
||||
|
||||
gUM(gTests[gCount]);
|
||||
});
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -924,6 +924,7 @@ MobileMessageDatabaseService.prototype = {
|
||||
// Participant store cursor iteration done.
|
||||
if (!invalidParticipantIds.length) {
|
||||
next();
|
||||
return;
|
||||
}
|
||||
|
||||
// Find affected thread.
|
||||
@ -1619,10 +1620,14 @@ MobileMessageDatabaseService.prototype = {
|
||||
function replaceShortMessageOnSave(aTransaction, aMessageStore,
|
||||
aParticipantStore, aThreadStore,
|
||||
aMessageRecord, aAddresses) {
|
||||
let isReplaceTypePid = (aMessageRecord.pid) &&
|
||||
((aMessageRecord.pid >= RIL.PDU_PID_REPLACE_SHORT_MESSAGE_TYPE_1 &&
|
||||
aMessageRecord.pid <= RIL.PDU_PID_REPLACE_SHORT_MESSAGE_TYPE_7) ||
|
||||
aMessageRecord.pid == RIL.PDU_PID_RETURN_CALL_MESSAGE);
|
||||
|
||||
if (aMessageRecord.type != "sms" ||
|
||||
aMessageRecord.delivery != DELIVERY_RECEIVED ||
|
||||
!(aMessageRecord.pid >= RIL.PDU_PID_REPLACE_SHORT_MESSAGE_TYPE_1 &&
|
||||
aMessageRecord.pid <= RIL.PDU_PID_REPLACE_SHORT_MESSAGE_TYPE_7)) {
|
||||
!isReplaceTypePid) {
|
||||
this.realSaveRecord(aTransaction, aMessageStore, aParticipantStore,
|
||||
aThreadStore, aMessageRecord, aAddresses);
|
||||
return;
|
||||
|
@ -14,7 +14,7 @@ const SENDER_0 = "+1234567890";
|
||||
const SENDER_1 = "+1234567891";
|
||||
|
||||
const PDU_PID_NORMAL = "00";
|
||||
const PDU_PIDS = ["00", "41", "42", "43", "44", "45", "46", "47"];
|
||||
const PDU_PIDS = ["00", "41", "42", "43", "44", "45", "46", "47", "5F"];
|
||||
|
||||
const PDU_DCS_NORMAL = "00";
|
||||
|
||||
|
@ -24,7 +24,7 @@
|
||||
|
||||
using namespace mozilla::dom::network;
|
||||
|
||||
class MobileConnection::Listener : public nsIMobileConnectionListener
|
||||
class MobileConnection::Listener MOZ_FINAL : public nsIMobileConnectionListener
|
||||
{
|
||||
MobileConnection* mMobileConnection;
|
||||
|
||||
@ -692,4 +692,4 @@ MobileConnection::NotifyRadioStateChanged()
|
||||
}
|
||||
|
||||
return DispatchTrustedEvent(NS_LITERAL_STRING("radiostatechange"));
|
||||
}
|
||||
}
|
||||
|
@ -10,9 +10,19 @@
|
||||
|
||||
using namespace mozilla::dom::network;
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_2(MobileConnectionArray,
|
||||
mWindow,
|
||||
mMobileConnections)
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(MobileConnectionArray)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(MobileConnectionArray)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow)
|
||||
// Notify our mobile connections that we're going away.
|
||||
tmp->DropConnections();
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(MobileConnectionArray)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMobileConnections)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(MobileConnectionArray)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(MobileConnectionArray)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(MobileConnectionArray)
|
||||
@ -38,6 +48,12 @@ MobileConnectionArray::MobileConnectionArray(nsPIDOMWindow* aWindow)
|
||||
}
|
||||
|
||||
MobileConnectionArray::~MobileConnectionArray()
|
||||
{
|
||||
DropConnections();
|
||||
}
|
||||
|
||||
void
|
||||
MobileConnectionArray::DropConnections()
|
||||
{
|
||||
for (uint32_t i = 0; i < mMobileConnections.Length(); i++) {
|
||||
mMobileConnections[i]->Shutdown();
|
||||
@ -78,4 +94,4 @@ MobileConnectionArray::IndexedGetter(uint32_t aIndex, bool& aFound) const
|
||||
aFound = aIndex < mMobileConnections.Length();
|
||||
|
||||
return aFound ? mMobileConnections[aIndex] : nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -45,6 +45,8 @@ public:
|
||||
private:
|
||||
~MobileConnectionArray();
|
||||
|
||||
void DropConnections();
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> mWindow;
|
||||
nsTArray<nsRefPtr<MobileConnection>> mMobileConnections;
|
||||
};
|
||||
@ -53,4 +55,4 @@ private:
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_network_MobileConnectionArray_h__
|
||||
#endif // mozilla_dom_network_MobileConnectionArray_h__
|
||||
|
@ -2056,7 +2056,12 @@ RadioInterface.prototype = {
|
||||
mwi.returnMessage = message.fullBody;
|
||||
gMessageManager.sendVoicemailMessage("RIL:VoicemailNotification",
|
||||
this.clientId, mwi);
|
||||
return true;
|
||||
|
||||
// Dicarded MWI comes without text body.
|
||||
// Hence, we discard it here after notifying the MWI status.
|
||||
if (mwi.discard) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
let notifyReceived = function notifyReceived(rv, domMessage) {
|
||||
|
@ -6965,17 +6965,6 @@ let GsmPDUHelper = {
|
||||
case PDU_PID_ANSI_136_R_DATA:
|
||||
case PDU_PID_USIM_DATA_DOWNLOAD:
|
||||
return;
|
||||
case PDU_PID_RETURN_CALL_MESSAGE:
|
||||
// Level 1 of message waiting indication:
|
||||
// Only a return call message is provided
|
||||
let mwi = msg.mwi = {};
|
||||
|
||||
// TODO: When should we de-activate the level 1 indicator?
|
||||
mwi.active = true;
|
||||
mwi.discard = false;
|
||||
mwi.msgCount = GECKO_VOICEMAIL_MESSAGE_COUNT_UNKNOWN;
|
||||
if (DEBUG) debug("TP-PID got return call message: " + msg.sender);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -56,44 +56,15 @@ function isVoicemailStatus(status) {
|
||||
const MWI_PDU_PREFIX = "0000";
|
||||
const MWI_PDU_UDH_PREFIX = "0040";
|
||||
const MWI_PID_DEFAULT = "00";
|
||||
const MWI_PID_RETURN_CALL_MSG = "5F";
|
||||
const MWI_DCS_DATA_MSG = "F0";
|
||||
const MWI_DCS_DISCARD_INACTIVE = "C0";
|
||||
const MWI_DCS_DISCARD_ACTIVE = "C8";
|
||||
const MWI_TIMESTAMP = "00000000000000";
|
||||
|
||||
const MWI_LEVEL1_SENDER = "+15125551234";
|
||||
const MWI_LEVEL1_PDU_ADDRESS = PDUBuilder.buildAddress(MWI_LEVEL1_SENDER);
|
||||
const MWI_DEFAULT_BODY = "1 new voicemail";
|
||||
const MWI_UD_DEFAULT = PDUBuilder.buildUserData({
|
||||
body: MWI_DEFAULT_BODY
|
||||
});
|
||||
|
||||
// Level 1 Message Waiting is just a return call message
|
||||
const MWI_LEVEL1_PDU =
|
||||
MWI_PDU_PREFIX +
|
||||
MWI_LEVEL1_PDU_ADDRESS +
|
||||
MWI_PID_RETURN_CALL_MSG +
|
||||
MWI_DCS_DATA_MSG +
|
||||
MWI_TIMESTAMP +
|
||||
MWI_UD_DEFAULT;
|
||||
|
||||
function testLevel1Indicator() {
|
||||
|
||||
function onLevel1Indicator(event) {
|
||||
let status = event.status;
|
||||
// TODO: bug 905228 - MozVoicemailStatus is not defined.
|
||||
//ok(status instanceof MozVoicemailStatus);
|
||||
is(status.hasMessages, true);
|
||||
is(status.messageCount, -1);
|
||||
is(status.returnNumber, MWI_LEVEL1_SENDER);
|
||||
is(status.returnMessage, MWI_DEFAULT_BODY);
|
||||
isVoicemailStatus(status);
|
||||
}
|
||||
|
||||
sendIndicatorPDU(MWI_LEVEL1_PDU, onLevel1Indicator, testLevel2DiscardActive);
|
||||
}
|
||||
|
||||
const MWI_LEVEL2_SENDER = "+15125551235";
|
||||
const MWI_LEVEL2_PDU_ADDRESS = PDUBuilder.buildAddress(MWI_LEVEL2_SENDER);
|
||||
const MWI_LEVEL2_DISCARD_ACTIVE_PDU =
|
||||
@ -234,4 +205,4 @@ function cleanUp() {
|
||||
finish();
|
||||
}
|
||||
|
||||
testLevel1Indicator();
|
||||
testLevel2DiscardActive();
|
||||
|
@ -19,7 +19,6 @@
|
||||
#include "mozilla/Monitor.h"
|
||||
#include "mozilla/FileUtils.h"
|
||||
#include "nsString.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
|
||||
@ -43,13 +42,15 @@ class UnixSocketImpl : public MessageLoopForIO::Watcher
|
||||
{
|
||||
public:
|
||||
UnixSocketImpl(UnixSocketConsumer* aConsumer, UnixSocketConnector* aConnector,
|
||||
const nsACString& aAddress)
|
||||
const nsACString& aAddress,
|
||||
SocketConnectionStatus aConnectionStatus)
|
||||
: mConsumer(aConsumer)
|
||||
, mIOLoop(nullptr)
|
||||
, mConnector(aConnector)
|
||||
, mShuttingDownOnIOThread(false)
|
||||
, mAddress(aAddress)
|
||||
, mDelayedConnectTask(nullptr)
|
||||
, mConnectionStatus(aConnectionStatus)
|
||||
{
|
||||
}
|
||||
|
||||
@ -245,6 +246,12 @@ private:
|
||||
* Task member for delayed connect task. Should only be access on main thread.
|
||||
*/
|
||||
CancelableTask* mDelayedConnectTask;
|
||||
|
||||
/**
|
||||
* Socket connection status. Duplicate from UnixSocketConsumer. Should only
|
||||
* be accessed on I/O thread.
|
||||
*/
|
||||
SocketConnectionStatus mConnectionStatus;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
@ -525,6 +532,7 @@ UnixSocketImpl::Accept()
|
||||
nsRefPtr<OnSocketEventTask> t =
|
||||
new OnSocketEventTask(this, OnSocketEventTask::CONNECT_ERROR);
|
||||
NS_DispatchToMainThread(t);
|
||||
mConnectionStatus = SOCKET_DISCONNECTED;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -562,6 +570,7 @@ UnixSocketImpl::Connect()
|
||||
nsRefPtr<OnSocketEventTask> t =
|
||||
new OnSocketEventTask(this, OnSocketEventTask::CONNECT_ERROR);
|
||||
NS_DispatchToMainThread(t);
|
||||
mConnectionStatus = SOCKET_DISCONNECTED;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -578,6 +587,7 @@ UnixSocketImpl::Connect()
|
||||
nsRefPtr<OnSocketEventTask> t =
|
||||
new OnSocketEventTask(this, OnSocketEventTask::CONNECT_ERROR);
|
||||
NS_DispatchToMainThread(t);
|
||||
mConnectionStatus = SOCKET_DISCONNECTED;
|
||||
return;
|
||||
}
|
||||
if (-1 == fcntl(mFd.get(), F_SETFL, current_opts & ~O_NONBLOCK)) {
|
||||
@ -586,6 +596,7 @@ UnixSocketImpl::Connect()
|
||||
nsRefPtr<OnSocketEventTask> t =
|
||||
new OnSocketEventTask(this, OnSocketEventTask::CONNECT_ERROR);
|
||||
NS_DispatchToMainThread(t);
|
||||
mConnectionStatus = SOCKET_DISCONNECTED;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -609,6 +620,7 @@ UnixSocketImpl::Connect()
|
||||
nsRefPtr<OnSocketEventTask> t =
|
||||
new OnSocketEventTask(this, OnSocketEventTask::CONNECT_ERROR);
|
||||
NS_DispatchToMainThread(t);
|
||||
mConnectionStatus = SOCKET_DISCONNECTED;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -624,6 +636,7 @@ UnixSocketImpl::Connect()
|
||||
nsRefPtr<OnSocketEventTask> t =
|
||||
new OnSocketEventTask(this, OnSocketEventTask::CONNECT_SUCCESS);
|
||||
NS_DispatchToMainThread(t);
|
||||
mConnectionStatus = SOCKET_CONNECTED;
|
||||
|
||||
SetUpIO();
|
||||
}
|
||||
@ -720,8 +733,7 @@ UnixSocketImpl::OnFileCanReadWithoutBlocking(int aFd)
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
MOZ_ASSERT(!mShuttingDownOnIOThread);
|
||||
|
||||
SocketConnectionStatus status = mConsumer->GetConnectionStatus();
|
||||
if (status == SOCKET_CONNECTED) {
|
||||
if (mConnectionStatus == SOCKET_CONNECTED) {
|
||||
// Read all of the incoming data.
|
||||
while (true) {
|
||||
nsAutoPtr<UnixSocketRawData> incoming(new UnixSocketRawData(MAX_READ_SIZE));
|
||||
@ -764,9 +776,7 @@ UnixSocketImpl::OnFileCanReadWithoutBlocking(int aFd)
|
||||
}
|
||||
|
||||
MOZ_CRASH("We returned early");
|
||||
}
|
||||
|
||||
if (status == SOCKET_LISTENING) {
|
||||
} else if (mConnectionStatus == SOCKET_LISTENING) {
|
||||
int client_fd = accept(mFd.get(), (struct sockaddr*)&mAddr, &mAddrSize);
|
||||
|
||||
if (client_fd < 0) {
|
||||
@ -791,6 +801,7 @@ UnixSocketImpl::OnFileCanReadWithoutBlocking(int aFd)
|
||||
nsRefPtr<OnSocketEventTask> t =
|
||||
new OnSocketEventTask(this, OnSocketEventTask::CONNECT_SUCCESS);
|
||||
NS_DispatchToMainThread(t);
|
||||
mConnectionStatus = SOCKET_CONNECTED;
|
||||
|
||||
SetUpIO();
|
||||
}
|
||||
@ -803,8 +814,7 @@ UnixSocketImpl::OnFileCanWriteWithoutBlocking(int aFd)
|
||||
MOZ_ASSERT(!mShuttingDownOnIOThread);
|
||||
|
||||
MOZ_ASSERT(aFd >= 0);
|
||||
SocketConnectionStatus status = mConsumer->GetConnectionStatus();
|
||||
if (status == SOCKET_CONNECTED) {
|
||||
if (mConnectionStatus == SOCKET_CONNECTED) {
|
||||
// Try to write the bytes of mCurrentRilRawData. If all were written, continue.
|
||||
//
|
||||
// Otherwise, save the byte position of the next byte to write
|
||||
@ -845,7 +855,7 @@ UnixSocketImpl::OnFileCanWriteWithoutBlocking(int aFd)
|
||||
mOutgoingQ.RemoveElementAt(0);
|
||||
delete data;
|
||||
}
|
||||
} else if (status == SOCKET_CONNECTING) {
|
||||
} else if (mConnectionStatus == SOCKET_CONNECTING) {
|
||||
int error, ret;
|
||||
socklen_t len = sizeof(error);
|
||||
ret = getsockopt(mFd.get(), SOL_SOCKET, SO_ERROR, &error, &len);
|
||||
@ -856,6 +866,7 @@ UnixSocketImpl::OnFileCanWriteWithoutBlocking(int aFd)
|
||||
nsRefPtr<OnSocketEventTask> t =
|
||||
new OnSocketEventTask(this, OnSocketEventTask::CONNECT_ERROR);
|
||||
NS_DispatchToMainThread(t);
|
||||
mConnectionStatus = SOCKET_DISCONNECTED;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -864,6 +875,7 @@ UnixSocketImpl::OnFileCanWriteWithoutBlocking(int aFd)
|
||||
nsRefPtr<OnSocketEventTask> t =
|
||||
new OnSocketEventTask(this, OnSocketEventTask::CONNECT_ERROR);
|
||||
NS_DispatchToMainThread(t);
|
||||
mConnectionStatus = SOCKET_DISCONNECTED;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -873,12 +885,14 @@ UnixSocketImpl::OnFileCanWriteWithoutBlocking(int aFd)
|
||||
nsRefPtr<OnSocketEventTask> t =
|
||||
new OnSocketEventTask(this, OnSocketEventTask::CONNECT_ERROR);
|
||||
NS_DispatchToMainThread(t);
|
||||
mConnectionStatus = SOCKET_DISCONNECTED;
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<OnSocketEventTask> t =
|
||||
new OnSocketEventTask(this, OnSocketEventTask::CONNECT_SUCCESS);
|
||||
NS_DispatchToMainThread(t);
|
||||
mConnectionStatus = SOCKET_CONNECTED;
|
||||
|
||||
SetUpIO();
|
||||
}
|
||||
@ -935,7 +949,7 @@ UnixSocketConsumer::ConnectSocket(UnixSocketConnector* aConnector,
|
||||
}
|
||||
|
||||
nsCString addr(aAddress);
|
||||
mImpl = new UnixSocketImpl(this, connector.forget(), addr);
|
||||
mImpl = new UnixSocketImpl(this, connector.forget(), addr, SOCKET_CONNECTING);
|
||||
MessageLoop* ioLoop = XRE_GetIOMessageLoop();
|
||||
mConnectionStatus = SOCKET_CONNECTING;
|
||||
if (aDelayMs > 0) {
|
||||
@ -961,7 +975,8 @@ UnixSocketConsumer::ListenSocket(UnixSocketConnector* aConnector)
|
||||
return false;
|
||||
}
|
||||
|
||||
mImpl = new UnixSocketImpl(this, connector.forget(), EmptyCString());
|
||||
mImpl = new UnixSocketImpl(this, connector.forget(), EmptyCString(),
|
||||
SOCKET_LISTENING);
|
||||
mConnectionStatus = SOCKET_LISTENING;
|
||||
XRE_GetIOMessageLoop()->PostTask(FROM_HERE,
|
||||
new SocketAcceptTask(mImpl));
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "nsString.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
@ -165,6 +166,7 @@ public:
|
||||
|
||||
SocketConnectionStatus GetConnectionStatus() const
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
return mConnectionStatus;
|
||||
}
|
||||
|
||||
|
@ -10,4 +10,4 @@
|
||||
# hardcoded milestones in the tree from these two files.
|
||||
#--------------------------------------------------------
|
||||
|
||||
28.0a1
|
||||
29.0a1
|
||||
|
@ -661,8 +661,7 @@ def run_tests_remote(tests, prefix, options):
|
||||
Test.CacheDir = posixpath.join(options.remote_test_root, '.js-cache')
|
||||
dm.mkDir(Test.CacheDir)
|
||||
|
||||
for path in os.listdir(JS_TESTS_DIR):
|
||||
dm.pushDir(os.path.join(JS_TESTS_DIR, path), posixpath.join(jit_tests_dir, 'tests', path))
|
||||
dm.pushDir(JS_TESTS_DIR, posixpath.join(jit_tests_dir, 'tests'), timeout=600)
|
||||
|
||||
dm.pushDir(os.path.dirname(TEST_DIR), options.remote_test_root, timeout=600)
|
||||
prefix[0] = os.path.join(options.remote_test_root, 'js')
|
||||
|
@ -758,9 +758,11 @@ void MediaPipelineTransmit::PipelineListener::ProcessAudioChunk(
|
||||
if (chunk.mBuffer) {
|
||||
switch (chunk.mBufferFormat) {
|
||||
case AUDIO_FORMAT_FLOAT32:
|
||||
MOZ_MTLOG(ML_ERROR, "Can't process audio except in 16-bit PCM yet");
|
||||
MOZ_ASSERT(PR_FALSE);
|
||||
return;
|
||||
{
|
||||
const float* buf = static_cast<const float *>(chunk.mChannelData[0]);
|
||||
ConvertAudioSamplesWithScale(buf, static_cast<int16_t*>(samples),
|
||||
chunk.mDuration, chunk.mVolume);
|
||||
}
|
||||
break;
|
||||
case AUDIO_FORMAT_S16:
|
||||
{
|
||||
|
@ -12,6 +12,7 @@ package org.webrtc.videoengine;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import org.webrtc.videoengine.CaptureCapabilityAndroid;
|
||||
@ -285,6 +286,12 @@ public class VideoCaptureAndroid implements PreviewCallback, Callback {
|
||||
|
||||
|
||||
Camera.Parameters parameters = camera.getParameters();
|
||||
|
||||
List<String> focusModeList = parameters.getSupportedFocusModes();
|
||||
if (focusModeList.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) {
|
||||
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
|
||||
}
|
||||
|
||||
parameters.setPreviewSize(currentCapability.width,
|
||||
currentCapability.height);
|
||||
parameters.setPreviewFormat(PIXEL_FORMAT);
|
||||
|
@ -91,10 +91,14 @@ classes.dex: proguard-jars
|
||||
@echo 'DX classes.dex'
|
||||
$(DX) --dex --output=classes.dex jars-proguarded $(ANDROID_COMPAT_LIB)
|
||||
|
||||
ifdef MOZ_DEBUG
|
||||
PROGUARD_PASSES=1
|
||||
ifdef MOZ_DISABLE_PROGUARD
|
||||
PROGUARD_PASSES=0
|
||||
else
|
||||
PROGUARD_PASSES=6
|
||||
ifdef MOZ_DEBUG
|
||||
PROGUARD_PASSES=1
|
||||
else
|
||||
PROGUARD_PASSES=6
|
||||
endif
|
||||
endif
|
||||
|
||||
proguard-jars: $(ALL_JARS)
|
||||
|
@ -19,6 +19,7 @@ import org.mozilla.gecko.db.BrowserContract.Schema;
|
||||
import org.mozilla.gecko.db.BrowserContract.SyncColumns;
|
||||
import org.mozilla.gecko.db.BrowserContract.Thumbnails;
|
||||
import org.mozilla.gecko.db.BrowserContract.URLColumns;
|
||||
import org.mozilla.gecko.db.PerProfileDatabases.DatabaseHelperFactory;
|
||||
import org.mozilla.gecko.gfx.BitmapUtils;
|
||||
import org.mozilla.gecko.mozglue.RobocopTarget;
|
||||
import org.mozilla.gecko.sync.Utils;
|
||||
@ -67,6 +68,8 @@ public class BrowserProvider extends ContentProvider {
|
||||
private static final String LOGTAG = "GeckoBrowserProvider";
|
||||
private Context mContext;
|
||||
|
||||
private PerProfileDatabases<BrowserDatabaseHelper> mDatabases;
|
||||
|
||||
static final String DATABASE_NAME = "browser.db";
|
||||
|
||||
static final int DATABASE_VERSION = 17;
|
||||
@ -313,8 +316,6 @@ public class BrowserProvider extends ContentProvider {
|
||||
SEARCH_SUGGEST_PROJECTION_MAP = Collections.unmodifiableMap(map);
|
||||
}
|
||||
|
||||
private HashMap<String, DatabaseHelper> mDatabasePerProfile;
|
||||
|
||||
private interface BookmarkMigrator {
|
||||
public void updateForNewTable(ContentValues bookmark);
|
||||
}
|
||||
@ -364,8 +365,8 @@ public class BrowserProvider extends ContentProvider {
|
||||
}
|
||||
}
|
||||
|
||||
final class DatabaseHelper extends SQLiteOpenHelper {
|
||||
public DatabaseHelper(Context context, String databasePath) {
|
||||
final class BrowserDatabaseHelper extends SQLiteOpenHelper {
|
||||
public BrowserDatabaseHelper(Context context, String databasePath) {
|
||||
super(context, databasePath, null, DATABASE_VERSION);
|
||||
}
|
||||
|
||||
@ -1953,63 +1954,9 @@ public class BrowserProvider extends ContentProvider {
|
||||
}
|
||||
}
|
||||
|
||||
private DatabaseHelper getDatabaseHelperForProfile(String profile, boolean isTest) {
|
||||
// Each profile has a separate browser.db database. The target
|
||||
// profile is provided using a URI query argument in each request
|
||||
// to our content provider.
|
||||
|
||||
// Always fallback to default profile if none has been provided.
|
||||
if (TextUtils.isEmpty(profile)) {
|
||||
profile = GeckoProfile.get(mContext).getName();
|
||||
}
|
||||
|
||||
DatabaseHelper dbHelper;
|
||||
synchronized (this) {
|
||||
dbHelper = mDatabasePerProfile.get(profile);
|
||||
if (dbHelper != null) {
|
||||
return dbHelper;
|
||||
}
|
||||
|
||||
String databasePath = getDatabasePath(profile, isTest);
|
||||
|
||||
// Before bug 768532, the database was located outside if the
|
||||
// profile on Android 2.2. Make sure it is moved inside the profile
|
||||
// directory.
|
||||
if (Build.VERSION.SDK_INT == 8) {
|
||||
File oldPath = mContext.getDatabasePath("browser-" + profile + ".db");
|
||||
if (oldPath.exists()) {
|
||||
oldPath.renameTo(new File(databasePath));
|
||||
}
|
||||
}
|
||||
|
||||
dbHelper = new DatabaseHelper(getContext(), databasePath);
|
||||
mDatabasePerProfile.put(profile, dbHelper);
|
||||
|
||||
DBUtils.ensureDatabaseIsNotLocked(dbHelper, databasePath);
|
||||
}
|
||||
|
||||
debug("Created database helper for profile: " + profile);
|
||||
return dbHelper;
|
||||
}
|
||||
|
||||
@RobocopTarget
|
||||
public String getDatabasePath(String profile, boolean isTest) {
|
||||
trace("Getting database path for profile: " + profile);
|
||||
|
||||
if (isTest) {
|
||||
return DATABASE_NAME;
|
||||
}
|
||||
|
||||
File profileDir = GeckoProfile.get(mContext, profile).getDir();
|
||||
if (profileDir == null) {
|
||||
debug("Couldn't find directory for profile: " + profile);
|
||||
return null;
|
||||
}
|
||||
|
||||
String databasePath = new File(profileDir, DATABASE_NAME).getAbsolutePath();
|
||||
debug("Successfully created database path for profile: " + databasePath);
|
||||
|
||||
return databasePath;
|
||||
return mDatabases.getDatabasePathForProfile(profile, isTest);
|
||||
}
|
||||
|
||||
private SQLiteDatabase getReadableDatabase(Uri uri) {
|
||||
@ -2020,7 +1967,7 @@ public class BrowserProvider extends ContentProvider {
|
||||
if (uri != null)
|
||||
profile = uri.getQueryParameter(BrowserContract.PARAM_PROFILE);
|
||||
|
||||
return getDatabaseHelperForProfile(profile, isTest(uri)).getReadableDatabase();
|
||||
return mDatabases.getDatabaseHelperForProfile(profile, isTest(uri)).getReadableDatabase();
|
||||
}
|
||||
|
||||
private SQLiteDatabase getWritableDatabase(Uri uri) {
|
||||
@ -2031,7 +1978,7 @@ public class BrowserProvider extends ContentProvider {
|
||||
if (uri != null)
|
||||
profile = uri.getQueryParameter(BrowserContract.PARAM_PROFILE);
|
||||
|
||||
return getDatabaseHelperForProfile(profile, isTest(uri)).getWritableDatabase();
|
||||
return mDatabases.getDatabaseHelperForProfile(profile, isTest(uri)).getWritableDatabase();
|
||||
}
|
||||
|
||||
private void cleanupSomeDeletedRecords(Uri fromUri, Uri targetUri, String tableName) {
|
||||
@ -2178,7 +2125,13 @@ public class BrowserProvider extends ContentProvider {
|
||||
|
||||
synchronized (this) {
|
||||
mContext = getContext();
|
||||
mDatabasePerProfile = new HashMap<String, DatabaseHelper>();
|
||||
mDatabases = new PerProfileDatabases<BrowserDatabaseHelper>(
|
||||
getContext(), DATABASE_NAME, new DatabaseHelperFactory<BrowserDatabaseHelper>() {
|
||||
@Override
|
||||
public BrowserDatabaseHelper makeDatabaseHelper(Context context, String databasePath) {
|
||||
return new BrowserDatabaseHelper(context, databasePath);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return true;
|
||||
|
81
mobile/android/base/db/PerProfileDatabases.java
Normal file
81
mobile/android/base/db/PerProfileDatabases.java
Normal file
@ -0,0 +1,81 @@
|
||||
/* 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/. */
|
||||
|
||||
package org.mozilla.gecko.db;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.mozilla.gecko.GeckoProfile;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.text.TextUtils;
|
||||
|
||||
/**
|
||||
* Manages a set of per-profile database storage helpers.
|
||||
*/
|
||||
public class PerProfileDatabases<T extends SQLiteOpenHelper> {
|
||||
|
||||
private final HashMap<String, T> mStorages = new HashMap<String, T>();
|
||||
|
||||
private final Context mContext;
|
||||
private final String mDatabaseName;
|
||||
private final DatabaseHelperFactory<T> mHelperFactory;
|
||||
|
||||
public interface DatabaseHelperFactory<T> {
|
||||
public T makeDatabaseHelper(Context context, String databasePath);
|
||||
}
|
||||
|
||||
public PerProfileDatabases(final Context context, final String databaseName, final DatabaseHelperFactory<T> helperFactory) {
|
||||
mContext = context;
|
||||
mDatabaseName = databaseName;
|
||||
mHelperFactory = helperFactory;
|
||||
}
|
||||
|
||||
public String getDatabasePathForProfile(String profile) {
|
||||
return getDatabasePathForProfile(profile, false);
|
||||
}
|
||||
|
||||
public String getDatabasePathForProfile(String profile, boolean isTest) {
|
||||
if (isTest) {
|
||||
return mDatabaseName;
|
||||
}
|
||||
|
||||
final File profileDir = GeckoProfile.get(mContext, profile).getDir();
|
||||
if (profileDir == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new File(profileDir, mDatabaseName).getAbsolutePath();
|
||||
}
|
||||
|
||||
public T getDatabaseHelperForProfile(String profile) {
|
||||
return getDatabaseHelperForProfile(profile, false);
|
||||
}
|
||||
|
||||
public T getDatabaseHelperForProfile(String profile, boolean isTest) {
|
||||
// Always fall back to default profile if none has been provided.
|
||||
if (TextUtils.isEmpty(profile)) {
|
||||
profile = GeckoProfile.get(mContext).getName();
|
||||
}
|
||||
|
||||
synchronized (this) {
|
||||
if (mStorages.containsKey(profile)) {
|
||||
return mStorages.get(profile);
|
||||
}
|
||||
|
||||
final String databasePath = getDatabasePathForProfile(profile, isTest);
|
||||
if (databasePath == null) {
|
||||
throw new IllegalStateException("Database path is null for profile: " + profile);
|
||||
}
|
||||
|
||||
final T helper = mHelperFactory.makeDatabaseHelper(mContext, databasePath);
|
||||
DBUtils.ensureDatabaseIsNotLocked(helper, databasePath);
|
||||
|
||||
mStorages.put(profile, helper);
|
||||
return helper;
|
||||
}
|
||||
}
|
||||
}
|
@ -12,6 +12,7 @@ import java.util.Map;
|
||||
import org.mozilla.gecko.GeckoProfile;
|
||||
import org.mozilla.gecko.db.BrowserContract.Clients;
|
||||
import org.mozilla.gecko.db.BrowserContract.Tabs;
|
||||
import org.mozilla.gecko.db.PerProfileDatabases.DatabaseHelperFactory;
|
||||
import org.mozilla.gecko.mozglue.RobocopTarget;
|
||||
|
||||
import android.content.ContentProvider;
|
||||
@ -33,6 +34,8 @@ public class TabsProvider extends ContentProvider {
|
||||
private static final String LOGTAG = "GeckoTabsProvider";
|
||||
private Context mContext;
|
||||
|
||||
private PerProfileDatabases<TabsDatabaseHelper> mDatabases;
|
||||
|
||||
static final String DATABASE_NAME = "tabs.db";
|
||||
|
||||
static final int DATABASE_VERSION = 2;
|
||||
@ -85,8 +88,6 @@ public class TabsProvider extends ContentProvider {
|
||||
CLIENTS_PROJECTION_MAP = Collections.unmodifiableMap(map);
|
||||
}
|
||||
|
||||
private HashMap<String, DatabaseHelper> mDatabasePerProfile;
|
||||
|
||||
static final String selectColumn(String table, String column) {
|
||||
return table + "." + column + " = ?";
|
||||
}
|
||||
@ -107,8 +108,8 @@ public class TabsProvider extends ContentProvider {
|
||||
}
|
||||
}
|
||||
|
||||
final class DatabaseHelper extends SQLiteOpenHelper {
|
||||
public DatabaseHelper(Context context, String databasePath) {
|
||||
final class TabsDatabaseHelper extends SQLiteOpenHelper {
|
||||
public TabsDatabaseHelper(Context context, String databasePath) {
|
||||
super(context, databasePath, null, DATABASE_VERSION);
|
||||
}
|
||||
|
||||
@ -207,59 +208,9 @@ public class TabsProvider extends ContentProvider {
|
||||
}
|
||||
}
|
||||
|
||||
private DatabaseHelper getDatabaseHelperForProfile(String profile) {
|
||||
// Each profile has a separate tabs.db database. The target
|
||||
// profile is provided using a URI query argument in each request
|
||||
// to our content provider.
|
||||
|
||||
// Always fallback to default profile if none has been provided.
|
||||
if (TextUtils.isEmpty(profile)) {
|
||||
profile = GeckoProfile.get(getContext()).getName();
|
||||
}
|
||||
|
||||
DatabaseHelper dbHelper;
|
||||
synchronized (this) {
|
||||
dbHelper = mDatabasePerProfile.get(profile);
|
||||
if (dbHelper != null) {
|
||||
return dbHelper;
|
||||
}
|
||||
|
||||
String databasePath = getDatabasePath(profile);
|
||||
|
||||
// Before bug 768532, the database was located outside if the
|
||||
// profile on Android 2.2. Make sure it is moved inside the profile
|
||||
// directory.
|
||||
if (Build.VERSION.SDK_INT == 8) {
|
||||
File oldPath = mContext.getDatabasePath("tabs-" + profile + ".db");
|
||||
if (oldPath.exists()) {
|
||||
oldPath.renameTo(new File(databasePath));
|
||||
}
|
||||
}
|
||||
|
||||
dbHelper = new DatabaseHelper(getContext(), databasePath);
|
||||
mDatabasePerProfile.put(profile, dbHelper);
|
||||
|
||||
DBUtils.ensureDatabaseIsNotLocked(dbHelper, databasePath);
|
||||
}
|
||||
|
||||
debug("Created database helper for profile: " + profile);
|
||||
return dbHelper;
|
||||
}
|
||||
|
||||
@RobocopTarget
|
||||
private String getDatabasePath(String profile) {
|
||||
trace("Getting database path for profile: " + profile);
|
||||
|
||||
File profileDir = GeckoProfile.get(mContext, profile).getDir();
|
||||
if (profileDir == null) {
|
||||
debug("Couldn't find directory for profile: " + profile);
|
||||
return null;
|
||||
}
|
||||
|
||||
String databasePath = new File(profileDir, DATABASE_NAME).getAbsolutePath();
|
||||
debug("Successfully created database path for profile: " + databasePath);
|
||||
|
||||
return databasePath;
|
||||
return mDatabases.getDatabasePathForProfile(profile);
|
||||
}
|
||||
|
||||
private SQLiteDatabase getReadableDatabase(Uri uri) {
|
||||
@ -270,7 +221,7 @@ public class TabsProvider extends ContentProvider {
|
||||
if (uri != null)
|
||||
profile = uri.getQueryParameter(BrowserContract.PARAM_PROFILE);
|
||||
|
||||
return getDatabaseHelperForProfile(profile).getReadableDatabase();
|
||||
return mDatabases.getDatabaseHelperForProfile(profile).getReadableDatabase();
|
||||
}
|
||||
|
||||
private SQLiteDatabase getWritableDatabase(Uri uri) {
|
||||
@ -281,7 +232,7 @@ public class TabsProvider extends ContentProvider {
|
||||
if (uri != null)
|
||||
profile = uri.getQueryParameter(BrowserContract.PARAM_PROFILE);
|
||||
|
||||
return getDatabaseHelperForProfile(profile).getWritableDatabase();
|
||||
return mDatabases.getDatabaseHelperForProfile(profile).getWritableDatabase();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -290,7 +241,13 @@ public class TabsProvider extends ContentProvider {
|
||||
|
||||
synchronized (this) {
|
||||
mContext = getContext();
|
||||
mDatabasePerProfile = new HashMap<String, DatabaseHelper>();
|
||||
mDatabases = new PerProfileDatabases<TabsDatabaseHelper>(
|
||||
getContext(), DATABASE_NAME, new DatabaseHelperFactory<TabsDatabaseHelper>() {
|
||||
@Override
|
||||
public TabsDatabaseHelper makeDatabaseHelper(Context context, String databasePath) {
|
||||
return new TabsDatabaseHelper(context, databasePath);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -117,6 +117,7 @@ gbjar.sources += [
|
||||
'db/LocalBrowserDB.java',
|
||||
'db/PasswordsProvider.java',
|
||||
'db/PerProfileContentProvider.java',
|
||||
'db/PerProfileDatabases.java',
|
||||
'db/TabsProvider.java',
|
||||
'Distribution.java',
|
||||
'DoorHanger.java',
|
||||
|
@ -5,7 +5,7 @@
|
||||
MOZ_APP_BASENAME=Fennec
|
||||
MOZ_APP_VENDOR=Mozilla
|
||||
|
||||
MOZ_APP_VERSION=28.0a1
|
||||
MOZ_APP_VERSION=29.0a1
|
||||
MOZ_APP_UA_NAME=Firefox
|
||||
|
||||
MOZ_BRANDING_DIRECTORY=mobile/android/branding/unofficial
|
||||
|
@ -14,6 +14,9 @@
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsIAsyncVerifyRedirectCallback.h"
|
||||
#include "nsISystemProxySettings.h"
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
#include "ipc/Nuwa.h"
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
using namespace mozilla;
|
||||
@ -674,6 +677,13 @@ nsPACMan::NamePACThread()
|
||||
{
|
||||
NS_ABORT_IF_FALSE(!NS_IsMainThread(), "wrong thread");
|
||||
PR_SetCurrentThreadName("Proxy Resolution");
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
if (IsNuwaProcess()) {
|
||||
NS_ASSERTION(NuwaMarkCurrentThread != nullptr,
|
||||
"NuwaMarkCurrentThread is undefined!");
|
||||
NuwaMarkCurrentThread(nullptr, nullptr);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -207,7 +207,16 @@ void RTSPSource::performPlay(int64_t playTimeUs) {
|
||||
if (mState == PAUSING) {
|
||||
playTimeUs = mLatestPausedUnit;
|
||||
}
|
||||
LOGI("performPlay : %lld", playTimeUs);
|
||||
|
||||
int64_t duration = 0;
|
||||
getDuration(&duration);
|
||||
MOZ_ASSERT(playTimeUs < duration,
|
||||
"Should never receive an out of bounds play time!");
|
||||
if (playTimeUs >= duration) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOGI("performPlay : duration=%lld playTimeUs=%lld", duration, playTimeUs);
|
||||
mState = PLAYING;
|
||||
mHandler->play(playTimeUs);
|
||||
}
|
||||
@ -238,13 +247,22 @@ void RTSPSource::performSeek(int64_t seekTimeUs) {
|
||||
if (mState != PLAYING && mState != PAUSING) {
|
||||
return;
|
||||
}
|
||||
LOGI("performSeek: %llu", seekTimeUs);
|
||||
|
||||
int64_t duration = 0;
|
||||
getDuration(&duration);
|
||||
MOZ_ASSERT(seekTimeUs < duration,
|
||||
"Should never receive an out of bounds seek time!");
|
||||
if (seekTimeUs >= duration) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < mTracks.size(); ++i) {
|
||||
TrackInfo *info = &mTracks.editItemAt(i);
|
||||
info->mLatestPausedUnit = 0;
|
||||
mLatestPausedUnit = 0;
|
||||
}
|
||||
|
||||
LOGI("performSeek: %llu", seekTimeUs);
|
||||
mState = SEEKING;
|
||||
mHandler->seek(seekTimeUs);
|
||||
}
|
||||
|
@ -4,8 +4,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/.
|
||||
|
||||
FAIL_ON_WARNINGS = True
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
'nsIWifiAccessPoint.idl',
|
||||
'nsIWifiListener.idl',
|
||||
@ -27,9 +25,10 @@ else:
|
||||
'nsWifiMonitor.cpp',
|
||||
]
|
||||
|
||||
# osx_corewlan.mm has warnings I don't understand.
|
||||
FAIL_ON_WARNINGS = CONFIG['OS_ARCH'] != 'Darwin'
|
||||
|
||||
if CONFIG['OS_ARCH'] == 'Darwin':
|
||||
# osx_corewlan.mm has warnings I don't understand.
|
||||
FAIL_ON_WARNINGS = False
|
||||
UNIFIED_SOURCES += [
|
||||
'nsWifiScannerMac.cpp',
|
||||
]
|
||||
|
@ -1051,14 +1051,6 @@ class RecursiveMakeBackend(CommonBackend):
|
||||
if not obj.dupe_manifest:
|
||||
raise
|
||||
|
||||
for base, pattern, dest in obj.pattern_installs:
|
||||
try:
|
||||
self._install_manifests['tests'].add_pattern_symlink(base,
|
||||
pattern, dest)
|
||||
except ValueError:
|
||||
if not obj.dupe_manifest:
|
||||
raise
|
||||
|
||||
for dest in obj.external_installs:
|
||||
try:
|
||||
self._install_manifests['tests'].add_optional_exists(dest)
|
||||
|
@ -24,7 +24,7 @@ from mozbuild.util import (
|
||||
shell_quote,
|
||||
StrictOrderingOnAppendList,
|
||||
)
|
||||
from .sandbox_symbols import compute_final_target
|
||||
from .sandbox_symbols import FinalTargetValue
|
||||
|
||||
|
||||
class TreeMetadata(object):
|
||||
@ -361,10 +361,6 @@ class TestManifest(SandboxDerived):
|
||||
# path is relative from the tests root directory.
|
||||
'installs',
|
||||
|
||||
# A list of pattern matching installs to perform. Entries are
|
||||
# (base, pattern, dest).
|
||||
'pattern_installs',
|
||||
|
||||
# Where all files for this manifest flavor are installed in the unified
|
||||
# test package directory.
|
||||
'install_prefix',
|
||||
@ -404,7 +400,6 @@ class TestManifest(SandboxDerived):
|
||||
self.manifest_relpath = relpath
|
||||
self.dupe_manifest = dupe_manifest
|
||||
self.installs = {}
|
||||
self.pattern_installs = []
|
||||
self.tests = []
|
||||
self.external_installs = set()
|
||||
|
||||
@ -504,6 +499,6 @@ class InstallationTarget(SandboxDerived):
|
||||
"""Returns whether or not the target is not derived from the default
|
||||
given xpiname and subdir."""
|
||||
|
||||
return compute_final_target(dict(
|
||||
return FinalTargetValue(dict(
|
||||
XPI_NAME=self.xpiname,
|
||||
DIST_SUBDIR=self.subdir)) == self.target
|
||||
|
@ -15,6 +15,8 @@ from mach.mixin.logging import LoggingMixin
|
||||
import mozpack.path as mozpath
|
||||
import manifestparser
|
||||
|
||||
from mozpack.files import FileFinder
|
||||
|
||||
from .data import (
|
||||
ConfigFileSubstitution,
|
||||
Defines,
|
||||
@ -256,6 +258,16 @@ class TreeMetadataEmitter(LoggingMixin):
|
||||
l = passthru.variables.setdefault('GARBAGE', [])
|
||||
l.append(f)
|
||||
|
||||
no_pgo = sandbox.get('NO_PGO')
|
||||
sources = sandbox.get('SOURCES', [])
|
||||
no_pgo_sources = [f for f in sources if sources[f].no_pgo]
|
||||
if no_pgo:
|
||||
if no_pgo_sources:
|
||||
raise SandboxValidationError('NO_PGO and SOURCES[...].no_pgo cannot be set at the same time')
|
||||
passthru.variables['NO_PROFILE_GUIDED_OPTIMIZE'] = no_pgo
|
||||
if no_pgo_sources:
|
||||
passthru.variables['NO_PROFILE_GUIDED_OPTIMIZE'] = no_pgo_sources
|
||||
|
||||
exports = sandbox.get('EXPORTS')
|
||||
if exports:
|
||||
yield Exports(sandbox, exports,
|
||||
@ -393,6 +405,8 @@ class TreeMetadataEmitter(LoggingMixin):
|
||||
|
||||
out_dir = mozpath.join(install_prefix, manifest_reldir)
|
||||
|
||||
finder = FileFinder(base=manifest_dir, find_executables=False)
|
||||
|
||||
# "head" and "tail" lists.
|
||||
# All manifests support support-files.
|
||||
#
|
||||
@ -417,9 +431,22 @@ class TreeMetadataEmitter(LoggingMixin):
|
||||
for pattern in value.split():
|
||||
# We only support globbing on support-files because
|
||||
# the harness doesn't support * for head and tail.
|
||||
#
|
||||
# While we could feed everything through the finder, we
|
||||
# don't because we want explicitly listed files that
|
||||
# no longer exist to raise an error. The finder is also
|
||||
# slower than simple lookup.
|
||||
if '*' in pattern and thing == 'support-files':
|
||||
obj.pattern_installs.append(
|
||||
(manifest_dir, pattern, out_dir))
|
||||
paths = [f[0] for f in finder.find(pattern)]
|
||||
if not paths:
|
||||
raise SandboxValidationError('%s support-files '
|
||||
'wildcard in %s returns no results.' % (
|
||||
pattern, path))
|
||||
|
||||
for f in paths:
|
||||
full = mozpath.normpath(mozpath.join(manifest_dir, f))
|
||||
obj.installs[full] = mozpath.join(out_dir, f)
|
||||
|
||||
else:
|
||||
full = mozpath.normpath(mozpath.join(manifest_dir,
|
||||
pattern))
|
||||
|
@ -185,9 +185,9 @@ class MozbuildSandbox(Sandbox):
|
||||
for name, func in FUNCTIONS.items():
|
||||
d[name] = getattr(self, func[0])
|
||||
|
||||
# Initialize the exports that we need in the global.
|
||||
extra_vars = self.metadata.get('exports', dict())
|
||||
self._globals.update(extra_vars)
|
||||
# Initialize the exports that we need in the global.
|
||||
extra_vars = self.metadata.get('exports', dict())
|
||||
self._globals.update(extra_vars)
|
||||
|
||||
def exec_file(self, path, filesystem_absolute=False):
|
||||
"""Override exec_file to normalize paths and restrict file loading.
|
||||
|
@ -34,6 +34,12 @@ from mozbuild.util import (
|
||||
)
|
||||
|
||||
|
||||
class SandboxDerivedValue(object):
|
||||
"""Classes deriving from this one receive a special treatment in a
|
||||
sandbox GlobalNamespace. See GlobalNamespace documentation.
|
||||
"""
|
||||
|
||||
|
||||
def alphabetical_sorted(iterable, cmp=None, key=lambda x: x.lower(),
|
||||
reverse=False):
|
||||
"""sorted() replacement for the sandbox, ordering alphabetically by
|
||||
@ -61,10 +67,17 @@ class GlobalNamespace(dict):
|
||||
|
||||
When variables are read, we first try to read the existing value. If a
|
||||
value is not found and it is defined in the allowed variables set, we
|
||||
return the default value for it. We don't assign default values until
|
||||
they are accessed because this makes debugging the end-result much
|
||||
simpler. Instead of a data structure with lots of empty/default values,
|
||||
you have a data structure with only the values that were read or touched.
|
||||
return a new instance of the class for that variable. We don't assign
|
||||
default instances until they are accessed because this makes debugging
|
||||
the end-result much simpler. Instead of a data structure with lots of
|
||||
empty/default values, you have a data structure with only the values
|
||||
that were read or touched.
|
||||
|
||||
Instances of variables classes are created by invoking class_name(),
|
||||
except when class_name derives from SandboxDerivedValue, in which
|
||||
case class_name(instance_of_the_global_namespace) is invoked.
|
||||
A value is added to those calls when instances are created during
|
||||
assignment (setitem).
|
||||
|
||||
Instantiators of this class are given a backdoor to perform setting of
|
||||
arbitrary values. e.g.
|
||||
@ -111,6 +124,8 @@ class GlobalNamespace(dict):
|
||||
|
||||
self._allow_all_writes = False
|
||||
|
||||
self._allow_one_mutation = set()
|
||||
|
||||
def __getitem__(self, name):
|
||||
try:
|
||||
return dict.__getitem__(self, name)
|
||||
@ -126,22 +141,37 @@ class GlobalNamespace(dict):
|
||||
# If the default is specifically a lambda (or, rather, any function--but
|
||||
# not a class that can be called), then it is actually a rule to
|
||||
# generate the default that should be used.
|
||||
default_rule = default[2]
|
||||
if isinstance(default_rule, type(lambda: None)):
|
||||
default_rule = default_rule(self)
|
||||
default = default[0]
|
||||
if issubclass(default, SandboxDerivedValue):
|
||||
value = default(self)
|
||||
else:
|
||||
value = default()
|
||||
|
||||
dict.__setitem__(self, name, copy.deepcopy(default_rule))
|
||||
dict.__setitem__(self, name, value)
|
||||
return dict.__getitem__(self, name)
|
||||
|
||||
def __setitem__(self, name, value):
|
||||
if self._allow_all_writes:
|
||||
dict.__setitem__(self, name, value)
|
||||
self._allow_one_mutation.add(name)
|
||||
return
|
||||
|
||||
# Forbid assigning over a previously set value. Interestingly, when
|
||||
# doing FOO += ['bar'], python actually does something like:
|
||||
# foo = namespace.__getitem__('FOO')
|
||||
# foo.__iadd__(['bar'])
|
||||
# namespace.__setitem__('FOO', foo)
|
||||
# This means __setitem__ is called with the value that is already
|
||||
# in the dict, when doing +=, which is permitted.
|
||||
if name in self._allow_one_mutation:
|
||||
self._allow_one_mutation.remove(name)
|
||||
elif name in self and dict.__getitem__(self, name) is not value:
|
||||
raise Exception('Reassigning %s is forbidden' % name)
|
||||
|
||||
# We don't need to check for name.isupper() here because LocalNamespace
|
||||
# only sends variables our way if isupper() is True.
|
||||
stored_type, input_type, default, docs, tier = \
|
||||
self._allowed_variables.get(name, (None, None, None, None, None))
|
||||
stored_type, input_type, docs, tier = \
|
||||
self._allowed_variables.get(name, (None, None, None, None))
|
||||
|
||||
# Variable is unknown.
|
||||
if stored_type is None:
|
||||
@ -160,7 +190,10 @@ class GlobalNamespace(dict):
|
||||
value, input_type)
|
||||
raise self.last_name_error
|
||||
|
||||
value = stored_type(value)
|
||||
if issubclass(stored_type, SandboxDerivedValue):
|
||||
value = stored_type(self, value)
|
||||
else:
|
||||
value = stored_type(value)
|
||||
|
||||
dict.__setitem__(self, name, value)
|
||||
|
||||
@ -177,6 +210,11 @@ class GlobalNamespace(dict):
|
||||
yield self
|
||||
self._allow_all_writes = False
|
||||
|
||||
# dict.update doesn't call our __setitem__, so we have to override it.
|
||||
def update(self, other):
|
||||
for name, value in other.items():
|
||||
self.__setitem__(name, value)
|
||||
|
||||
|
||||
class LocalNamespace(dict):
|
||||
"""Represents the locals namespace in a Sandbox.
|
||||
@ -382,6 +420,6 @@ class Sandbox(object):
|
||||
return self._globals.get(key, default)
|
||||
|
||||
def get_affected_tiers(self):
|
||||
tiers = (self._allowed_variables[key][4] for key in self
|
||||
tiers = (self._allowed_variables[key][3] for key in self
|
||||
if key in self._allowed_variables)
|
||||
return set(tier for tier in tiers if tier)
|
||||
|
@ -21,26 +21,30 @@ from collections import OrderedDict
|
||||
from mozbuild.util import (
|
||||
HierarchicalStringList,
|
||||
StrictOrderingOnAppendList,
|
||||
StrictOrderingOnAppendListWithFlagsFactory,
|
||||
)
|
||||
from .sandbox import SandboxDerivedValue
|
||||
from types import StringTypes
|
||||
|
||||
|
||||
class FinalTargetValue(SandboxDerivedValue, unicode):
|
||||
def __new__(cls, sandbox, value=""):
|
||||
if not value:
|
||||
value = 'dist/'
|
||||
if sandbox['XPI_NAME']:
|
||||
value += 'xpi-stage/' + sandbox['XPI_NAME']
|
||||
else:
|
||||
value += 'bin'
|
||||
if sandbox['DIST_SUBDIR']:
|
||||
value += '/' + sandbox['DIST_SUBDIR']
|
||||
return unicode.__new__(cls, value)
|
||||
|
||||
|
||||
def compute_final_target(variables):
|
||||
"""Convert the default value for FINAL_TARGET"""
|
||||
basedir = 'dist/'
|
||||
if variables['XPI_NAME']:
|
||||
basedir += 'xpi-stage/' + variables['XPI_NAME']
|
||||
else:
|
||||
basedir += 'bin'
|
||||
if variables['DIST_SUBDIR']:
|
||||
basedir += '/' + variables['DIST_SUBDIR']
|
||||
return basedir
|
||||
|
||||
|
||||
# This defines the set of mutable global variables.
|
||||
#
|
||||
# Each variable is a tuple of:
|
||||
#
|
||||
# (storage_type, input_types, default_value, docs, tier)
|
||||
# (storage_type, input_types, docs, tier)
|
||||
#
|
||||
# Tier says for which specific tier the variable has an effect.
|
||||
# Valid tiers are:
|
||||
@ -55,7 +59,7 @@ def compute_final_target(variables):
|
||||
|
||||
VARIABLES = {
|
||||
# Variables controlling reading of other frontend files.
|
||||
'ANDROID_GENERATED_RESFILES': (StrictOrderingOnAppendList, list, [],
|
||||
'ANDROID_GENERATED_RESFILES': (StrictOrderingOnAppendList, list,
|
||||
"""Android resource files generated as part of the build.
|
||||
|
||||
This variable contains a list of files that are expected to be
|
||||
@ -64,33 +68,33 @@ VARIABLES = {
|
||||
file.
|
||||
""", 'export'),
|
||||
|
||||
'ANDROID_RESFILES': (StrictOrderingOnAppendList, list, [],
|
||||
'ANDROID_RESFILES': (StrictOrderingOnAppendList, list,
|
||||
"""Android resource files.
|
||||
|
||||
This variable contains a list of files to package into a 'res'
|
||||
directory and merge into an APK file.
|
||||
""", 'export'),
|
||||
|
||||
'SOURCES': (StrictOrderingOnAppendList, list, [],
|
||||
'SOURCES': (StrictOrderingOnAppendListWithFlagsFactory({'no_pgo': bool}), list,
|
||||
"""Source code files.
|
||||
|
||||
This variable contains a list of source code files to compile.
|
||||
Accepts assembler, C, C++, Objective C/C++.
|
||||
""", 'compile'),
|
||||
|
||||
'GENERATED_SOURCES': (StrictOrderingOnAppendList, list, [],
|
||||
'GENERATED_SOURCES': (StrictOrderingOnAppendList, list,
|
||||
"""Generated source code files.
|
||||
|
||||
This variable contains a list of generated source code files to
|
||||
compile. Accepts assembler, C, C++, Objective C/C++.
|
||||
""", 'compile'),
|
||||
|
||||
'FILES_PER_UNIFIED_FILE': (int, int, None,
|
||||
'FILES_PER_UNIFIED_FILE': (int, int,
|
||||
"""The number of source files to compile into each unified source file.
|
||||
|
||||
""", 'None'),
|
||||
|
||||
'UNIFIED_SOURCES': (StrictOrderingOnAppendList, list, [],
|
||||
'UNIFIED_SOURCES': (StrictOrderingOnAppendList, list,
|
||||
"""Source code files that can be compiled together.
|
||||
|
||||
This variable contains a list of source code files to compile,
|
||||
@ -99,7 +103,7 @@ VARIABLES = {
|
||||
size.
|
||||
""", 'compile'),
|
||||
|
||||
'GENERATED_UNIFIED_SOURCES': (StrictOrderingOnAppendList, list, [],
|
||||
'GENERATED_UNIFIED_SOURCES': (StrictOrderingOnAppendList, list,
|
||||
"""Generated source code files that can be compiled together.
|
||||
|
||||
This variable contains a list of generated source code files to
|
||||
@ -108,7 +112,7 @@ VARIABLES = {
|
||||
and reduce the debug info size.
|
||||
""", 'compile'),
|
||||
|
||||
'GENERATED_FILES': (StrictOrderingOnAppendList, list, [],
|
||||
'GENERATED_FILES': (StrictOrderingOnAppendList, list,
|
||||
"""Generic generated files.
|
||||
|
||||
This variable contains a list of generate files for the build system
|
||||
@ -116,7 +120,7 @@ VARIABLES = {
|
||||
Makefile.in.
|
||||
""", 'export'),
|
||||
|
||||
'DEFINES': (OrderedDict, dict, OrderedDict(),
|
||||
'DEFINES': (OrderedDict, dict,
|
||||
"""Dictionary of compiler defines to declare.
|
||||
|
||||
These are passed in to the compiler as ``-Dkey='value'`` for string
|
||||
@ -144,7 +148,7 @@ VARIABLES = {
|
||||
})
|
||||
""", None),
|
||||
|
||||
'DIRS': (list, list, [],
|
||||
'DIRS': (list, list,
|
||||
"""Child directories to descend into looking for build frontend files.
|
||||
|
||||
This works similarly to the ``DIRS`` variable in make files. Each str
|
||||
@ -158,18 +162,18 @@ VARIABLES = {
|
||||
delimiters.
|
||||
""", None),
|
||||
|
||||
'EXPORT_LIBRARY': (bool, bool, False,
|
||||
'EXPORT_LIBRARY': (bool, bool,
|
||||
"""Install the library to the static libraries folder.
|
||||
""", None),
|
||||
|
||||
'EXTRA_COMPONENTS': (StrictOrderingOnAppendList, list, [],
|
||||
'EXTRA_COMPONENTS': (StrictOrderingOnAppendList, list,
|
||||
"""Additional component files to distribute.
|
||||
|
||||
This variable contains a list of files to copy into
|
||||
``$(FINAL_TARGET)/components/``.
|
||||
""", 'libs'),
|
||||
|
||||
'EXTRA_JS_MODULES': (StrictOrderingOnAppendList, list, [],
|
||||
'EXTRA_JS_MODULES': (StrictOrderingOnAppendList, list,
|
||||
"""Additional JavaScript files to distribute.
|
||||
|
||||
This variable contains a list of files to copy into
|
||||
@ -177,7 +181,7 @@ VARIABLES = {
|
||||
to ``modules`` if left undefined.
|
||||
""", 'libs'),
|
||||
|
||||
'EXTRA_PP_JS_MODULES': (StrictOrderingOnAppendList, list, [],
|
||||
'EXTRA_PP_JS_MODULES': (StrictOrderingOnAppendList, list,
|
||||
"""Additional JavaScript files to distribute.
|
||||
|
||||
This variable contains a list of files to copy into
|
||||
@ -185,14 +189,14 @@ VARIABLES = {
|
||||
``JS_MODULES_PATH`` defaults to ``modules`` if left undefined.
|
||||
""", 'libs'),
|
||||
|
||||
'EXTRA_PP_COMPONENTS': (StrictOrderingOnAppendList, list, [],
|
||||
'EXTRA_PP_COMPONENTS': (StrictOrderingOnAppendList, list,
|
||||
"""Javascript XPCOM files.
|
||||
|
||||
This variable contains a list of files to preprocess. Generated
|
||||
files will be installed in the ``/components`` directory of the distribution.
|
||||
""", 'libs'),
|
||||
|
||||
'FINAL_LIBRARY': (unicode, unicode, "",
|
||||
'FINAL_LIBRARY': (unicode, unicode,
|
||||
"""Library in which the objects of the current directory will be linked.
|
||||
|
||||
This variable contains the name of a library, defined elsewhere with
|
||||
@ -200,42 +204,42 @@ VARIABLES = {
|
||||
linked.
|
||||
""", 'binaries'),
|
||||
|
||||
'CPP_UNIT_TESTS': (StrictOrderingOnAppendList, list, [],
|
||||
'CPP_UNIT_TESTS': (StrictOrderingOnAppendList, list,
|
||||
"""C++ source files for unit tests.
|
||||
|
||||
This is a list of C++ unit test sources. Entries must be files that
|
||||
exist. These generally have ``.cpp`` extensions.
|
||||
""", 'binaries'),
|
||||
|
||||
'FAIL_ON_WARNINGS': (bool, bool, False,
|
||||
'FAIL_ON_WARNINGS': (bool, bool,
|
||||
"""Whether to treat warnings as errors.
|
||||
""", None),
|
||||
|
||||
'FORCE_SHARED_LIB': (bool, bool, False,
|
||||
'FORCE_SHARED_LIB': (bool, bool,
|
||||
"""Whether the library in this directory is a shared library.
|
||||
""", None),
|
||||
|
||||
'FORCE_STATIC_LIB': (bool, bool, False,
|
||||
'FORCE_STATIC_LIB': (bool, bool,
|
||||
"""Whether the library in this directory is a static library.
|
||||
""", None),
|
||||
|
||||
'GENERATED_INCLUDES' : (StrictOrderingOnAppendList, list, [],
|
||||
'GENERATED_INCLUDES' : (StrictOrderingOnAppendList, list,
|
||||
"""Directories generated by the build system to be searched for include
|
||||
files by the compiler.
|
||||
""", None),
|
||||
|
||||
'HOST_SOURCES': (StrictOrderingOnAppendList, list, [],
|
||||
'HOST_SOURCES': (StrictOrderingOnAppendList, list,
|
||||
"""Source code files to compile with the host compiler.
|
||||
|
||||
This variable contains a list of source code files to compile.
|
||||
with the host compiler.
|
||||
""", 'compile'),
|
||||
|
||||
'IS_COMPONENT': (bool, bool, False,
|
||||
'IS_COMPONENT': (bool, bool,
|
||||
"""Whether the library contains a binary XPCOM component manifest.
|
||||
""", None),
|
||||
|
||||
'PARALLEL_DIRS': (list, list, [],
|
||||
'PARALLEL_DIRS': (list, list,
|
||||
"""A parallel version of ``DIRS``.
|
||||
|
||||
Ideally this variable does not exist. It is provided so a transition
|
||||
@ -244,18 +248,18 @@ VARIABLES = {
|
||||
likely go away.
|
||||
""", None),
|
||||
|
||||
'HOST_LIBRARY_NAME': (unicode, unicode, "",
|
||||
'HOST_LIBRARY_NAME': (unicode, unicode,
|
||||
"""Name of target library generated when cross compiling.
|
||||
""", 'binaries'),
|
||||
|
||||
'JAVA_JAR_TARGETS': (dict, dict, {},
|
||||
'JAVA_JAR_TARGETS': (dict, dict,
|
||||
"""Defines Java JAR targets to be built.
|
||||
|
||||
This variable should not be populated directly. Instead, it should
|
||||
populated by calling add_java_jar().
|
||||
""", 'binaries'),
|
||||
|
||||
'JS_MODULES_PATH': (unicode, unicode, "",
|
||||
'JS_MODULES_PATH': (unicode, unicode,
|
||||
"""Sub-directory of ``$(FINAL_TARGET)`` to install
|
||||
``EXTRA_JS_MODULES``.
|
||||
|
||||
@ -265,7 +269,7 @@ VARIABLES = {
|
||||
``$(FINAL_TARGET)/modules``.
|
||||
""", None),
|
||||
|
||||
'LIBRARY_NAME': (unicode, unicode, "",
|
||||
'LIBRARY_NAME': (unicode, unicode,
|
||||
"""The name of the library generated for a directory.
|
||||
|
||||
In ``example/components/moz.build``,::
|
||||
@ -276,44 +280,48 @@ VARIABLES = {
|
||||
``example/components/xpcomsample.lib`` on Windows.
|
||||
""", 'binaries'),
|
||||
|
||||
'LIBS': (StrictOrderingOnAppendList, list, [],
|
||||
'LIBS': (StrictOrderingOnAppendList, list,
|
||||
"""Linker libraries and flags.
|
||||
|
||||
A list of libraries and flags to include when linking.
|
||||
""", None),
|
||||
|
||||
'LIBXUL_LIBRARY': (bool, bool, False,
|
||||
'LIBXUL_LIBRARY': (bool, bool,
|
||||
"""Whether the library in this directory is linked into libxul.
|
||||
|
||||
Implies ``MOZILLA_INTERNAL_API`` and ``FORCE_STATIC_LIB``.
|
||||
""", None),
|
||||
|
||||
'LOCAL_INCLUDES': (StrictOrderingOnAppendList, list, [],
|
||||
'LOCAL_INCLUDES': (StrictOrderingOnAppendList, list,
|
||||
"""Additional directories to be searched for include files by the compiler.
|
||||
""", None),
|
||||
|
||||
'MSVC_ENABLE_PGO': (bool, bool, False,
|
||||
"""Whether profile-guided optimization is enabled in this directory.
|
||||
'MSVC_ENABLE_PGO': (bool, bool,
|
||||
"""Whether profile-guided optimization is enabled for MSVC in this directory.
|
||||
""", None),
|
||||
|
||||
'NO_VISIBILITY_FLAGS': (bool, bool, False,
|
||||
'NO_PGO': (bool, bool,
|
||||
"""Whether profile-guided optimization is disable in this directory.
|
||||
""", None),
|
||||
|
||||
'NO_VISIBILITY_FLAGS': (bool, bool,
|
||||
"""Build sources listed in this file without VISIBILITY_FLAGS.
|
||||
""", None),
|
||||
|
||||
'OS_LIBS': (list, list, [],
|
||||
'OS_LIBS': (list, list,
|
||||
"""System link libraries.
|
||||
|
||||
This variable contains a list of system libaries to link against.
|
||||
""", None),
|
||||
|
||||
'SDK_LIBRARY': (StrictOrderingOnAppendList, list, [],
|
||||
'SDK_LIBRARY': (StrictOrderingOnAppendList, list,
|
||||
"""Elements of the distributed SDK.
|
||||
|
||||
Files on this list will be copied into ``SDK_LIB_DIR``
|
||||
(``$DIST/sdk/lib``).
|
||||
""", None),
|
||||
|
||||
'SIMPLE_PROGRAMS': (StrictOrderingOnAppendList, list, [],
|
||||
'SIMPLE_PROGRAMS': (StrictOrderingOnAppendList, list,
|
||||
"""Compile a list of executable names.
|
||||
|
||||
Each name in this variable corresponds to an executable built from the
|
||||
@ -324,7 +332,7 @@ VARIABLES = {
|
||||
``BIN_SUFFIX``, the name will remain unchanged.
|
||||
""", 'binaries'),
|
||||
|
||||
'HOST_SIMPLE_PROGRAMS': (StrictOrderingOnAppendList, list, [],
|
||||
'HOST_SIMPLE_PROGRAMS': (StrictOrderingOnAppendList, list,
|
||||
"""Compile a list of host executable names.
|
||||
|
||||
Each name in this variable corresponds to a hosst executable built
|
||||
@ -335,7 +343,7 @@ VARIABLES = {
|
||||
``HOST_BIN_SUFFIX``, the name will remain unchanged.
|
||||
""", 'binaries'),
|
||||
|
||||
'TOOL_DIRS': (list, list, [],
|
||||
'TOOL_DIRS': (list, list,
|
||||
"""Like DIRS but for tools.
|
||||
|
||||
Tools are for pieces of the build system that aren't required to
|
||||
@ -343,7 +351,7 @@ VARIABLES = {
|
||||
code and utilities.
|
||||
""", None),
|
||||
|
||||
'TEST_DIRS': (list, list, [],
|
||||
'TEST_DIRS': (list, list,
|
||||
"""Like DIRS but only for directories that contain test-only code.
|
||||
|
||||
If tests are not enabled, this variable will be ignored.
|
||||
@ -352,12 +360,12 @@ VARIABLES = {
|
||||
complete.
|
||||
""", None),
|
||||
|
||||
'TEST_TOOL_DIRS': (list, list, [],
|
||||
'TEST_TOOL_DIRS': (list, list,
|
||||
"""TOOL_DIRS that is only executed if tests are enabled.
|
||||
""", None),
|
||||
|
||||
|
||||
'TIERS': (OrderedDict, dict, OrderedDict(),
|
||||
'TIERS': (OrderedDict, dict,
|
||||
"""Defines directories constituting the tier traversal mechanism.
|
||||
|
||||
The recursive make backend iteration is organized into tiers. There are
|
||||
@ -375,7 +383,7 @@ VARIABLES = {
|
||||
populated by calling add_tier_dir().
|
||||
""", None),
|
||||
|
||||
'EXTERNAL_MAKE_DIRS': (list, list, [],
|
||||
'EXTERNAL_MAKE_DIRS': (list, list,
|
||||
"""Directories that build with make but don't use moz.build files.
|
||||
|
||||
This is like ``DIRS`` except it implies that ``make`` is used to build the
|
||||
@ -383,11 +391,11 @@ VARIABLES = {
|
||||
files.
|
||||
""", None),
|
||||
|
||||
'PARALLEL_EXTERNAL_MAKE_DIRS': (list, list, [],
|
||||
'PARALLEL_EXTERNAL_MAKE_DIRS': (list, list,
|
||||
"""Parallel version of ``EXTERNAL_MAKE_DIRS``.
|
||||
""", None),
|
||||
|
||||
'CONFIGURE_SUBST_FILES': (StrictOrderingOnAppendList, list, [],
|
||||
'CONFIGURE_SUBST_FILES': (StrictOrderingOnAppendList, list,
|
||||
"""Output files that will be generated using configure-like substitution.
|
||||
|
||||
This is a substitute for ``AC_OUTPUT`` in autoconf. For each path in this
|
||||
@ -397,7 +405,7 @@ VARIABLES = {
|
||||
``AC_SUBST`` variables declared during configure.
|
||||
""", None),
|
||||
|
||||
'CONFIGURE_DEFINE_FILES': (StrictOrderingOnAppendList, list, [],
|
||||
'CONFIGURE_DEFINE_FILES': (StrictOrderingOnAppendList, list,
|
||||
"""Output files generated from configure/config.status.
|
||||
|
||||
This is a substitute for ``AC_CONFIG_HEADER`` in autoconf. This is very
|
||||
@ -405,7 +413,7 @@ VARIABLES = {
|
||||
into account the values of ``AC_DEFINE`` instead of ``AC_SUBST``.
|
||||
""", None),
|
||||
|
||||
'EXPORTS': (HierarchicalStringList, list, HierarchicalStringList(),
|
||||
'EXPORTS': (HierarchicalStringList, list,
|
||||
"""List of files to be exported, and in which subdirectories.
|
||||
|
||||
``EXPORTS`` is generally used to list the include files to be exported to
|
||||
@ -420,7 +428,7 @@ VARIABLES = {
|
||||
EXPORTS.mozilla.dom += ['bar.h']
|
||||
""", None),
|
||||
|
||||
'PROGRAM' : (unicode, unicode, "",
|
||||
'PROGRAM' : (unicode, unicode,
|
||||
"""Compiled executable name.
|
||||
|
||||
If the configuration token ``BIN_SUFFIX`` is set, its value will be
|
||||
@ -428,7 +436,7 @@ VARIABLES = {
|
||||
``BIN_SUFFIX``, ``PROGRAM`` will remain unchanged.
|
||||
""", 'binaries'),
|
||||
|
||||
'HOST_PROGRAM' : (unicode, unicode, "",
|
||||
'HOST_PROGRAM' : (unicode, unicode,
|
||||
"""Compiled host executable name.
|
||||
|
||||
If the configuration token ``HOST_BIN_SUFFIX`` is set, its value will be
|
||||
@ -436,7 +444,7 @@ VARIABLES = {
|
||||
ends with ``HOST_BIN_SUFFIX``, ``HOST_PROGRAM`` will remain unchanged.
|
||||
""", 'binaries'),
|
||||
|
||||
'NO_DIST_INSTALL': (bool, bool, False,
|
||||
'NO_DIST_INSTALL': (bool, bool,
|
||||
"""Disable installing certain files into the distribution directory.
|
||||
|
||||
If present, some files defined by other variables won't be
|
||||
@ -444,7 +452,7 @@ VARIABLES = {
|
||||
""", None),
|
||||
|
||||
# IDL Generation.
|
||||
'XPIDL_SOURCES': (StrictOrderingOnAppendList, list, [],
|
||||
'XPIDL_SOURCES': (StrictOrderingOnAppendList, list,
|
||||
"""XPCOM Interface Definition Files (xpidl).
|
||||
|
||||
This is a list of files that define XPCOM interface definitions.
|
||||
@ -452,7 +460,7 @@ VARIABLES = {
|
||||
files.
|
||||
""", 'libs'),
|
||||
|
||||
'XPIDL_MODULE': (unicode, unicode, "",
|
||||
'XPIDL_MODULE': (unicode, unicode,
|
||||
"""XPCOM Interface Definition Module Name.
|
||||
|
||||
This is the name of the ``.xpt`` file that is created by linking
|
||||
@ -460,93 +468,93 @@ VARIABLES = {
|
||||
as ``MODULE``.
|
||||
""", None),
|
||||
|
||||
'IPDL_SOURCES': (StrictOrderingOnAppendList, list, [],
|
||||
'IPDL_SOURCES': (StrictOrderingOnAppendList, list,
|
||||
"""IPDL source files.
|
||||
|
||||
These are ``.ipdl`` files that will be parsed and converted to
|
||||
``.cpp`` files.
|
||||
""", 'export'),
|
||||
|
||||
'WEBIDL_FILES': (StrictOrderingOnAppendList, list, [],
|
||||
'WEBIDL_FILES': (StrictOrderingOnAppendList, list,
|
||||
"""WebIDL source files.
|
||||
|
||||
These will be parsed and converted to ``.cpp`` and ``.h`` files.
|
||||
""", 'export'),
|
||||
|
||||
'GENERATED_EVENTS_WEBIDL_FILES': (StrictOrderingOnAppendList, list, [],
|
||||
'GENERATED_EVENTS_WEBIDL_FILES': (StrictOrderingOnAppendList, list,
|
||||
"""WebIDL source files for generated events.
|
||||
|
||||
These will be parsed and converted to ``.cpp`` and ``.h`` files.
|
||||
""", 'export'),
|
||||
|
||||
'TEST_WEBIDL_FILES': (StrictOrderingOnAppendList, list, [],
|
||||
'TEST_WEBIDL_FILES': (StrictOrderingOnAppendList, list,
|
||||
"""Test WebIDL source files.
|
||||
|
||||
These will be parsed and converted to ``.cpp`` and ``.h`` files
|
||||
if tests are enabled.
|
||||
""", 'export'),
|
||||
|
||||
'GENERATED_WEBIDL_FILES': (StrictOrderingOnAppendList, list, [],
|
||||
'GENERATED_WEBIDL_FILES': (StrictOrderingOnAppendList, list,
|
||||
"""Generated WebIDL source files.
|
||||
|
||||
These will be generated from some other files.
|
||||
""", 'export'),
|
||||
|
||||
'PREPROCESSED_TEST_WEBIDL_FILES': (StrictOrderingOnAppendList, list, [],
|
||||
'PREPROCESSED_TEST_WEBIDL_FILES': (StrictOrderingOnAppendList, list,
|
||||
"""Preprocessed test WebIDL source files.
|
||||
|
||||
These will be preprocessed, then parsed and converted to .cpp
|
||||
and ``.h`` files if tests are enabled.
|
||||
""", 'export'),
|
||||
|
||||
'PREPROCESSED_WEBIDL_FILES': (StrictOrderingOnAppendList, list, [],
|
||||
'PREPROCESSED_WEBIDL_FILES': (StrictOrderingOnAppendList, list,
|
||||
"""Preprocessed WebIDL source files.
|
||||
|
||||
These will be preprocessed before being parsed and converted.
|
||||
""", 'export'),
|
||||
|
||||
# Test declaration.
|
||||
'A11Y_MANIFESTS': (StrictOrderingOnAppendList, list, [],
|
||||
'A11Y_MANIFESTS': (StrictOrderingOnAppendList, list,
|
||||
"""List of manifest files defining a11y tests.
|
||||
""", None),
|
||||
|
||||
'BROWSER_CHROME_MANIFESTS': (StrictOrderingOnAppendList, list, [],
|
||||
'BROWSER_CHROME_MANIFESTS': (StrictOrderingOnAppendList, list,
|
||||
"""List of manifest files defining browser chrome tests.
|
||||
""", None),
|
||||
|
||||
'METRO_CHROME_MANIFESTS': (StrictOrderingOnAppendList, list, [],
|
||||
'METRO_CHROME_MANIFESTS': (StrictOrderingOnAppendList, list,
|
||||
"""List of manifest files defining metro browser chrome tests.
|
||||
""", None),
|
||||
|
||||
'MOCHITEST_CHROME_MANIFESTS': (StrictOrderingOnAppendList, list, [],
|
||||
'MOCHITEST_CHROME_MANIFESTS': (StrictOrderingOnAppendList, list,
|
||||
"""List of manifest files defining mochitest chrome tests.
|
||||
""", None),
|
||||
|
||||
'MOCHITEST_MANIFESTS': (StrictOrderingOnAppendList, list, [],
|
||||
'MOCHITEST_MANIFESTS': (StrictOrderingOnAppendList, list,
|
||||
"""List of manifest files defining mochitest tests.
|
||||
""", None),
|
||||
|
||||
'MOCHITEST_WEBAPPRT_CHROME_MANIFESTS': (StrictOrderingOnAppendList, list, [],
|
||||
'MOCHITEST_WEBAPPRT_CHROME_MANIFESTS': (StrictOrderingOnAppendList, list,
|
||||
"""List of manifest files defining webapprt mochitest chrome tests.
|
||||
""", None),
|
||||
|
||||
'WEBRTC_SIGNALLING_TEST_MANIFESTS': (StrictOrderingOnAppendList, list, [],
|
||||
'WEBRTC_SIGNALLING_TEST_MANIFESTS': (StrictOrderingOnAppendList, list,
|
||||
"""List of manifest files defining WebRTC signalling tests.
|
||||
""", None),
|
||||
|
||||
'XPCSHELL_TESTS_MANIFESTS': (StrictOrderingOnAppendList, list, [],
|
||||
'XPCSHELL_TESTS_MANIFESTS': (StrictOrderingOnAppendList, list,
|
||||
"""List of manifest files defining xpcshell tests.
|
||||
""", None),
|
||||
|
||||
# The following variables are used to control the target of installed files.
|
||||
'XPI_NAME': (unicode, unicode, "",
|
||||
'XPI_NAME': (unicode, unicode,
|
||||
"""The name of an extension XPI to generate.
|
||||
|
||||
When this variable is present, the results of this directory will end up
|
||||
being packaged into an extension instead of the main dist/bin results.
|
||||
""", 'libs'),
|
||||
|
||||
'DIST_SUBDIR': (unicode, unicode, "",
|
||||
'DIST_SUBDIR': (unicode, unicode,
|
||||
"""The name of an alternate directory to install files to.
|
||||
|
||||
When this variable is present, the results of this directory will end up
|
||||
@ -554,7 +562,7 @@ VARIABLES = {
|
||||
otherwise be placed.
|
||||
""", 'libs'),
|
||||
|
||||
'FINAL_TARGET': (unicode, unicode, compute_final_target,
|
||||
'FINAL_TARGET': (FinalTargetValue, unicode,
|
||||
"""The name of the directory to install targets to.
|
||||
|
||||
The directory is relative to the top of the object directory. The
|
||||
|
@ -49,7 +49,7 @@ def function_reference(f, attr, args, doc):
|
||||
return lines
|
||||
|
||||
|
||||
def variable_reference(v, st_type, in_type, default, doc, tier):
|
||||
def variable_reference(v, st_type, in_type, doc, tier):
|
||||
lines = [
|
||||
v,
|
||||
'-' * len(v),
|
||||
@ -66,7 +66,6 @@ def variable_reference(v, st_type, in_type, default, doc, tier):
|
||||
lines.extend([
|
||||
':Storage Type: ``%s``' % st_type.__name__,
|
||||
':Input Type: ``%s``' % in_type.__name__,
|
||||
':Default Value: %s' % default,
|
||||
'',
|
||||
])
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
[DEFAULT]
|
||||
support-files = support/**
|
||||
|
||||
[xpcshell.js]
|
||||
|
@ -382,18 +382,6 @@ class TestRecursiveMakeBackend(BackendTester):
|
||||
|
||||
self.assertEqual(len(o['xpcshell.js']), 1)
|
||||
|
||||
def test_test_manifest_pattern_matches_recorded(self):
|
||||
"""Pattern matches in test manifests' support-files should be recorded."""
|
||||
env = self._consume('test-manifests-written', RecursiveMakeBackend)
|
||||
m = InstallManifest(path=os.path.join(env.topobjdir,
|
||||
'_build_manifests', 'install', 'tests'))
|
||||
|
||||
# This is not the most robust test in the world, but it gets the job
|
||||
# done.
|
||||
entries = [e for e in m._dests.keys() if '**' in e]
|
||||
self.assertEqual(len(entries), 1)
|
||||
self.assertIn('support/**', entries[0])
|
||||
|
||||
def test_xpidl_generation(self):
|
||||
"""Ensure xpidl files and directories are written out."""
|
||||
env = self._consume('xpidl', RecursiveMakeBackend)
|
||||
|
@ -3,5 +3,3 @@
|
||||
# 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/.
|
||||
|
||||
XPIDL_MODULE = 'bazbar'
|
||||
|
@ -248,8 +248,10 @@ class TestEmitterBasic(unittest.TestCase):
|
||||
'installs': {
|
||||
'a11y.ini',
|
||||
'test_a11y.js',
|
||||
# From ** wildcard.
|
||||
'a11y-support/foo',
|
||||
'a11y-support/dir1/bar',
|
||||
},
|
||||
'pattern-installs': 1,
|
||||
},
|
||||
'browser.ini': {
|
||||
'flavor': 'browser-chrome',
|
||||
@ -317,9 +319,6 @@ class TestEmitterBasic(unittest.TestCase):
|
||||
|
||||
self.assertIn(path, m['installs'])
|
||||
|
||||
if 'pattern-installs' in m:
|
||||
self.assertEqual(len(o.pattern_installs), m['pattern-installs'])
|
||||
|
||||
def test_test_manifest_unmatched_generated(self):
|
||||
reader = self.reader('test-manifest-unmatched-generated')
|
||||
|
||||
|
@ -76,10 +76,23 @@ class TestGlobalNamespace(unittest.TestCase):
|
||||
self.assertTrue(d['foo'])
|
||||
|
||||
with self.assertRaises(KeyError) as ke:
|
||||
ns['foo'] = False
|
||||
ns['bar'] = False
|
||||
|
||||
self.assertEqual(ke.exception.args[1], 'set_unknown')
|
||||
|
||||
ns['DIRS'] = []
|
||||
with self.assertRaisesRegexp(Exception, 'Reassigning .* is forbidden') as ke:
|
||||
ns['DIRS'] = []
|
||||
|
||||
with ns.allow_all_writes() as d:
|
||||
d['DIST_SUBDIR'] = 'foo'
|
||||
|
||||
self.assertEqual(ns['DIST_SUBDIR'], 'foo')
|
||||
ns['DIST_SUBDIR'] = 'bar'
|
||||
self.assertEqual(ns['DIST_SUBDIR'], 'bar')
|
||||
with self.assertRaisesRegexp(Exception, 'Reassigning .* is forbidden') as ke:
|
||||
ns['DIST_SUBDIR'] = 'baz'
|
||||
|
||||
self.assertTrue(d['foo'])
|
||||
|
||||
def test_key_checking(self):
|
||||
|
@ -262,7 +262,7 @@ class TestBuildReader(unittest.TestCase):
|
||||
self.assertEqual([sandbox['RELATIVEDIR'] for sandbox in sandboxes],
|
||||
['', 'foo', 'foo/baz', 'bar'])
|
||||
self.assertEqual([sandbox['XPIDL_MODULE'] for sandbox in sandboxes],
|
||||
['foobar', 'foobar', 'foobar', 'bazbar'])
|
||||
['foobar', 'foobar', 'foobar', 'foobar'])
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
@ -146,9 +146,9 @@ class TestSandbox(unittest.TestCase):
|
||||
sandbox = self.sandbox()
|
||||
|
||||
sandbox.exec_source('DIRS = ["foo"]', 'foo.py')
|
||||
sandbox.exec_source('DIRS = ["bar"]', 'foo.py')
|
||||
sandbox.exec_source('DIRS += ["bar"]', 'foo.py')
|
||||
|
||||
self.assertEqual(sandbox['DIRS'], ['bar'])
|
||||
self.assertEqual(sandbox['DIRS'], ['foo', 'bar'])
|
||||
|
||||
def test_exec_source_illegal_key_set(self):
|
||||
sandbox = self.sandbox()
|
||||
|
@ -36,7 +36,7 @@ class TestSymbols(unittest.TestCase):
|
||||
self.assertEqual(lines[-1].strip(), '')
|
||||
|
||||
def test_documentation_formatting(self):
|
||||
for typ, inp, default, doc, tier in VARIABLES.values():
|
||||
for typ, inp, doc, tier in VARIABLES.values():
|
||||
self._verify_doc(doc)
|
||||
|
||||
for attr, args, doc in FUNCTIONS.values():
|
||||
|
@ -22,6 +22,7 @@ from mozbuild.util import (
|
||||
MozbuildDeletionError,
|
||||
HierarchicalStringList,
|
||||
StrictOrderingOnAppendList,
|
||||
StrictOrderingOnAppendListWithFlagsFactory,
|
||||
UnsortedError,
|
||||
)
|
||||
|
||||
@ -285,5 +286,39 @@ class TestStrictOrderingOnAppendList(unittest.TestCase):
|
||||
self.assertEqual(len(l), 2)
|
||||
|
||||
|
||||
class TestStrictOrderingOnAppendListWithFlagsFactory(unittest.TestCase):
|
||||
def test_strict_ordering_on_append_list_with_flags_factory(self):
|
||||
cls = StrictOrderingOnAppendListWithFlagsFactory({
|
||||
'foo': bool,
|
||||
'bar': int,
|
||||
})
|
||||
|
||||
l = cls()
|
||||
l += ['a', 'b']
|
||||
|
||||
with self.assertRaises(Exception):
|
||||
l['a'] = 'foo'
|
||||
|
||||
with self.assertRaises(Exception):
|
||||
c = l['c']
|
||||
|
||||
self.assertEqual(l['a'].foo, False)
|
||||
l['a'].foo = True
|
||||
self.assertEqual(l['a'].foo, True)
|
||||
|
||||
with self.assertRaises(TypeError):
|
||||
l['a'].bar = 'bar'
|
||||
|
||||
self.assertEqual(l['a'].bar, 0)
|
||||
l['a'].bar = 42
|
||||
self.assertEqual(l['a'].bar, 42)
|
||||
|
||||
l['b'].foo = True
|
||||
self.assertEqual(l['b'].foo, True)
|
||||
|
||||
with self.assertRaises(AttributeError):
|
||||
l['b'].baz = False
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
@ -301,6 +301,74 @@ class StrictOrderingOnAppendList(list):
|
||||
class MozbuildDeletionError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def StrictOrderingOnAppendListWithFlagsFactory(flags):
|
||||
"""Returns a StrictOrderingOnAppendList-like object, with optional
|
||||
flags on each item.
|
||||
|
||||
The flags are defined in the dict given as argument, where keys are
|
||||
the flag names, and values the type used for the value of that flag.
|
||||
|
||||
Example:
|
||||
FooList = StrictOrderingOnAppendListWithFlagsFactory({
|
||||
'foo': bool, 'bar': unicode
|
||||
})
|
||||
foo = FooList(['a', 'b', 'c'])
|
||||
foo['a'].foo = True
|
||||
foo['b'].bar = 'bar'
|
||||
"""
|
||||
|
||||
assert isinstance(flags, dict)
|
||||
assert all(isinstance(v, type) for v in flags.values())
|
||||
|
||||
class Flags(object):
|
||||
__slots__ = flags.keys()
|
||||
_flags = flags
|
||||
|
||||
def __getattr__(self, name):
|
||||
if name not in self.__slots__:
|
||||
raise AttributeError("'%s' object has no attribute '%s'" %
|
||||
(self.__class__.__name__, name))
|
||||
try:
|
||||
return object.__getattr__(self, name)
|
||||
except AttributeError:
|
||||
value = self._flags[name]()
|
||||
self.__setattr__(name, value)
|
||||
return value
|
||||
|
||||
def __setattr__(self, name, value):
|
||||
if name not in self.__slots__:
|
||||
raise AttributeError("'%s' object has no attribute '%s'" %
|
||||
(self.__class__.__name__, name))
|
||||
if not isinstance(value, self._flags[name]):
|
||||
raise TypeError("'%s' attribute of class '%s' must be '%s'" %
|
||||
(name, self.__class__.__name__,
|
||||
self._flags[name].__name__))
|
||||
return object.__setattr__(self, name, value)
|
||||
|
||||
def __delattr__(self, name):
|
||||
raise MozbuildDeletionError('Unable to delete attributes for this object')
|
||||
|
||||
class StrictOrderingOnAppendListWithFlags(StrictOrderingOnAppendList):
|
||||
def __init__(self, iterable=[]):
|
||||
StrictOrderingOnAppendList.__init__(self, iterable)
|
||||
self._flags_type = Flags
|
||||
self._flags = dict()
|
||||
|
||||
def __getitem__(self, name):
|
||||
if name not in self._flags:
|
||||
if name not in self:
|
||||
raise KeyError("'%s'" % name)
|
||||
self._flags[name] = self._flags_type()
|
||||
return self._flags[name]
|
||||
|
||||
def __setitem__(self, name, value):
|
||||
raise TypeError("'%s' object does not support item assignment" %
|
||||
self.__class__.__name__)
|
||||
|
||||
return StrictOrderingOnAppendListWithFlags
|
||||
|
||||
|
||||
class HierarchicalStringList(object):
|
||||
"""A hierarchy of lists of strings.
|
||||
|
||||
|
@ -6,11 +6,11 @@ from __future__ import unicode_literals
|
||||
|
||||
from contextlib import contextmanager
|
||||
|
||||
from .copier import FilePurger
|
||||
from .files import (
|
||||
AbsoluteSymlinkFile,
|
||||
ExistingFile,
|
||||
File,
|
||||
FileFinder,
|
||||
)
|
||||
import mozpack.path as mozpath
|
||||
|
||||
@ -63,15 +63,8 @@ class InstallManifest(object):
|
||||
the FileCopier. No error is raised if the destination path does not
|
||||
exist.
|
||||
|
||||
patternsymlink -- Paths matched by the expression in the source path
|
||||
will be symlinked to the destination directory.
|
||||
|
||||
patterncopy -- Similar to patternsymlink except files are copied, not
|
||||
symlinked.
|
||||
|
||||
Version 1 of the manifest was the initial version.
|
||||
Version 2 added optional path support
|
||||
Version 3 added support for pattern entries.
|
||||
Versions 1 and 2 of the manifest format are similar. Version 2 added
|
||||
optional path support.
|
||||
"""
|
||||
FIELD_SEPARATOR = '\x1f'
|
||||
|
||||
@ -79,8 +72,6 @@ class InstallManifest(object):
|
||||
COPY = 2
|
||||
REQUIRED_EXISTS = 3
|
||||
OPTIONAL_EXISTS = 4
|
||||
PATTERN_SYMLINK = 5
|
||||
PATTERN_COPY = 6
|
||||
|
||||
def __init__(self, path=None, fileobj=None):
|
||||
"""Create a new InstallManifest entry.
|
||||
@ -103,7 +94,7 @@ class InstallManifest(object):
|
||||
|
||||
def _load_from_fileobj(self, fileobj):
|
||||
version = fileobj.readline().rstrip()
|
||||
if version not in ('1', '2', '3'):
|
||||
if version not in ('1', '2'):
|
||||
raise UnreadableInstallManifest('Unknown manifest version: ' %
|
||||
version)
|
||||
|
||||
@ -115,7 +106,7 @@ class InstallManifest(object):
|
||||
record_type = int(fields[0])
|
||||
|
||||
if record_type == self.SYMLINK:
|
||||
dest, source = fields[1:]
|
||||
dest, source= fields[1:]
|
||||
self.add_symlink(source, dest)
|
||||
continue
|
||||
|
||||
@ -134,16 +125,6 @@ class InstallManifest(object):
|
||||
self.add_optional_exists(path)
|
||||
continue
|
||||
|
||||
if record_type == self.PATTERN_SYMLINK:
|
||||
_, base, pattern, dest = fields[1:]
|
||||
self.add_pattern_symlink(base, pattern, dest)
|
||||
continue
|
||||
|
||||
if record_type == self.PATTERN_COPY:
|
||||
_, base, pattern, dest = fields[1:]
|
||||
self.add_pattern_copy(base, pattern, dest)
|
||||
continue
|
||||
|
||||
raise UnreadableInstallManifest('Unknown record type: %d' %
|
||||
record_type)
|
||||
|
||||
@ -177,7 +158,7 @@ class InstallManifest(object):
|
||||
It is an error if both are specified.
|
||||
"""
|
||||
with _auto_fileobj(path, fileobj, 'wb') as fh:
|
||||
fh.write('3\n')
|
||||
fh.write('2\n')
|
||||
|
||||
for dest in sorted(self._dests):
|
||||
entry = self._dests[dest]
|
||||
@ -217,29 +198,6 @@ class InstallManifest(object):
|
||||
"""
|
||||
self._add_entry(dest, (self.OPTIONAL_EXISTS,))
|
||||
|
||||
def add_pattern_symlink(self, base, pattern, dest):
|
||||
"""Add a pattern match that results in symlinks being created.
|
||||
|
||||
A ``FileFinder`` will be created with its base set to ``base``
|
||||
and ``FileFinder.find()`` will be called with ``pattern`` to discover
|
||||
source files. Each source file will be symlinked under ``dest``.
|
||||
|
||||
Filenames under ``dest`` are constructed by taking the path fragment
|
||||
after ``base`` and concatenating it with ``dest``. e.g.
|
||||
|
||||
<base>/foo/bar.h -> <dest>/foo/bar.h
|
||||
"""
|
||||
self._add_entry(mozpath.join(base, pattern, dest),
|
||||
(self.PATTERN_SYMLINK, base, pattern, dest))
|
||||
|
||||
def add_pattern_copy(self, base, pattern, dest):
|
||||
"""Add a pattern match that results in copies.
|
||||
|
||||
See ``add_pattern_symlink()`` for usage.
|
||||
"""
|
||||
self._add_entry(mozpath.join(base, pattern, dest),
|
||||
(self.PATTERN_COPY, base, pattern, dest))
|
||||
|
||||
def _add_entry(self, dest, entry):
|
||||
if dest in self._dests:
|
||||
raise ValueError('Item already in manifest: %s' % dest)
|
||||
@ -273,21 +231,5 @@ class InstallManifest(object):
|
||||
registry.add(dest, ExistingFile(required=False))
|
||||
continue
|
||||
|
||||
if install_type in (self.PATTERN_SYMLINK, self.PATTERN_COPY):
|
||||
_, base, pattern, dest = entry
|
||||
finder = FileFinder(base, find_executables=False)
|
||||
paths = [f[0] for f in finder.find(pattern)]
|
||||
|
||||
if install_type == self.PATTERN_SYMLINK:
|
||||
cls = AbsoluteSymlinkFile
|
||||
else:
|
||||
cls = File
|
||||
|
||||
for path in paths:
|
||||
source = mozpath.join(base, path)
|
||||
registry.add(mozpath.join(dest, path), cls(source))
|
||||
|
||||
continue
|
||||
|
||||
raise Exception('Unknown install type defined in manifest: %d' %
|
||||
install_type)
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user