mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 13:51:41 +00:00
Merge m-c to inbound.
--HG-- rename : dom/contacts/tests/test_contacts_upgrade.html => dom/contacts/tests/test_contacts_upgrade.xul rename : dom/indexedDB/test/test_globalObjects.xul => dom/indexedDB/test/test_globalObjects_chrome.xul rename : dom/indexedDB/test/test_globalObjects.html => dom/indexedDB/test/test_globalObjects_content.html rename : dom/indexedDB/test/unit/test_globalObjects.js => dom/indexedDB/test/unit/test_globalObjects_xpc.js
This commit is contained in:
commit
554a83ef67
@ -191,21 +191,22 @@ let PaymentProvider = {
|
||||
},
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
// Until bug 814629 is done, we only have support for a single SIM, so we
|
||||
// can only provide information for a single ICC. However, we return an array
|
||||
// so the payment provider facing API won't need to change once we support
|
||||
// multiple SIMs.
|
||||
// Bug 938993. Support Multi-SIM for Payments.
|
||||
get iccInfo() {
|
||||
delete this.iccInfo;
|
||||
return this.iccInfo = iccProvider.getIccInfo(0);
|
||||
},
|
||||
|
||||
get iccIds() {
|
||||
return [iccProvider.iccInfo.iccid];
|
||||
return [this.iccInfo.iccid];
|
||||
},
|
||||
|
||||
get mcc() {
|
||||
return [iccProvider.iccInfo.mcc];
|
||||
return [this.iccInfo.mcc];
|
||||
},
|
||||
|
||||
get mnc() {
|
||||
return [iccProvider.iccInfo.mnc];
|
||||
return [this.iccInfo.mnc];
|
||||
},
|
||||
|
||||
_silentNumbers: null,
|
||||
|
@ -1,4 +1,4 @@
|
||||
{
|
||||
"revision": "8ef103bc368f8309e42cffb648fa73ab756b2599",
|
||||
"revision": "4e8959a60a4ee1373e71fe31229ba5bd7575c02c",
|
||||
"repo_path": "/integration/gaia-central"
|
||||
}
|
||||
|
@ -963,6 +963,9 @@ var gPluginHandler = {
|
||||
return;
|
||||
}
|
||||
|
||||
Services.telemetry.getHistogramById("PLUGINS_INFOBAR_SHOWN").
|
||||
add(true);
|
||||
|
||||
let message;
|
||||
// Icons set directly cannot be manipulated using moz-image-region, so
|
||||
// we use CSS classes instead.
|
||||
@ -1001,21 +1004,26 @@ var gPluginHandler = {
|
||||
}
|
||||
}
|
||||
|
||||
// These strings are temporary no-string-change for branch uplift
|
||||
let buttons = [
|
||||
{
|
||||
label: gNavigatorBundle.getString("pluginBlockNow.label"),
|
||||
accessKey: gNavigatorBundle.getString("pluginBlockNow.accesskey"),
|
||||
label: gNavigatorBundle.getString("pluginContinueBlocking.label"),
|
||||
accessKey: gNavigatorBundle.getString("pluginContinueBlocking.accesskey"),
|
||||
callback: function() {
|
||||
Services.telemetry.getHistogramById("PLUGINS_INFOBAR_BLOCK").
|
||||
add(true);
|
||||
|
||||
Services.perms.addFromPrincipal(aBrowser.contentDocument.nodePrincipal,
|
||||
"plugin-hidden-notification",
|
||||
Services.perms.DENY_ACTION);
|
||||
}
|
||||
},
|
||||
{
|
||||
label: gNavigatorBundle.getString("offlineApps.allow"),
|
||||
accessKey: gNavigatorBundle.getString("offlineApps.allowAccessKey"),
|
||||
label: gNavigatorBundle.getString("pluginActivateTrigger.label"),
|
||||
accessKey: gNavigatorBundle.getString("pluginActivateTrigger.accesskey"),
|
||||
callback: function() {
|
||||
Services.telemetry.getHistogramById("PLUGINS_INFOBAR_ALLOW").
|
||||
add(true);
|
||||
|
||||
let curNotification =
|
||||
PopupNotifications.getNotification("click-to-play-plugins",
|
||||
aBrowser);
|
||||
|
@ -2071,6 +2071,12 @@ this.CustomizableUI = {
|
||||
onWidgetDrag: function(aWidgetId, aArea) {
|
||||
CustomizableUIInternal.notifyListeners("onWidgetDrag", aWidgetId, aArea);
|
||||
},
|
||||
notifyStartCustomizing: function(aWindow) {
|
||||
CustomizableUIInternal.notifyListeners("onCustomizeStart", aWindow);
|
||||
},
|
||||
notifyEndCustomizing: function(aWindow) {
|
||||
CustomizableUIInternal.notifyListeners("onCustomizeEnd", aWindow);
|
||||
},
|
||||
isAreaOverflowable: function(aAreaId) {
|
||||
let area = gAreas.get(aAreaId);
|
||||
return area ? area.get("type") == this.TYPE_TOOLBAR && area.get("overflowable")
|
||||
|
@ -111,6 +111,7 @@ CustomizeMode.prototype = {
|
||||
this.document.documentElement._lightweightTheme.disable();
|
||||
|
||||
this.dispatchToolboxEvent("beforecustomization");
|
||||
CustomizableUI.notifyStartCustomizing(this.window);
|
||||
|
||||
let window = this.window;
|
||||
let document = this.document;
|
||||
@ -285,6 +286,7 @@ CustomizeMode.prototype = {
|
||||
this._changed = false;
|
||||
this._transitioning = false;
|
||||
this.dispatchToolboxEvent("aftercustomization");
|
||||
CustomizableUI.notifyEndCustomizing(this.window);
|
||||
}.bind(this)).then(null, ERROR);
|
||||
},
|
||||
|
||||
|
@ -178,6 +178,7 @@ body {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
body.dim > #header > #element-position,
|
||||
body.dim > #main > p,
|
||||
body.dim > #main > .tooltip {
|
||||
visibility: hidden;
|
||||
|
@ -46,6 +46,9 @@ LayoutView.prototype = {
|
||||
// 'property' is what we are measuring;
|
||||
// 'value' is the computed dimension, computed in update().
|
||||
this.map = {
|
||||
position: {selector: "#element-position",
|
||||
property: "position",
|
||||
value: undefined},
|
||||
marginTop: {selector: ".margin.top > span",
|
||||
property: "margin-top",
|
||||
value: undefined},
|
||||
@ -201,7 +204,19 @@ LayoutView.prototype = {
|
||||
|
||||
for (let i in this.map) {
|
||||
let property = this.map[i].property;
|
||||
this.map[i].value = parseInt(layout[property]);
|
||||
if (!(property in layout)) {
|
||||
// Depending on the actor version, some properties
|
||||
// might be missing.
|
||||
continue;
|
||||
}
|
||||
let parsedValue = parseInt(layout[property]);
|
||||
if (Number.isNaN(parsedValue)) {
|
||||
// Not a number. We use the raw string.
|
||||
// Useful for "position" for example.
|
||||
this.map[i].value = layout[property];
|
||||
} else {
|
||||
this.map[i].value = parsedValue;
|
||||
}
|
||||
}
|
||||
|
||||
let margins = layout.autoMargins;
|
||||
|
@ -74,7 +74,7 @@
|
||||
<body class="theme-body devtools-monospace">
|
||||
|
||||
<p id="header">
|
||||
<span id="element-size"></span>
|
||||
<span id="element-size"></span><span id="element-position"></span>
|
||||
</p>
|
||||
|
||||
<div id="main">
|
||||
|
@ -229,7 +229,7 @@ CssHtmlTree.processTemplate = function CssHtmlTree_processTemplate(aTemplate,
|
||||
};
|
||||
|
||||
XPCOMUtils.defineLazyGetter(CssHtmlTree, "_strings", function() Services.strings
|
||||
.createBundle("chrome://browser/locale/devtools/styleinspector.properties"));
|
||||
.createBundle("chrome://global/locale/devtools/styleinspector.properties"));
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "clipboardHelper", function() {
|
||||
return Cc["@mozilla.org/widget/clipboardhelper;1"].
|
||||
|
@ -2446,7 +2446,7 @@ XPCOMUtils.defineLazyGetter(this, "clipboardHelper", function() {
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "_strings", function() {
|
||||
return Services.strings.createBundle(
|
||||
"chrome://browser/locale/devtools/styleinspector.properties");
|
||||
"chrome://global/locale/devtools/styleinspector.properties");
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "domUtils", function() {
|
||||
|
@ -14,7 +14,7 @@ loader.lazyGetter(this, "gDevTools", () => Cu.import("resource:///modules/devtoo
|
||||
loader.lazyGetter(this, "RuleView", () => require("devtools/styleinspector/rule-view"));
|
||||
loader.lazyGetter(this, "ComputedView", () => require("devtools/styleinspector/computed-view"));
|
||||
loader.lazyGetter(this, "_strings", () => Services.strings
|
||||
.createBundle("chrome://browser/locale/devtools/styleinspector.properties"));
|
||||
.createBundle("chrome://global/locale/devtools/styleinspector.properties"));
|
||||
|
||||
// This module doesn't currently export any symbols directly, it only
|
||||
// registers inspector tools.
|
||||
|
@ -47,7 +47,7 @@ function checkCssLogic()
|
||||
cssLogic.processMatchedSelectors();
|
||||
|
||||
let _strings = Services.strings
|
||||
.createBundle("chrome://browser/locale/devtools/styleinspector.properties");
|
||||
.createBundle("chrome://global/locale/devtools/styleinspector.properties");
|
||||
|
||||
let inline = _strings.GetStringFromName("rule.sourceInline");
|
||||
|
||||
|
@ -41,7 +41,7 @@ function checkSheets()
|
||||
let elementStyle = ruleView()._elementStyle;
|
||||
|
||||
let _strings = Services.strings
|
||||
.createBundle("chrome://browser/locale/devtools/styleinspector.properties");
|
||||
.createBundle("chrome://global/locale/devtools/styleinspector.properties");
|
||||
|
||||
let inline = _strings.GetStringFromName("rule.sourceInline");
|
||||
|
||||
|
@ -163,6 +163,14 @@ PluginClickToActivate=Activate %S.
|
||||
PluginVulnerableUpdatable=This plugin is vulnerable and should be updated.
|
||||
PluginVulnerableNoUpdate=This plugin has security vulnerabilities.
|
||||
|
||||
# infobar UI
|
||||
pluginContinueBlocking.label=Continue Blocking
|
||||
pluginContinueBlocking.accesskey=B
|
||||
# LOCALIZATION NOTE (pluginActivateTrigger): Use the unicode ellipsis char, \u2026,
|
||||
# or use "..." if \u2026 doesn't suit traditions in your locale.
|
||||
pluginActivateTrigger.label=Allow…
|
||||
pluginActivateTrigger.accesskey=A
|
||||
|
||||
# Sanitize
|
||||
# LOCALIZATION NOTE (sanitizeDialog2.everything.title): When "Time range to
|
||||
# clear" is set to "Everything", the Clear Recent History dialog's title is
|
||||
|
@ -39,7 +39,6 @@
|
||||
locale/browser/devtools/scratchpad.dtd (%chrome/browser/devtools/scratchpad.dtd)
|
||||
locale/browser/devtools/styleeditor.properties (%chrome/browser/devtools/styleeditor.properties)
|
||||
locale/browser/devtools/styleeditor.dtd (%chrome/browser/devtools/styleeditor.dtd)
|
||||
locale/browser/devtools/styleinspector.properties (%chrome/browser/devtools/styleinspector.properties)
|
||||
locale/browser/devtools/styleinspector.dtd (%chrome/browser/devtools/styleinspector.dtd)
|
||||
locale/browser/devtools/webConsole.dtd (%chrome/browser/devtools/webConsole.dtd)
|
||||
locale/browser/devtools/VariablesView.dtd (%chrome/browser/devtools/VariablesView.dtd)
|
||||
|
@ -39,30 +39,52 @@ var APZCObserver = {
|
||||
handleEvent: function APZC_handleEvent(aEvent) {
|
||||
switch (aEvent.type) {
|
||||
case 'pageshow':
|
||||
if (aEvent.target != Browser.selectedBrowser.contentDocument)
|
||||
break;
|
||||
// fall through to TabSelect:
|
||||
case 'TabSelect':
|
||||
// ROOT_ID doesn't really identify the view we want. When we call
|
||||
// this on a content document (tab), findElementWithViewId will
|
||||
// always return the root content document associated with the
|
||||
// scrollable frame.
|
||||
const ROOT_ID = 1;
|
||||
let windowUtils = Browser.selectedBrowser.contentWindow.
|
||||
QueryInterface(Ci.nsIInterfaceRequestor).
|
||||
getInterface(Ci.nsIDOMWindowUtils);
|
||||
// findElementWithViewId will throw if it can't find it
|
||||
let element;
|
||||
try {
|
||||
element = windowUtils.findElementWithViewId(ROOT_ID);
|
||||
} catch (e) {
|
||||
// Not present; nothing to do here
|
||||
if (aEvent.target != Browser.selectedBrowser.contentDocument) {
|
||||
break;
|
||||
}
|
||||
windowUtils.setDisplayPortForElement(0, 0, ContentAreaObserver.width,
|
||||
ContentAreaObserver.height,
|
||||
element);
|
||||
// intentional fall through
|
||||
case 'TabSelect': {
|
||||
// Start off with something reasonable. The apzc will handle these
|
||||
// calculations once scrolling starts.
|
||||
let doc = Browser.selectedBrowser.contentDocument.documentElement;
|
||||
// While running tests, sometimes this can be null. If we don't have a
|
||||
// root document, there's no point in setting a scrollable display port.
|
||||
if (!doc) {
|
||||
break;
|
||||
}
|
||||
let win = Browser.selectedBrowser.contentWindow;
|
||||
let factor = 0.2;
|
||||
let portX = 0;
|
||||
let portY = 0;
|
||||
let portWidth = ContentAreaObserver.width;
|
||||
let portHeight = ContentAreaObserver.height;
|
||||
|
||||
if (portWidth < doc.scrollWidth) {
|
||||
portWidth += ContentAreaObserver.width * factor;
|
||||
if (portWidth > doc.scrollWidth) {
|
||||
portWidth = doc.scrollWidth;
|
||||
}
|
||||
}
|
||||
if (portHeight < doc.scrollHeight) {
|
||||
portHeight += ContentAreaObserver.height * factor;
|
||||
if (portHeight > doc.scrollHeight) {
|
||||
portHeight = doc.scrollHeight;
|
||||
}
|
||||
}
|
||||
if (win.scrollX > 0) {
|
||||
portX -= ContentAreaObserver.width * factor;
|
||||
}
|
||||
if (win.scrollY > 0) {
|
||||
portY -= ContentAreaObserver.height * factor;
|
||||
}
|
||||
let cwu = Browser.selectedBrowser.contentWindow
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
cwu.setDisplayPortForElement(portX, portY,
|
||||
portWidth, portHeight,
|
||||
Browser.selectedBrowser.contentDocument.documentElement);
|
||||
break;
|
||||
}
|
||||
case 'TabOpen': {
|
||||
let browser = aEvent.originalTarget.linkedBrowser;
|
||||
browser.addEventListener("pageshow", this, true);
|
||||
|
@ -253,6 +253,7 @@ var SelectionHelperUI = {
|
||||
_endMark: null,
|
||||
_caretMark: null,
|
||||
_target: null,
|
||||
_showAfterUpdate: false,
|
||||
_movement: { active: false, x:0, y: 0 },
|
||||
_activeSelectionRect: null,
|
||||
_selectionMarkIds: [],
|
||||
@ -350,13 +351,29 @@ var SelectionHelperUI = {
|
||||
*/
|
||||
|
||||
observe: function (aSubject, aTopic, aData) {
|
||||
switch (aTopic) {
|
||||
case "attach_edit_session_to_content":
|
||||
let event = aSubject;
|
||||
SelectionHelperUI.attachEditSession(Browser.selectedTab.browser,
|
||||
event.clientX, event.clientY);
|
||||
break;
|
||||
}
|
||||
switch (aTopic) {
|
||||
case "attach_edit_session_to_content":
|
||||
let event = aSubject;
|
||||
this.attachEditSession(Browser.selectedTab.browser,
|
||||
event.clientX, event.clientY);
|
||||
break;
|
||||
|
||||
case "apzc-handle-pan-begin":
|
||||
if (this.isActive && this.layerMode == kContentLayer) {
|
||||
this._hideMonocles();
|
||||
}
|
||||
break;
|
||||
|
||||
case "apzc-handle-pan-end":
|
||||
// The selection range callback will check to see if the new
|
||||
// position is off the screen, in which case it shuts down and
|
||||
// clears the selection.
|
||||
if (this.isActive && this.layerMode == kContentLayer) {
|
||||
this._showAfterUpdate = true;
|
||||
this._sendAsyncMessage("Browser:SelectionUpdate", {});
|
||||
}
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
@ -530,7 +547,10 @@ var SelectionHelperUI = {
|
||||
*/
|
||||
|
||||
init: function () {
|
||||
Services.obs.addObserver(this, "attach_edit_session_to_content", false);
|
||||
let os = Services.obs;
|
||||
os.addObserver(this, "attach_edit_session_to_content", false);
|
||||
os.addObserver(this, "apzc-handle-pan-begin", false);
|
||||
os.addObserver(this, "apzc-handle-pan-end", false);
|
||||
},
|
||||
|
||||
_init: function _init(aMsgTarget) {
|
||||
@ -908,6 +928,16 @@ var SelectionHelperUI = {
|
||||
this._shutdown();
|
||||
},
|
||||
|
||||
_checkMonocleVisibility: function(aX, aY) {
|
||||
if (aX < 0 || aY < 0 ||
|
||||
aX > ContentAreaObserver.viewableWidth ||
|
||||
aY > ContentAreaObserver.viewableHeight) {
|
||||
this.closeEditSession(true);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
/*
|
||||
* Message handlers
|
||||
*/
|
||||
@ -920,26 +950,43 @@ var SelectionHelperUI = {
|
||||
let haveSelectionRect = true;
|
||||
|
||||
if (json.updateStart) {
|
||||
this.startMark.position(this._msgTarget.btocx(json.start.xPos, true),
|
||||
this._msgTarget.btocy(json.start.yPos, true));
|
||||
let x = this._msgTarget.btocx(json.start.xPos, true);
|
||||
let y = this._msgTarget.btocx(json.start.yPos, true);
|
||||
if (!this._checkMonocleVisibility(x, y)) {
|
||||
return;
|
||||
}
|
||||
this.startMark.position(x, y);
|
||||
}
|
||||
if (json.updateEnd) {
|
||||
this.endMark.position(this._msgTarget.btocx(json.end.xPos, true),
|
||||
this._msgTarget.btocy(json.end.yPos, true));
|
||||
let x = this._msgTarget.btocx(json.end.xPos, true);
|
||||
let y = this._msgTarget.btocx(json.end.yPos, true);
|
||||
if (!this._checkMonocleVisibility(x, y)) {
|
||||
return;
|
||||
}
|
||||
this.endMark.position(x, y);
|
||||
}
|
||||
|
||||
if (json.updateCaret) {
|
||||
let x = this._msgTarget.btocx(json.caret.xPos, true);
|
||||
let y = this._msgTarget.btocx(json.caret.yPos, true);
|
||||
if (!this._checkMonocleVisibility(x, y)) {
|
||||
return;
|
||||
}
|
||||
// If selectionRangeFound is set SelectionHelper found a range we can
|
||||
// attach to. If not, there's no text in the control, and hence no caret
|
||||
// position information we can use.
|
||||
haveSelectionRect = json.selectionRangeFound;
|
||||
if (json.selectionRangeFound) {
|
||||
this.caretMark.position(this._msgTarget.btocx(json.caret.xPos, true),
|
||||
this._msgTarget.btocy(json.caret.yPos, true));
|
||||
this.caretMark.position(x, y);
|
||||
this.caretMark.show();
|
||||
}
|
||||
}
|
||||
|
||||
if (this._showAfterUpdate) {
|
||||
this._showAfterUpdate = false;
|
||||
this._showMonocles(!json.updateCaret);
|
||||
}
|
||||
|
||||
this._targetIsEditable = json.targetIsEditable;
|
||||
this._activeSelectionRect = haveSelectionRect ?
|
||||
this._msgTarget.rectBrowserToClient(json.selection, true) :
|
||||
|
@ -38,7 +38,7 @@
|
||||
background-color: -moz-Dialog;
|
||||
}
|
||||
|
||||
#navigator-toolbox > toolbar:not(#toolbar-menubar):not(#TabsToolbar) {
|
||||
#navigator-toolbox > toolbar:not(#toolbar-menubar):not(#TabsToolbar):not(#nav-bar) {
|
||||
padding-top: 1px;
|
||||
padding-bottom: 1px;
|
||||
}
|
||||
|
@ -961,7 +961,7 @@ MediaDecoder::GetStatistics()
|
||||
double MediaDecoder::ComputePlaybackRate(bool* aReliable)
|
||||
{
|
||||
GetReentrantMonitor().AssertCurrentThreadIn();
|
||||
MOZ_ASSERT(NS_IsMainThread() || OnStateMachineThread());
|
||||
MOZ_ASSERT(NS_IsMainThread() || OnStateMachineThread() || OnDecodeThread());
|
||||
|
||||
int64_t length = mResource ? mResource->GetLength() : -1;
|
||||
if (mDuration >= 0 && length >= 0) {
|
||||
|
@ -1829,52 +1829,44 @@ bool MediaDecoderStateMachine::HasLowDecodedData(int64_t aAudioUsecs) const
|
||||
AssertCurrentThreadInMonitor();
|
||||
// We consider ourselves low on decoded data if we're low on audio,
|
||||
// provided we've not decoded to the end of the audio stream, or
|
||||
// if we're only playing video and we're low on video frames, provided
|
||||
// if we're low on video frames, provided
|
||||
// we've not decoded to the end of the video stream.
|
||||
return ((HasAudio() &&
|
||||
!mReader->AudioQueue().IsFinished() &&
|
||||
AudioDecodedUsecs() < aAudioUsecs)
|
||||
||
|
||||
(!HasAudio() &&
|
||||
HasVideo() &&
|
||||
(HasVideo() &&
|
||||
!mReader->VideoQueue().IsFinished() &&
|
||||
static_cast<uint32_t>(mReader->VideoQueue().GetSize()) < LOW_VIDEO_FRAMES));
|
||||
}
|
||||
|
||||
bool MediaDecoderStateMachine::HasLowUndecodedData() const
|
||||
{
|
||||
return GetUndecodedData() < mLowDataThresholdUsecs;
|
||||
return HasLowUndecodedData(mLowDataThresholdUsecs);
|
||||
}
|
||||
|
||||
int64_t MediaDecoderStateMachine::GetUndecodedData() const
|
||||
bool MediaDecoderStateMachine::HasLowUndecodedData(double aUsecs) const
|
||||
{
|
||||
AssertCurrentThreadInMonitor();
|
||||
NS_ASSERTION(mState > DECODER_STATE_DECODING_METADATA,
|
||||
"Must have loaded metadata for GetBuffered() to work");
|
||||
dom::TimeRanges buffered;
|
||||
|
||||
nsresult res = mDecoder->GetBuffered(&buffered);
|
||||
NS_ENSURE_SUCCESS(res, 0);
|
||||
double currentTime = GetCurrentTime();
|
||||
|
||||
nsIDOMTimeRanges* r = static_cast<nsIDOMTimeRanges*>(&buffered);
|
||||
uint32_t length = 0;
|
||||
res = r->GetLength(&length);
|
||||
NS_ENSURE_SUCCESS(res, 0);
|
||||
|
||||
for (uint32_t index = 0; index < length; ++index) {
|
||||
double start, end;
|
||||
res = r->Start(index, &start);
|
||||
NS_ENSURE_SUCCESS(res, 0);
|
||||
|
||||
res = r->End(index, &end);
|
||||
NS_ENSURE_SUCCESS(res, 0);
|
||||
|
||||
if (start <= currentTime && end >= currentTime) {
|
||||
return static_cast<int64_t>((end - currentTime) * USECS_PER_S);
|
||||
}
|
||||
bool reliable;
|
||||
double bytesPerSecond = mDecoder->ComputePlaybackRate(&reliable);
|
||||
if (!reliable) {
|
||||
// Default to assuming we have enough
|
||||
return false;
|
||||
}
|
||||
return 0;
|
||||
|
||||
MediaResource* stream = mDecoder->GetResource();
|
||||
int64_t currentPos = stream->Tell();
|
||||
int64_t requiredPos = currentPos + int64_t((aUsecs/1000000.0)*bytesPerSecond);
|
||||
int64_t length = stream->GetLength();
|
||||
if (length >= 0) {
|
||||
requiredPos = std::min(requiredPos, length);
|
||||
}
|
||||
|
||||
return stream->GetCachedDataEnd(currentPos) < requiredPos;
|
||||
}
|
||||
|
||||
void MediaDecoderStateMachine::SetFrameBufferLength(uint32_t aLength)
|
||||
@ -2282,14 +2274,13 @@ nsresult MediaDecoderStateMachine::RunStateMachine()
|
||||
if ((isLiveStream || !mDecoder->CanPlayThrough()) &&
|
||||
elapsed < TimeDuration::FromSeconds(mBufferingWait * mPlaybackRate) &&
|
||||
(mQuickBuffering ? HasLowDecodedData(QUICK_BUFFERING_LOW_DATA_USECS)
|
||||
: (GetUndecodedData() < mBufferingWait * mPlaybackRate * USECS_PER_S)) &&
|
||||
: HasLowUndecodedData(mBufferingWait * USECS_PER_S)) &&
|
||||
!mDecoder->IsDataCachedToEndOfResource() &&
|
||||
!resource->IsSuspended())
|
||||
{
|
||||
LOG(PR_LOG_DEBUG,
|
||||
("%p Buffering: %.3lfs/%ds, timeout in %.3lfs %s",
|
||||
("%p Buffering: wait %ds, timeout in %.3lfs %s",
|
||||
mDecoder.get(),
|
||||
GetUndecodedData() / static_cast<double>(USECS_PER_S),
|
||||
mBufferingWait,
|
||||
mBufferingWait - elapsed.ToSeconds(),
|
||||
(mQuickBuffering ? "(quick exit)" : "")));
|
||||
@ -2528,15 +2519,15 @@ void MediaDecoderStateMachine::AdvanceFrame()
|
||||
mDecoder->GetState() == MediaDecoder::PLAY_STATE_PLAYING &&
|
||||
HasLowDecodedData(remainingTime + EXHAUSTED_DATA_MARGIN_USECS) &&
|
||||
!mDecoder->IsDataCachedToEndOfResource() &&
|
||||
!resource->IsSuspended() &&
|
||||
(JustExitedQuickBuffering() || HasLowUndecodedData()))
|
||||
{
|
||||
if (currentFrame) {
|
||||
mReader->VideoQueue().PushFront(currentFrame.forget());
|
||||
!resource->IsSuspended()) {
|
||||
if (JustExitedQuickBuffering() || HasLowUndecodedData()) {
|
||||
if (currentFrame) {
|
||||
mReader->VideoQueue().PushFront(currentFrame.forget());
|
||||
}
|
||||
StartBuffering();
|
||||
ScheduleStateMachine();
|
||||
return;
|
||||
}
|
||||
StartBuffering();
|
||||
ScheduleStateMachine();
|
||||
return;
|
||||
}
|
||||
|
||||
// We've got enough data to keep playing until at least the next frame.
|
||||
|
@ -394,9 +394,8 @@ private:
|
||||
// The decoder monitor must be held.
|
||||
bool HasLowUndecodedData() const;
|
||||
|
||||
// Returns the number of microseconds of undecoded data available for
|
||||
// decoding. The decoder monitor must be held.
|
||||
int64_t GetUndecodedData() const;
|
||||
// Returns true if we have less than aUsecs of undecoded data available.
|
||||
bool HasLowUndecodedData(double aUsecs) const;
|
||||
|
||||
// Returns the number of unplayed usecs of audio we've got decoded and/or
|
||||
// pushed to the hardware waiting to play. This is how much audio we can
|
||||
|
@ -82,7 +82,6 @@ public:
|
||||
v.get_ArrayOfBluetoothNamedValue();
|
||||
|
||||
nsTArray<nsRefPtr<BluetoothDevice> > devices;
|
||||
JSObject* JsDevices;
|
||||
for (uint32_t i = 0; i < values.Length(); i++) {
|
||||
const BluetoothValue properties = values[i].value();
|
||||
if (properties.type() != BluetoothValue::TArrayOfBluetoothNamedValue) {
|
||||
@ -106,6 +105,7 @@ public:
|
||||
}
|
||||
|
||||
AutoPushJSContext cx(sc->GetNativeContext());
|
||||
JSObject* JsDevices = nullptr;
|
||||
rv = nsTArrayToJSArray(cx, devices, &JsDevices);
|
||||
if (!JsDevices) {
|
||||
BT_WARNING("Cannot create JS array!");
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -7,11 +7,12 @@
|
||||
#ifndef mozilla_dom_bluetooth_bluetoothhfpmanager_h__
|
||||
#define mozilla_dom_bluetooth_bluetoothhfpmanager_h__
|
||||
|
||||
#include <hardware/bluetooth.h>
|
||||
#include <hardware/bt_hf.h>
|
||||
|
||||
#include "BluetoothCommon.h"
|
||||
#include "BluetoothProfileManagerBase.h"
|
||||
#ifdef MOZ_B2G_RIL
|
||||
#include "BluetoothRilListener.h"
|
||||
#endif
|
||||
#include "BluetoothSocketObserver.h"
|
||||
#include "mozilla/ipc/UnixSocket.h"
|
||||
#include "mozilla/Hal.h"
|
||||
@ -20,8 +21,6 @@ BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
class BluetoothReplyRunnable;
|
||||
class BluetoothSocket;
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
class Call;
|
||||
|
||||
/**
|
||||
@ -67,14 +66,12 @@ public:
|
||||
bool IsActive();
|
||||
|
||||
uint16_t mState;
|
||||
bool mDirection; // true: incoming call; false: outgoing call
|
||||
nsString mNumber;
|
||||
int mType;
|
||||
bthf_call_direction_t mDirection; // 0: outgoing call; 1: incoming call
|
||||
bthf_call_addrtype_t mType;
|
||||
};
|
||||
#endif // MOZ_B2G_RIL
|
||||
|
||||
class BluetoothHfpManager : public BluetoothSocketObserver
|
||||
, public BluetoothProfileManagerBase
|
||||
class BluetoothHfpManager : public BluetoothProfileManagerBase
|
||||
, public BatteryObserver
|
||||
{
|
||||
public:
|
||||
@ -89,21 +86,10 @@ public:
|
||||
static BluetoothHfpManager* Get();
|
||||
~BluetoothHfpManager();
|
||||
|
||||
// The following functions are inherited from BluetoothSocketObserver
|
||||
virtual void ReceiveSocketData(
|
||||
BluetoothSocket* aSocket,
|
||||
nsAutoPtr<mozilla::ipc::UnixSocketRawData>& aMessage) MOZ_OVERRIDE;
|
||||
virtual void OnSocketConnectSuccess(BluetoothSocket* aSocket) MOZ_OVERRIDE;
|
||||
virtual void OnSocketConnectError(BluetoothSocket* aSocket) MOZ_OVERRIDE;
|
||||
virtual void OnSocketDisconnect(BluetoothSocket* aSocket) MOZ_OVERRIDE;
|
||||
|
||||
bool Listen();
|
||||
bool ConnectSco(BluetoothReplyRunnable* aRunnable = nullptr);
|
||||
bool ConnectSco();
|
||||
bool DisconnectSco();
|
||||
bool ListenSco();
|
||||
bool IsScoConnected();
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
/**
|
||||
* @param aSend A boolean indicates whether we need to notify headset or not
|
||||
*/
|
||||
@ -113,106 +99,89 @@ public:
|
||||
void HandleIccInfoChanged();
|
||||
void HandleVoiceConnectionChanged();
|
||||
|
||||
// Bluedroid hfp callback handlers
|
||||
void ProcessConnectionState(bthf_connection_state_t aState, bt_bdaddr_t* aBdAddress);
|
||||
void ProcessAudioState(bthf_audio_state_t aState, bt_bdaddr_t* aBdAddress);
|
||||
void ProcessAnswerCall();
|
||||
void ProcessHangupCall();
|
||||
void ProcessVolumeControl(bthf_volume_type_t aType, int aVolume);
|
||||
void ProcessDialCall(char *aNumber);
|
||||
void ProcessDtmfCmd(char aDtmf);
|
||||
void ProcessAtChld(bthf_chld_type_t aChld);
|
||||
void ProcessAtCnum();
|
||||
void ProcessAtCind();
|
||||
void ProcessAtCops();
|
||||
void ProcessAtClcc();
|
||||
void ProcessUnknownAt(char *aAtString);
|
||||
|
||||
// CDMA-specific functions
|
||||
void UpdateSecondNumber(const nsAString& aNumber);
|
||||
void AnswerWaitingCall();
|
||||
void IgnoreWaitingCall();
|
||||
void ToggleCalls();
|
||||
#endif
|
||||
|
||||
private:
|
||||
class CloseScoTask;
|
||||
class GetVolumeTask;
|
||||
#ifdef MOZ_B2G_RIL
|
||||
class CloseScoTask;
|
||||
class RespondToBLDNTask;
|
||||
class SendRingIndicatorTask;
|
||||
#endif
|
||||
class MainThreadTask;
|
||||
|
||||
friend class CloseScoTask;
|
||||
friend class GetVolumeTask;
|
||||
#ifdef MOZ_B2G_RIL
|
||||
friend class RespondToBLDNTask;
|
||||
friend class SendRingIndicatorTask;
|
||||
#endif
|
||||
friend class BluetoothHfpManagerObserver;
|
||||
friend class GetVolumeTask;
|
||||
friend class CloseScoTask;
|
||||
friend class RespondToBLDNTask;
|
||||
friend class MainThreadTask;
|
||||
|
||||
BluetoothHfpManager();
|
||||
bool Init();
|
||||
bool InitHfpInterface();
|
||||
void DeinitHfpInterface();
|
||||
void Reset();
|
||||
|
||||
void HandleShutdown();
|
||||
void HandleVolumeChanged(const nsAString& aData);
|
||||
|
||||
bool Init();
|
||||
void Notify(const hal::BatteryInformation& aBatteryInfo);
|
||||
void Reset();
|
||||
#ifdef MOZ_B2G_RIL
|
||||
|
||||
void NotifyConnectionStateChanged(const nsAString& aType);
|
||||
void NotifyDialer(const nsAString& aCommand);
|
||||
|
||||
PhoneType GetPhoneType(const nsAString& aType);
|
||||
void ResetCallArray();
|
||||
uint32_t FindFirstCall(uint16_t aState);
|
||||
uint32_t GetNumberOfCalls(uint16_t aState);
|
||||
PhoneType GetPhoneType(const nsAString& aType);
|
||||
#endif
|
||||
bthf_call_state_t ConvertToBthfCallState(int aCallState);
|
||||
|
||||
void NotifyConnectionStatusChanged(const nsAString& aType);
|
||||
void NotifyDialer(const nsAString& aCommand);
|
||||
void UpdatePhoneCIND(uint32_t aCallIndex, bool aSend = true);
|
||||
void UpdateDeviceCIND();
|
||||
void SendCLCC(Call& aCall, int aIndex);
|
||||
void SendLine(const char* aMessage);
|
||||
void SendResponse(bthf_at_response_t aResponseCode);
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
void SendCCWA(const nsAString& aNumber, int aType);
|
||||
bool SendCLCC(const Call& aCall, int aIndex);
|
||||
#endif
|
||||
bool SendCommand(const char* aCommand, uint32_t aValue = 0);
|
||||
bool SendLine(const char* aMessage);
|
||||
#ifdef MOZ_B2G_RIL
|
||||
void UpdateCIND(uint8_t aType, uint8_t aValue, bool aSend = true);
|
||||
#endif
|
||||
void OnScoConnectSuccess();
|
||||
void OnScoConnectError();
|
||||
void OnScoDisconnect();
|
||||
int mConnectionState;
|
||||
int mAudioState;
|
||||
// Phone CIND
|
||||
int mCallSetupState;
|
||||
// Device CIND
|
||||
int mBattChg;
|
||||
int mService;
|
||||
int mRoam;
|
||||
int mSignal;
|
||||
|
||||
int mCurrentVgs;
|
||||
int mCurrentVgm;
|
||||
#ifdef MOZ_B2G_RIL
|
||||
bool mBSIR;
|
||||
bool mCCWA;
|
||||
bool mCLIP;
|
||||
#endif
|
||||
bool mCMEE;
|
||||
bool mCMER;
|
||||
#ifdef MOZ_B2G_RIL
|
||||
bool mFirstCKPD;
|
||||
int mNetworkSelectionMode;
|
||||
PhoneType mPhoneType;
|
||||
#endif
|
||||
bool mReceiveVgsFlag;
|
||||
#ifdef MOZ_B2G_RIL
|
||||
bool mDialingRequestProcessed;
|
||||
#endif
|
||||
PhoneType mPhoneType;
|
||||
nsString mDeviceAddress;
|
||||
#ifdef MOZ_B2G_RIL
|
||||
nsString mMsisdn;
|
||||
nsString mOperatorName;
|
||||
|
||||
nsTArray<Call> mCurrentCallArray;
|
||||
nsAutoPtr<BluetoothRilListener> mListener;
|
||||
#endif
|
||||
nsRefPtr<BluetoothProfileController> mController;
|
||||
nsRefPtr<BluetoothReplyRunnable> mScoRunnable;
|
||||
|
||||
// If a connection has been established, mSocket will be the socket
|
||||
// communicating with the remote socket. We maintain the invariant that if
|
||||
// mSocket is non-null, mHandsfreeSocket and mHeadsetSocket must be null (and
|
||||
// vice versa).
|
||||
nsRefPtr<BluetoothSocket> mSocket;
|
||||
|
||||
// Server sockets. Once an inbound connection is established, it will hand
|
||||
// over the ownership to mSocket, and get a new server socket while Listen()
|
||||
// is called.
|
||||
nsRefPtr<BluetoothSocket> mHandsfreeSocket;
|
||||
nsRefPtr<BluetoothSocket> mHeadsetSocket;
|
||||
nsRefPtr<BluetoothSocket> mScoSocket;
|
||||
SocketConnectionStatus mScoSocketStatus;
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
// CDMA-specific variable
|
||||
Call mCdmaSecondCall;
|
||||
#endif
|
||||
};
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
@ -18,7 +18,6 @@
|
||||
|
||||
#include "BluetoothServiceBluedroid.h"
|
||||
|
||||
#include <hardware/bluetooth.h>
|
||||
#include <hardware/hardware.h>
|
||||
|
||||
#include "BluetoothProfileController.h"
|
||||
@ -32,8 +31,6 @@ using namespace mozilla;
|
||||
using namespace mozilla::ipc;
|
||||
USING_BLUETOOTH_NAMESPACE
|
||||
|
||||
typedef char bdstr_t[18];
|
||||
|
||||
/**
|
||||
* Classes only used in this file
|
||||
*/
|
||||
@ -159,39 +156,31 @@ ClassToIcon(uint32_t aClass, nsAString& aRetIcon)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
AdapterStateChangeCallback(bt_state_t aStatus)
|
||||
static bool
|
||||
IsReady()
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
|
||||
BT_LOGD("%s, BT_STATE:%d", __FUNCTION__, aStatus);
|
||||
nsAutoString signalName;
|
||||
if (aStatus == BT_STATE_ON) {
|
||||
sIsBtEnabled = true;
|
||||
signalName = NS_LITERAL_STRING("AdapterAdded");
|
||||
// by default bluetooth scan mode is NONE
|
||||
bt_property_t prop;
|
||||
prop.type = BT_PROPERTY_ADAPTER_SCAN_MODE;
|
||||
bt_scan_mode_t mode = BT_SCAN_MODE_CONNECTABLE;
|
||||
prop.val = (void*) &mode;
|
||||
prop.len = sizeof(mode);
|
||||
if (sBtInterface) {
|
||||
int ret = sBtInterface->set_adapter_property(&prop);
|
||||
if (ret != BT_STATUS_SUCCESS) {
|
||||
BT_LOGR("Warning! Fail to set property to BT_SCAN_MODE_CONNECTABLE");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
sIsBtEnabled = false;
|
||||
signalName = NS_LITERAL_STRING("Disabled");
|
||||
if (!sBtInterface || !sIsBtEnabled) {
|
||||
BT_LOGR("Warning! Bluetooth Service is not ready");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
BluetoothSignal signal(signalName, NS_LITERAL_STRING(KEY_MANAGER),
|
||||
BluetoothValue(true));
|
||||
nsRefPtr<DistributeBluetoothSignalTask>
|
||||
t = new DistributeBluetoothSignalTask(signal);
|
||||
if (NS_FAILED(NS_DispatchToMainThread(t))) {
|
||||
NS_WARNING("Failed to dispatch to main thread!");
|
||||
const bt_interface_t*
|
||||
GetBluetoothInterface()
|
||||
{
|
||||
return (IsReady()) ? sBtInterface : nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
StringToBdAddressType(const nsAString& aBdAddress,
|
||||
bt_bdaddr_t *aRetBdAddressType)
|
||||
{
|
||||
const char* str = NS_ConvertUTF16toUTF8(aBdAddress).get();
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
aRetBdAddressType->address[i] = (uint8_t) strtoul(str, (char **)&str, 16);
|
||||
str++;
|
||||
}
|
||||
}
|
||||
|
||||
@ -208,25 +197,47 @@ BdAddressTypeToString(bt_bdaddr_t* aBdAddressType, nsAString& aRetBdAddress)
|
||||
aRetBdAddress = NS_ConvertUTF8toUTF16((char*)bdstr);
|
||||
}
|
||||
|
||||
static bool
|
||||
IsReady()
|
||||
static void
|
||||
Setup()
|
||||
{
|
||||
if (!sBtInterface || !sIsBtEnabled) {
|
||||
BT_LOGR("Warning! Bluetooth Service is not ready");
|
||||
return false;
|
||||
// Bluetooth scan mode is NONE by default
|
||||
bt_scan_mode_t mode = BT_SCAN_MODE_CONNECTABLE;
|
||||
bt_property_t prop;
|
||||
prop.type = BT_PROPERTY_ADAPTER_SCAN_MODE;
|
||||
prop.val = (void*)&mode;
|
||||
prop.len = sizeof(mode);
|
||||
|
||||
NS_ENSURE_TRUE_VOID(sBtInterface);
|
||||
|
||||
int ret = sBtInterface->set_adapter_property(&prop);
|
||||
if (ret != BT_STATUS_SUCCESS) {
|
||||
BT_LOGR("%s: Fail to set: BT_SCAN_MODE_CONNECTABLE", __FUNCTION__);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
StringToBdAddressType(const nsAString& aBdAddress,
|
||||
bt_bdaddr_t *aRetBdAddressType)
|
||||
AdapterStateChangeCallback(bt_state_t aStatus)
|
||||
{
|
||||
const char* str = NS_ConvertUTF16toUTF8(aBdAddress).get();
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
aRetBdAddressType->address[i] = (uint8_t) strtoul(str, (char **)&str, 16);
|
||||
str++;
|
||||
BT_LOGR("%s, BT_STATE:%d", __FUNCTION__, aStatus);
|
||||
|
||||
nsAutoString signalName;
|
||||
if (aStatus == BT_STATE_ON) {
|
||||
Setup();
|
||||
sIsBtEnabled = true;
|
||||
signalName = NS_LITERAL_STRING("AdapterAdded");
|
||||
} else {
|
||||
sIsBtEnabled = false;
|
||||
signalName = NS_LITERAL_STRING("Disabled");
|
||||
}
|
||||
|
||||
BluetoothSignal signal(signalName, NS_LITERAL_STRING(KEY_MANAGER),
|
||||
BluetoothValue(true));
|
||||
nsRefPtr<DistributeBluetoothSignalTask>
|
||||
t = new DistributeBluetoothSignalTask(signal);
|
||||
if (NS_FAILED(NS_DispatchToMainThread(t))) {
|
||||
NS_WARNING("Failed to dispatch to main thread!");
|
||||
}
|
||||
}
|
||||
|
||||
@ -525,12 +536,13 @@ BondStateChangedCallback(bt_status_t aStatus, bt_bdaddr_t* aRemoteBdAddress,
|
||||
|
||||
nsAutoString remoteAddress;
|
||||
BdAddressTypeToString(aRemoteBdAddress, remoteAddress);
|
||||
bool bonded;
|
||||
|
||||
if (aState == BT_BOND_STATE_BONDING) {
|
||||
// We don't need to handle bonding state
|
||||
return;
|
||||
} else if (aState == BT_BOND_STATE_NONE) {
|
||||
// We don't need to handle bonding state
|
||||
NS_ENSURE_TRUE_VOID(aState != BT_BOND_STATE_BONDING);
|
||||
NS_ENSURE_FALSE_VOID(aState == BT_BOND_STATE_BONDED &&
|
||||
sAdapterBondedAddressArray.Contains(remoteAddress));
|
||||
bool bonded;
|
||||
if (aState == BT_BOND_STATE_NONE) {
|
||||
bonded = false;
|
||||
sAdapterBondedAddressArray.RemoveElement(remoteAddress);
|
||||
} else if (aState == BT_BOND_STATE_BONDED) {
|
||||
@ -731,9 +743,21 @@ BluetoothServiceBluedroid::GetDefaultAdapterPathInternal(
|
||||
nsRefPtr<BluetoothReplyRunnable> runnable(aRunnable);
|
||||
|
||||
BluetoothValue v = InfallibleTArray<BluetoothNamedValue>();
|
||||
|
||||
v.get_ArrayOfBluetoothNamedValue().AppendElement(
|
||||
BluetoothNamedValue(NS_LITERAL_STRING("Address"), sAdapterBdAddress));
|
||||
|
||||
v.get_ArrayOfBluetoothNamedValue().AppendElement(
|
||||
BluetoothNamedValue(NS_LITERAL_STRING("Name"), sAdapterBdName));
|
||||
|
||||
v.get_ArrayOfBluetoothNamedValue().AppendElement(
|
||||
BluetoothNamedValue(NS_LITERAL_STRING("Discoverable"),
|
||||
sAdapterDiscoverable));
|
||||
|
||||
v.get_ArrayOfBluetoothNamedValue().AppendElement(
|
||||
BluetoothNamedValue(NS_LITERAL_STRING("DiscoverableTimeout"),
|
||||
sAdapterDiscoverableTimeout));
|
||||
|
||||
v.get_ArrayOfBluetoothNamedValue().AppendElement(
|
||||
BluetoothNamedValue(NS_LITERAL_STRING("Devices"),
|
||||
sAdapterBondedAddressArray));
|
||||
|
@ -7,9 +7,20 @@
|
||||
#ifndef mozilla_dom_bluetooth_bluetoothservicebluedroid_h__
|
||||
#define mozilla_dom_bluetooth_bluetoothservicebluedroid_h__
|
||||
|
||||
#include <hardware/bluetooth.h>
|
||||
|
||||
#include "BluetoothCommon.h"
|
||||
#include "BluetoothService.h"
|
||||
|
||||
typedef char bdstr_t[18];
|
||||
|
||||
const bt_interface_t*
|
||||
GetBluetoothInterface();
|
||||
|
||||
void
|
||||
StringToBdAddressType(const nsAString& aBdAddress,
|
||||
bt_bdaddr_t *aRetBdAddressType);
|
||||
|
||||
class DBusMessage;
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
@ -174,6 +174,7 @@ static nsRefPtr<RawDBusConnection> gThreadConnection;
|
||||
static nsDataHashtable<nsStringHashKey, DBusMessage* >* sPairingReqTable;
|
||||
static nsTArray<uint32_t> sAuthorizedServiceClass;
|
||||
static nsString sAdapterPath;
|
||||
static bool sAdapterNameIsReady = false;
|
||||
static Atomic<int32_t> sIsPairing(0);
|
||||
static int sConnectedDeviceCount = 0;
|
||||
static StaticAutoPtr<Monitor> sStopBluetoothMonitor;
|
||||
@ -700,6 +701,20 @@ GetProperty(DBusMessageIter aIter, Properties* aPropertyTypes,
|
||||
nsString& data = propertyValue.get_ArrayOfnsString()[i];
|
||||
data = GetAddressFromObjectPath(data);
|
||||
}
|
||||
} else if (!sAdapterNameIsReady &&
|
||||
aPropertyTypes == sAdapterProperties &&
|
||||
propertyName.EqualsLiteral("Name")) {
|
||||
MOZ_ASSERT(propertyValue.type() == BluetoothValue::TnsString);
|
||||
|
||||
// Notify BluetoothManager whenever adapter name is ready.
|
||||
if (!propertyValue.get_nsString().IsEmpty()) {
|
||||
sAdapterNameIsReady = true;
|
||||
BluetoothSignal signal(NS_LITERAL_STRING("AdapterAdded"),
|
||||
NS_LITERAL_STRING(KEY_MANAGER), sAdapterPath);
|
||||
nsRefPtr<DistributeBluetoothSignalTask> task =
|
||||
new DistributeBluetoothSignalTask(signal);
|
||||
NS_DispatchToMainThread(task);
|
||||
}
|
||||
}
|
||||
|
||||
aProperties.AppendElement(BluetoothNamedValue(propertyName, propertyValue));
|
||||
@ -1534,6 +1549,13 @@ EventFilter(DBusConnection* aConn, DBusMessage* aMsg, void* aData)
|
||||
} else {
|
||||
v = NS_ConvertUTF8toUTF16(str);
|
||||
NS_DispatchToMainThread(new PrepareAdapterRunnable(v.get_nsString()));
|
||||
|
||||
/**
|
||||
* The adapter name isn't ready for the time being. Wait for the upcoming
|
||||
* signal PropertyChanged of adapter name, and then propagate signal
|
||||
* AdapterAdded to BluetoothManager.
|
||||
*/
|
||||
return DBUS_HANDLER_RESULT_HANDLED;
|
||||
}
|
||||
} else if (dbus_message_is_signal(aMsg, DBUS_MANAGER_IFACE,
|
||||
"PropertyChanged")) {
|
||||
@ -1773,6 +1795,8 @@ BluetoothDBusService::StopInternal()
|
||||
sAuthorizedServiceClass.Clear();
|
||||
sControllerArray.Clear();
|
||||
|
||||
sAdapterNameIsReady = false;
|
||||
|
||||
StopDBus();
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -10,11 +10,28 @@
|
||||
|
||||
USING_INDEXEDDB_NAMESPACE
|
||||
|
||||
namespace {
|
||||
|
||||
class CleanupFileRunnable MOZ_FINAL : public nsIRunnable
|
||||
{
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIRUNNABLE
|
||||
|
||||
CleanupFileRunnable(FileManager* aFileManager, int64_t aFileId);
|
||||
|
||||
private:
|
||||
nsRefPtr<FileManager> mFileManager;
|
||||
int64_t mFileId;
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
// static
|
||||
FileInfo*
|
||||
FileInfo::Create(FileManager* aFileManager, int64_t aId)
|
||||
{
|
||||
NS_ASSERTION(aId > 0, "Wrong id!");
|
||||
MOZ_ASSERT(aId > 0, "Wrong id!");
|
||||
|
||||
if (aId <= INT16_MAX) {
|
||||
return new FileInfo16(aFileManager, aId);
|
||||
@ -98,16 +115,40 @@ FileInfo::UpdateReferences(mozilla::ThreadSafeAutoRefCnt& aRefCount,
|
||||
void
|
||||
FileInfo::Cleanup()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
nsRefPtr<CleanupFileRunnable> cleaner =
|
||||
new CleanupFileRunnable(mFileManager, Id());
|
||||
|
||||
if (quota::QuotaManager::IsShuttingDown()) {
|
||||
// IndexedDatabaseManager is main-thread only.
|
||||
if (!NS_IsMainThread()) {
|
||||
NS_DispatchToMainThread(cleaner);
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<IndexedDatabaseManager> mgr = IndexedDatabaseManager::Get();
|
||||
NS_ASSERTION(mgr, "Shouldn't be null!");
|
||||
cleaner->Run();
|
||||
}
|
||||
|
||||
if (NS_FAILED(mgr->AsyncDeleteFile(mFileManager, Id()))) {
|
||||
CleanupFileRunnable::CleanupFileRunnable(FileManager* aFileManager,
|
||||
int64_t aFileId)
|
||||
: mFileManager(aFileManager), mFileId(aFileId)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS1(CleanupFileRunnable,
|
||||
nsIRunnable)
|
||||
|
||||
NS_IMETHODIMP
|
||||
CleanupFileRunnable::Run()
|
||||
{
|
||||
if (mozilla::dom::quota::QuotaManager::IsShuttingDown()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsRefPtr<IndexedDatabaseManager> mgr = IndexedDatabaseManager::Get();
|
||||
MOZ_ASSERT(mgr);
|
||||
|
||||
if (NS_FAILED(mgr->AsyncDeleteFile(mFileManager, mFileId))) {
|
||||
NS_WARNING("Failed to delete file asynchronously!");
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -344,7 +344,6 @@ IndexedDBDatabaseChild::EnsureDatabase(
|
||||
void
|
||||
IndexedDBDatabaseChild::ActorDestroy(ActorDestroyReason aWhy)
|
||||
{
|
||||
MOZ_ASSERT(!mStrongDatabase);
|
||||
if (mDatabase) {
|
||||
mDatabase->SetActor(static_cast<IndexedDBDatabaseChild*>(NULL));
|
||||
#ifdef DEBUG
|
||||
|
98
dom/indexedDB/test/blob_worker_crash_iframe.html
Normal file
98
dom/indexedDB/test/blob_worker_crash_iframe.html
Normal file
@ -0,0 +1,98 @@
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>Indexed Database Test</title>
|
||||
|
||||
<script type="text/javascript">
|
||||
function report(result) {
|
||||
var message = { source: "iframe" };
|
||||
message.result = result;
|
||||
window.parent.postMessage(message, "*");
|
||||
}
|
||||
|
||||
function runIndexedDBTest() {
|
||||
var db = null;
|
||||
|
||||
// Create the data-store
|
||||
function createDatastore() {
|
||||
try {
|
||||
var request = indexedDB.open(window.location.pathname, 1);
|
||||
request.onupgradeneeded = function(event) {
|
||||
event.target.result.createObjectStore("foo");
|
||||
}
|
||||
request.onsuccess = function(event) {
|
||||
db = event.target.result;
|
||||
createAndStoreBlob();
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
dump("EXCEPTION IN CREATION: " + e + "\n " + e.stack + "\n");
|
||||
report(false);
|
||||
}
|
||||
}
|
||||
|
||||
function createAndStoreBlob() {
|
||||
const BLOB_DATA = ["fun ", "times ", "all ", "around!"];
|
||||
var blob = new Blob(BLOB_DATA, { type: "text/plain" });
|
||||
var objectStore = db.transaction("foo", "readwrite").objectStore("foo");
|
||||
objectStore.add({ blob: blob }, 42).onsuccess = refetchBlob;
|
||||
}
|
||||
|
||||
function refetchBlob() {
|
||||
var foo = db.transaction("foo").objectStore("foo");
|
||||
foo.get(42).onsuccess = fetchedBlobCreateWorkerAndSendBlob;
|
||||
}
|
||||
|
||||
function fetchedBlobCreateWorkerAndSendBlob(event) {
|
||||
var idbBlob = event.target.result.blob;
|
||||
var compositeBlob = new Blob(['I like the following blob: ', idbBlob],
|
||||
{ type: "text/fancy" });
|
||||
|
||||
function workerScript() {
|
||||
onmessage = function(event) {
|
||||
// Save the Blob to the worker's global scope.
|
||||
self.holdOntoBlob = event.data;
|
||||
// Send any message so we can serialize and keep our runtime behaviour
|
||||
// consistent.
|
||||
postMessage('kung fu death grip established');
|
||||
}
|
||||
}
|
||||
|
||||
var url =
|
||||
URL.createObjectURL(new Blob(["(", workerScript.toSource(), ")()"]));
|
||||
|
||||
// Keep a reference to the worker on the window.
|
||||
var worker = window.worker = new Worker(url);
|
||||
worker.postMessage(compositeBlob);
|
||||
worker.onmessage = workerLatchedBlobDeleteFromDB;
|
||||
}
|
||||
|
||||
function workerLatchedBlobDeleteFromDB() {
|
||||
// Delete the reference to the Blob from the database leaving the worker
|
||||
// thread reference as the only live reference once a GC has cleaned
|
||||
// out our references that we sent to the worker. The page that owns
|
||||
// us triggers a GC just for that reason.
|
||||
var objectStore = db.transaction("foo", "readwrite").objectStore("foo");
|
||||
objectStore.delete(42).onsuccess = closeDBTellOwningThread;
|
||||
}
|
||||
|
||||
function closeDBTellOwningThread(event) {
|
||||
// Now that worker has latched the blob, clean up the database.
|
||||
db.close();
|
||||
db = null;
|
||||
report('ready');
|
||||
}
|
||||
|
||||
createDatastore();
|
||||
}
|
||||
</script>
|
||||
|
||||
</head>
|
||||
|
||||
<body onload="runIndexedDBTest();">
|
||||
</body>
|
||||
|
||||
</html>
|
@ -2,6 +2,7 @@
|
||||
support-files =
|
||||
bfcache_iframe1.html
|
||||
bfcache_iframe2.html
|
||||
blob_worker_crash_iframe.html
|
||||
error_events_abort_transactions_iframe.html
|
||||
event_propagation_iframe.html
|
||||
exceptions_in_events_iframe.html
|
||||
@ -26,6 +27,7 @@ support-files =
|
||||
[test_bfcache.html]
|
||||
[test_blob_archive.html]
|
||||
[test_blob_simple.html]
|
||||
[test_blob_worker_crash.html]
|
||||
[test_clear.html]
|
||||
[test_complex_keyPaths.html]
|
||||
[test_count.html]
|
||||
|
62
dom/indexedDB/test/test_blob_worker_crash.html
Normal file
62
dom/indexedDB/test/test_blob_worker_crash.html
Normal file
@ -0,0 +1,62 @@
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>Indexed Database Blob Worker Crash Test</title>
|
||||
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
|
||||
<script type="text/javascript;version=1.7">
|
||||
/*
|
||||
* This tests ensures that if the last live reference to a Blob is on the
|
||||
* worker and the database has already been shutdown, that there is no crash
|
||||
* when the owning page gets cleaned up which causes the termination of the
|
||||
* worker which in turn garbage collects during its shutdown.
|
||||
*
|
||||
* We do the IndexedDB stuff in the iframe so we can kill it as part of our
|
||||
* test. Doing it out here is no good.
|
||||
*/
|
||||
|
||||
function testSteps()
|
||||
{
|
||||
info("Open iframe, wait for it to do its IndexedDB stuff.");
|
||||
|
||||
let iframe = document.getElementById("iframe1");
|
||||
window.addEventListener("message", grabEventAndContinueHandler, false);
|
||||
// Put it in a different origin to be safe
|
||||
//allowUnlimitedQuota("http://example.org/");
|
||||
iframe.src = //"http://example.org" +
|
||||
window.location.pathname.replace(
|
||||
"test_blob_worker_crash.html",
|
||||
"blob_worker_crash_iframe.html");
|
||||
|
||||
let event = yield unexpectedSuccessHandler;
|
||||
is(event.data.result, "ready", "worker initialized correctly");
|
||||
|
||||
info("Trigger a GC to clean-up the iframe's main-thread IndexedDB");
|
||||
scheduleGC();
|
||||
yield undefined;
|
||||
|
||||
info("Kill the iframe, forget about it, trigger a GC.");
|
||||
iframe.parentNode.removeChild(iframe);
|
||||
iframe = null;
|
||||
scheduleGC();
|
||||
yield undefined;
|
||||
|
||||
info("If we are still alive, then we win!");
|
||||
ok('Did not crash / trigger an assert!');
|
||||
|
||||
finishTest();
|
||||
yield undefined;
|
||||
}
|
||||
</script>
|
||||
<script type="text/javascript;version=1.7" src="helpers.js"></script>
|
||||
|
||||
</head>
|
||||
|
||||
<body onload="runTest();"></body>
|
||||
<iframe id="iframe1"></iframe>
|
||||
</html>
|
@ -206,24 +206,38 @@ MobileMessageManager::Send(const JS::Value& aNumber_,
|
||||
JS::Rooted<JSObject*> numbers(aCx, &aNumber.toObject());
|
||||
|
||||
uint32_t size;
|
||||
JS_ALWAYS_TRUE(JS_GetArrayLength(aCx, numbers, &size));
|
||||
if (!JS_GetArrayLength(aCx, numbers, &size)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
JS::Value* requests = new JS::Value[size];
|
||||
JS::AutoValueVector requests(aCx);
|
||||
if (!requests.resize(size)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
JS::Rooted<JS::Value> number(aCx);
|
||||
JS::Rooted<JSString*> str(aCx);
|
||||
for (uint32_t i = 0; i < size; ++i) {
|
||||
if (!JS_GetElement(aCx, numbers, i, &number)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
JS::Rooted<JSString*> str(aCx, number.toString());
|
||||
str = JS::ToString(aCx, number);
|
||||
if (!str) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult rv = Send(aCx, global, serviceId, str, aMessage, &requests[i]);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
aReturn->setObjectOrNull(JS_NewArrayObject(aCx, size, requests));
|
||||
NS_ENSURE_TRUE(aReturn->isObject(), NS_ERROR_FAILURE);
|
||||
JS::Rooted<JSObject*> obj(aCx);
|
||||
obj = JS_NewArrayObject(aCx, requests.length(), requests.begin());
|
||||
if (!obj) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
aReturn->setObject(*obj);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -353,7 +353,7 @@ TelephonyProvider.prototype = {
|
||||
this._getClient(aClientId).sendWorkerMessage("enumerateCalls", null,
|
||||
(function(response) {
|
||||
for (let call of response.calls) {
|
||||
call.clienId = aClientId;
|
||||
call.clientId = aClientId;
|
||||
call.state = this._convertRILCallState(call.state);
|
||||
call.isActive = this._matchActiveCall(call);
|
||||
|
||||
|
@ -23,6 +23,8 @@ import org.mozilla.gecko.home.SearchEngine;
|
||||
import org.mozilla.gecko.menu.GeckoMenu;
|
||||
import org.mozilla.gecko.preferences.GeckoPreferences;
|
||||
import org.mozilla.gecko.prompts.Prompt;
|
||||
import org.mozilla.gecko.toolbar.AutocompleteHandler;
|
||||
import org.mozilla.gecko.toolbar.BrowserToolbar;
|
||||
import org.mozilla.gecko.util.Clipboard;
|
||||
import org.mozilla.gecko.util.GamepadUtils;
|
||||
import org.mozilla.gecko.util.HardwareUtils;
|
||||
|
@ -14,7 +14,7 @@ import android.view.inputmethod.InputMethodManager;
|
||||
import java.util.Collection;
|
||||
import java.util.Locale;
|
||||
|
||||
final class InputMethods {
|
||||
final public class InputMethods {
|
||||
public static final String METHOD_ANDROID_LATINIME = "com.android.inputmethod.latin/.LatinIME";
|
||||
public static final String METHOD_ATOK = "com.justsystems.atokmobile.service/.AtokInputMethodService";
|
||||
public static final String METHOD_GOOGLE_JAPANESE_INPUT = "com.google.android.inputmethod.japanese/.MozcService";
|
||||
|
@ -5,7 +5,6 @@
|
||||
|
||||
package org.mozilla.gecko.home;
|
||||
|
||||
import org.mozilla.gecko.AutocompleteHandler;
|
||||
import org.mozilla.gecko.GeckoAppShell;
|
||||
import org.mozilla.gecko.GeckoEvent;
|
||||
import org.mozilla.gecko.PrefsHelper;
|
||||
@ -16,6 +15,7 @@ import org.mozilla.gecko.db.BrowserDB.URLColumns;
|
||||
import org.mozilla.gecko.home.HomePager.OnUrlOpenListener;
|
||||
import org.mozilla.gecko.home.SearchEngine;
|
||||
import org.mozilla.gecko.home.SearchLoader.SearchCursorLoader;
|
||||
import org.mozilla.gecko.toolbar.AutocompleteHandler;
|
||||
import org.mozilla.gecko.util.GeckoEventListener;
|
||||
import org.mozilla.gecko.util.StringUtils;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
|
@ -91,15 +91,10 @@ gbjar.sources += [
|
||||
'animation/ViewHelper.java',
|
||||
'ANRReporter.java',
|
||||
'AppNotificationClient.java',
|
||||
'AutocompleteHandler.java',
|
||||
'BackButton.java',
|
||||
'BaseGeckoInterface.java',
|
||||
'BrowserApp.java',
|
||||
'BrowserToolbar.java',
|
||||
'BrowserToolbarBackground.java',
|
||||
'CameraImageResultHandler.java',
|
||||
'CameraVideoResultHandler.java',
|
||||
'CanvasDelegate.java',
|
||||
'ContactService.java',
|
||||
'ContextGetter.java',
|
||||
'CustomEditText.java',
|
||||
@ -127,7 +122,6 @@ gbjar.sources += [
|
||||
'FilePickerResultHandlerSync.java',
|
||||
'FindInPageBar.java',
|
||||
'FormAssistPopup.java',
|
||||
'ForwardButton.java',
|
||||
'GeckoAccessibility.java',
|
||||
'GeckoActivity.java',
|
||||
'GeckoActivityStatus.java',
|
||||
@ -245,7 +239,6 @@ gbjar.sources += [
|
||||
'NotificationService.java',
|
||||
'NSSBridge.java',
|
||||
'OrderedBroadcastHelper.java',
|
||||
'PageActionLayout.java',
|
||||
'preferences/AlignRightLinkPreference.java',
|
||||
'preferences/AndroidImport.java',
|
||||
'preferences/AndroidImportPreference.java',
|
||||
@ -272,7 +265,6 @@ gbjar.sources += [
|
||||
'ScrollAnimator.java',
|
||||
'ServiceNotificationClient.java',
|
||||
'SessionParser.java',
|
||||
'ShapedButton.java',
|
||||
'SharedPreferencesHelper.java',
|
||||
'SiteIdentityPopup.java',
|
||||
'SmsManager.java',
|
||||
@ -282,7 +274,6 @@ gbjar.sources += [
|
||||
'sqlite/SQLiteBridgeException.java',
|
||||
'SurfaceBits.java',
|
||||
'Tab.java',
|
||||
'TabCounter.java',
|
||||
'Tabs.java',
|
||||
'TabsAccessor.java',
|
||||
'TabsPanel.java',
|
||||
@ -291,6 +282,15 @@ gbjar.sources += [
|
||||
'TextSelection.java',
|
||||
'TextSelectionHandle.java',
|
||||
'ThumbnailHelper.java',
|
||||
'toolbar/AutocompleteHandler.java',
|
||||
'toolbar/BackButton.java',
|
||||
'toolbar/BrowserToolbar.java',
|
||||
'toolbar/BrowserToolbarBackground.java',
|
||||
'toolbar/CanvasDelegate.java',
|
||||
'toolbar/ForwardButton.java',
|
||||
'toolbar/PageActionLayout.java',
|
||||
'toolbar/ShapedButton.java',
|
||||
'toolbar/TabCounter.java',
|
||||
'TouchEventInterceptor.java',
|
||||
'updater/UpdateService.java',
|
||||
'updater/UpdateServiceHelper.java',
|
||||
|
@ -6,20 +6,20 @@
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:gecko="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<org.mozilla.gecko.BrowserToolbarBackground android:id="@+id/url_bar_bg"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:background="@drawable/url_bar_bg"/>
|
||||
<org.mozilla.gecko.toolbar.BrowserToolbarBackground android:id="@+id/url_bar_bg"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:background="@drawable/url_bar_bg"/>
|
||||
|
||||
<org.mozilla.gecko.ShapedButton android:id="@+id/tabs"
|
||||
style="@style/UrlBar.ImageButton"
|
||||
android:layout_width="84dip"
|
||||
android:layout_alignParentLeft="true"
|
||||
gecko:curveTowards="left"
|
||||
android:background="@drawable/shaped_button"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingLeft="6dip"
|
||||
android:paddingRight="38dip"/>
|
||||
<org.mozilla.gecko.toolbar.ShapedButton android:id="@+id/tabs"
|
||||
style="@style/UrlBar.ImageButton"
|
||||
android:layout_width="84dip"
|
||||
android:layout_alignParentLeft="true"
|
||||
gecko:curveTowards="left"
|
||||
android:background="@drawable/shaped_button"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingLeft="6dip"
|
||||
android:paddingRight="38dip"/>
|
||||
|
||||
<!-- The TextSwitcher should be shifted 28dp on the right, to avoid
|
||||
the curve. On a 56dp space, centering 24dp image will leave
|
||||
@ -27,7 +27,7 @@
|
||||
2 layers. Hence to center this, an additional 4dp is added to the right.
|
||||
The margins will be 12dp on left, 48dp on right, instead of ideal 16dp
|
||||
and 44dp. -->
|
||||
<org.mozilla.gecko.TabCounter android:id="@+id/tabs_counter"
|
||||
<org.mozilla.gecko.toolbar.TabCounter android:id="@+id/tabs_counter"
|
||||
style="@style/UrlBar.ImageButton.TabCount"
|
||||
android:layout_width="24dip"
|
||||
android:layout_height="24dip"
|
||||
@ -49,21 +49,21 @@
|
||||
android:focusable="false"
|
||||
android:background="@drawable/url_bar_entry"/>
|
||||
|
||||
<org.mozilla.gecko.ForwardButton style="@style/UrlBar.ImageButton.Forward"
|
||||
android:id="@+id/forward"
|
||||
android:layout_toRightOf="@+id/tabs"/>
|
||||
<org.mozilla.gecko.toolbar.ForwardButton style="@style/UrlBar.ImageButton.Forward"
|
||||
android:id="@+id/forward"
|
||||
android:layout_toRightOf="@+id/tabs"/>
|
||||
|
||||
<org.mozilla.gecko.BackButton android:id="@+id/back"
|
||||
style="@style/UrlBar.ImageButton"
|
||||
android:layout_width="50dip"
|
||||
android:layout_height="50dip"
|
||||
android:layout_toRightOf="@id/tabs"
|
||||
android:layout_marginLeft="-28dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:padding="13dp"
|
||||
android:src="@drawable/ic_menu_back"
|
||||
android:contentDescription="@string/back"
|
||||
android:background="@drawable/url_bar_nav_button"/>
|
||||
<org.mozilla.gecko.toolbar.BackButton android:id="@+id/back"
|
||||
style="@style/UrlBar.ImageButton"
|
||||
android:layout_width="50dip"
|
||||
android:layout_height="50dip"
|
||||
android:layout_toRightOf="@id/tabs"
|
||||
android:layout_marginLeft="-28dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:padding="13dp"
|
||||
android:src="@drawable/ic_menu_back"
|
||||
android:contentDescription="@string/back"
|
||||
android:background="@drawable/url_bar_nav_button"/>
|
||||
|
||||
<LinearLayout android:id="@+id/url_edit_container"
|
||||
style="@style/UrlBar.Button"
|
||||
@ -142,12 +142,12 @@
|
||||
android:layout_gravity="center_vertical"
|
||||
gecko:autoUpdateTheme="false"/>
|
||||
|
||||
<org.mozilla.gecko.PageActionLayout android:id="@+id/page_action_layout"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginRight="@dimen/browser_toolbar_button_padding"
|
||||
android:visibility="gone"
|
||||
android:orientation="horizontal"/>
|
||||
<org.mozilla.gecko.toolbar.PageActionLayout android:id="@+id/page_action_layout"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginRight="@dimen/browser_toolbar_button_padding"
|
||||
android:visibility="gone"
|
||||
android:orientation="horizontal"/>
|
||||
|
||||
<ImageButton android:id="@+id/stop"
|
||||
style="@style/UrlBar.ImageButton.Icon"
|
||||
|
@ -12,10 +12,10 @@
|
||||
<ImageButton android:id="@+id/forward"
|
||||
style="@style/UrlBar.ImageButton.Unused"/>
|
||||
|
||||
<org.mozilla.gecko.BrowserToolbarBackground android:id="@+id/url_bar_bg"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:background="@drawable/url_bar_bg"/>
|
||||
<org.mozilla.gecko.toolbar.BrowserToolbarBackground android:id="@+id/url_bar_bg"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:background="@drawable/url_bar_bg"/>
|
||||
|
||||
<ImageView android:id="@+id/url_bar_entry"
|
||||
style="@style/UrlBar.Button"
|
||||
@ -48,13 +48,13 @@
|
||||
<LinearLayout android:id="@+id/menu_items"
|
||||
style="@style/UrlBar.ImageButton.Unused"/>
|
||||
|
||||
<org.mozilla.gecko.ShapedButton android:id="@+id/menu"
|
||||
style="@style/UrlBar.ImageButton"
|
||||
android:layout_width="48dip"
|
||||
android:layout_alignParentRight="true"
|
||||
android:contentDescription="@string/menu"
|
||||
android:background="@drawable/shaped_button"
|
||||
android:visibility="gone"/>
|
||||
<org.mozilla.gecko.toolbar.ShapedButton android:id="@+id/menu"
|
||||
style="@style/UrlBar.ImageButton"
|
||||
android:layout_width="48dip"
|
||||
android:layout_alignParentRight="true"
|
||||
android:contentDescription="@string/menu"
|
||||
android:background="@drawable/shaped_button"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<org.mozilla.gecko.widget.GeckoImageView android:id="@+id/menu_icon"
|
||||
style="@style/UrlBar.ImageButton"
|
||||
@ -64,16 +64,16 @@
|
||||
android:src="@drawable/menu_level"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<org.mozilla.gecko.ShapedButton android:id="@+id/tabs"
|
||||
style="@style/UrlBar.ImageButton"
|
||||
android:layout_width="72dip"
|
||||
android:layout_toLeftOf="@id/menu"
|
||||
android:layout_alignWithParentIfMissing="true"
|
||||
gecko:curveTowards="right"
|
||||
android:background="@drawable/shaped_button"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingLeft="37dip"
|
||||
android:paddingRight="11dip"/>
|
||||
<org.mozilla.gecko.toolbar.ShapedButton android:id="@+id/tabs"
|
||||
style="@style/UrlBar.ImageButton"
|
||||
android:layout_width="72dip"
|
||||
android:layout_toLeftOf="@id/menu"
|
||||
android:layout_alignWithParentIfMissing="true"
|
||||
gecko:curveTowards="right"
|
||||
android:background="@drawable/shaped_button"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingLeft="37dip"
|
||||
android:paddingRight="11dip"/>
|
||||
|
||||
<!-- The TextSwitcher should be shifted 24dp on the left, to avoid
|
||||
the curve. On a 48dp space, centering 24dp image will leave
|
||||
@ -81,7 +81,7 @@
|
||||
2 layers. Hence to center this, an additional 4dp is added to the left.
|
||||
The margins will be 40dp on left, 8dp on right, instead of ideal 30dp
|
||||
and 12dp. -->
|
||||
<org.mozilla.gecko.TabCounter android:id="@+id/tabs_counter"
|
||||
<org.mozilla.gecko.toolbar.TabCounter android:id="@+id/tabs_counter"
|
||||
style="@style/UrlBar.ImageButton.TabCount"
|
||||
android:layout_width="24dip"
|
||||
android:layout_height="24dip"
|
||||
@ -166,12 +166,12 @@
|
||||
android:layout_gravity="center_vertical"
|
||||
gecko:autoUpdateTheme="false"/>
|
||||
|
||||
<org.mozilla.gecko.PageActionLayout android:id="@+id/page_action_layout"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginRight="12dp"
|
||||
android:visibility="gone"
|
||||
android:orientation="horizontal"/>
|
||||
<org.mozilla.gecko.toolbar.PageActionLayout android:id="@+id/page_action_layout"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginRight="12dp"
|
||||
android:visibility="gone"
|
||||
android:orientation="horizontal"/>
|
||||
|
||||
<ImageButton android:id="@+id/stop"
|
||||
style="@style/UrlBar.ImageButton.Icon"
|
||||
|
@ -67,7 +67,8 @@
|
||||
view. To make sure the EditText is not the first focusable view in
|
||||
the root view, BrowserToolbar should be specified as low in the
|
||||
view hierarchy as possible. -->
|
||||
<org.mozilla.gecko.BrowserToolbar android:id="@id/browser_toolbar"
|
||||
<org.mozilla.gecko.toolbar.BrowserToolbar
|
||||
android:id="@id/browser_toolbar"
|
||||
style="@style/BrowserToolbar"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="@dimen/browser_toolbar_height"
|
||||
|
@ -3,7 +3,7 @@
|
||||
* 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;
|
||||
package org.mozilla.gecko.toolbar;
|
||||
|
||||
public interface AutocompleteHandler {
|
||||
void onAutocomplete(String res);
|
@ -2,7 +2,9 @@
|
||||
* 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;
|
||||
package org.mozilla.gecko.toolbar;
|
||||
|
||||
import org.mozilla.gecko.R;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
@ -3,8 +3,19 @@
|
||||
* 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;
|
||||
package org.mozilla.gecko.toolbar;
|
||||
|
||||
import org.mozilla.gecko.BrowserApp;
|
||||
import org.mozilla.gecko.CustomEditText;
|
||||
import org.mozilla.gecko.InputMethods;
|
||||
import org.mozilla.gecko.GeckoApplication;
|
||||
import org.mozilla.gecko.GeckoAppShell;
|
||||
import org.mozilla.gecko.GeckoProfile;
|
||||
import org.mozilla.gecko.LightweightTheme;
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.SiteIdentityPopup;
|
||||
import org.mozilla.gecko.Tab;
|
||||
import org.mozilla.gecko.Tabs;
|
||||
import org.mozilla.gecko.animation.PropertyAnimator;
|
||||
import org.mozilla.gecko.animation.ViewHelper;
|
||||
import org.mozilla.gecko.gfx.ImmutableViewportMetrics;
|
||||
@ -12,7 +23,6 @@ import org.mozilla.gecko.gfx.LayerView;
|
||||
import org.mozilla.gecko.util.GamepadUtils;
|
||||
import org.mozilla.gecko.menu.GeckoMenu;
|
||||
import org.mozilla.gecko.menu.MenuPopup;
|
||||
import org.mozilla.gecko.PageActionLayout;
|
||||
import org.mozilla.gecko.PrefsHelper;
|
||||
import org.mozilla.gecko.util.Clipboard;
|
||||
import org.mozilla.gecko.util.StringUtils;
|
@ -2,8 +2,11 @@
|
||||
* 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;
|
||||
package org.mozilla.gecko.toolbar;
|
||||
|
||||
import org.mozilla.gecko.GeckoApplication;
|
||||
import org.mozilla.gecko.LightweightTheme;
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.widget.GeckoLinearLayout;
|
||||
|
||||
import android.content.Context;
|
@ -2,7 +2,7 @@
|
||||
* 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;
|
||||
package org.mozilla.gecko.toolbar;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
@ -2,7 +2,9 @@
|
||||
* 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;
|
||||
package org.mozilla.gecko.toolbar;
|
||||
|
||||
import org.mozilla.gecko.R;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
@ -3,8 +3,11 @@
|
||||
* 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;
|
||||
package org.mozilla.gecko.toolbar;
|
||||
|
||||
import org.mozilla.gecko.GeckoAppShell;
|
||||
import org.mozilla.gecko.GeckoEvent;
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.gfx.BitmapUtils;
|
||||
import org.mozilla.gecko.util.GeckoEventListener;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
@ -2,8 +2,12 @@
|
||||
* 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;
|
||||
package org.mozilla.gecko.toolbar;
|
||||
|
||||
import org.mozilla.gecko.GeckoApplication;
|
||||
import org.mozilla.gecko.LightweightTheme;
|
||||
import org.mozilla.gecko.LightweightThemeDrawable;
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.widget.GeckoImageButton;
|
||||
|
||||
import android.content.Context;
|
@ -3,9 +3,10 @@
|
||||
* 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;
|
||||
package org.mozilla.gecko.toolbar;
|
||||
|
||||
import org.mozilla.gecko.animation.Rotate3DAnimation;
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.widget.GeckoTextSwitcher;
|
||||
|
||||
import android.content.Context;
|
@ -17,6 +17,7 @@ var SelectionHandler = {
|
||||
_cache: null,
|
||||
_activeType: 0, // TYPE_NONE
|
||||
_ignoreSelectionChanges: false, // True while user drags text selection handles
|
||||
_ignoreCompositionChanges: false, // Persist caret during IME composition updates
|
||||
|
||||
// The window that holds the selection (can be a sub-frame)
|
||||
get _contentWindow() {
|
||||
@ -108,6 +109,9 @@ var SelectionHandler = {
|
||||
this._ignoreSelectionChanges = true;
|
||||
this._moveSelection(data.handleType == this.HANDLE_TYPE_START, data.x, data.y);
|
||||
} else if (this._activeType == this.TYPE_CURSOR) {
|
||||
// Ignore IMM composition notifications when caret movement starts
|
||||
this._ignoreCompositionChanges = true;
|
||||
|
||||
// Send a click event to the text box, which positions the caret
|
||||
this._sendMouseEvents(data.x, data.y);
|
||||
|
||||
@ -133,6 +137,10 @@ var SelectionHandler = {
|
||||
}
|
||||
// Act on selectionChange notifications after handle movement ends
|
||||
this._ignoreSelectionChanges = false;
|
||||
|
||||
} else if (this._activeType == this.TYPE_CURSOR) {
|
||||
// Act on IMM composition notifications after caret movement ends
|
||||
this._ignoreCompositionChanges = false;
|
||||
}
|
||||
this._positionHandles();
|
||||
break;
|
||||
@ -158,7 +166,8 @@ var SelectionHandler = {
|
||||
break;
|
||||
|
||||
case "compositionend":
|
||||
if (this._activeType == this.TYPE_CURSOR) {
|
||||
// compositionend messages normally terminate caret display
|
||||
if (this._activeType == this.TYPE_CURSOR && !this._ignoreCompositionChanges) {
|
||||
this._deactivate();
|
||||
}
|
||||
break;
|
||||
@ -530,6 +539,7 @@ var SelectionHandler = {
|
||||
this._isRTL = false;
|
||||
this._cache = null;
|
||||
this._ignoreSelectionChanges = false;
|
||||
this._ignoreCompositionChanges = false;
|
||||
},
|
||||
|
||||
_getViewOffset: function sh_getViewOffset() {
|
||||
|
@ -86,6 +86,11 @@
|
||||
|
||||
#include <limits>
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
#include "nsINetworkManager.h"
|
||||
#include "nsThreadUtils.h" // for NS_IsMainThread
|
||||
#endif
|
||||
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
|
||||
#include "nsReadableUtils.h"
|
||||
@ -2360,4 +2365,28 @@ NS_IsSrcdocChannel(nsIChannel *aChannel)
|
||||
return false;
|
||||
}
|
||||
|
||||
// The following members are used for network per-app metering.
|
||||
const static uint64_t NETWORK_STATS_THRESHOLD = 65536;
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
inline nsresult
|
||||
NS_GetActiveNetworkInterface(nsCOMPtr<nsINetworkInterface> &aNetworkInterface)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsINetworkManager> networkManager =
|
||||
do_GetService("@mozilla.org/network/manager;1", &rv);
|
||||
|
||||
if (NS_FAILED(rv) || !networkManager) {
|
||||
aNetworkInterface = nullptr;
|
||||
return rv;
|
||||
}
|
||||
|
||||
networkManager->GetActive(getter_AddRefs(aNetworkInterface));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // !nsNetUtil_h__
|
||||
|
@ -1691,6 +1691,10 @@ nsFtpState::Init(nsFtpChannel *channel)
|
||||
// initialize counter for network metering
|
||||
mCountRecv = 0;
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
NS_GetActiveNetworkInterface(mActiveNetwork);
|
||||
#endif
|
||||
|
||||
mKeepRunning = true;
|
||||
mSuppliedEntityID = channel->EntityID();
|
||||
|
||||
@ -2199,22 +2203,6 @@ nsresult
|
||||
nsFtpState::SaveNetworkStats(bool enforce)
|
||||
{
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// Obtain active network
|
||||
nsresult rv;
|
||||
if (!mActiveNetwork) {
|
||||
nsCOMPtr<nsINetworkManager> networkManager =
|
||||
do_GetService("@mozilla.org/network/manager;1", &rv);
|
||||
|
||||
if (NS_FAILED(rv) || !networkManager) {
|
||||
mActiveNetwork = nullptr;
|
||||
return rv;
|
||||
}
|
||||
|
||||
networkManager->GetActive(getter_AddRefs(mActiveNetwork));
|
||||
}
|
||||
|
||||
// Obtain app id
|
||||
uint32_t appId;
|
||||
bool isInBrowser;
|
||||
@ -2237,6 +2225,7 @@ nsFtpState::SaveNetworkStats(bool enforce)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsINetworkStatsServiceProxy> networkStatsServiceProxy =
|
||||
do_GetService("@mozilla.org/networkstatsServiceProxy;1", &rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
|
@ -262,10 +262,6 @@ private:
|
||||
|
||||
// These members are used for network per-app metering (bug 855948)
|
||||
// Currently, they are only available on gonk.
|
||||
public:
|
||||
const static uint64_t NETWORK_STATS_THRESHOLD = 65536;
|
||||
|
||||
private:
|
||||
uint64_t mCountRecv;
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
nsCOMPtr<nsINetworkInterface> mActiveNetwork;
|
||||
|
@ -230,17 +230,20 @@ nsHttpTransaction::Init(uint32_t caps,
|
||||
mActivityDistributor = nullptr;
|
||||
}
|
||||
|
||||
// obtain app info
|
||||
bool isInBrowser;
|
||||
nsCOMPtr<nsIChannel> channel = do_QueryInterface(eventsink);
|
||||
if (channel) {
|
||||
bool isInBrowser;
|
||||
NS_GetAppInfo(channel, &mAppId, &isInBrowser);
|
||||
}
|
||||
|
||||
// obtain active connection type
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
if (mAppId != NECKO_NO_APP_ID) {
|
||||
GetActiveNetwork();
|
||||
nsCOMPtr<nsINetworkInterface> activeNetwork;
|
||||
NS_GetActiveNetworkInterface(activeNetwork);
|
||||
mActiveNetwork =
|
||||
new nsMainThreadPtrHolder<nsINetworkInterface>(activeNetwork);
|
||||
}
|
||||
#endif
|
||||
|
||||
// create transport event sink proxy. it coalesces all events if and only
|
||||
// if the activity observer is not active. when the observer is active
|
||||
@ -707,28 +710,6 @@ nsHttpTransaction::WriteSegments(nsAHttpSegmentWriter *writer,
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
nsHttpTransaction::GetActiveNetwork()
|
||||
{
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsINetworkManager> networkManager =
|
||||
do_GetService("@mozilla.org/network/manager;1", &rv);
|
||||
|
||||
if (NS_FAILED(rv) || !networkManager) {
|
||||
mActiveNetwork = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsINetworkInterface> activeNetwork;
|
||||
networkManager->GetActive(getter_AddRefs(activeNetwork));
|
||||
mActiveNetwork =
|
||||
new nsMainThreadPtrHolder<nsINetworkInterface>(activeNetwork);
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// nsHttpTransaction save network statistics event
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -340,10 +340,6 @@ private:
|
||||
|
||||
// These members are used for network per-app metering (bug 746073)
|
||||
// Currently, they are only available on gonk.
|
||||
public:
|
||||
const static uint64_t NETWORK_STATS_THRESHOLD = 65536;
|
||||
|
||||
private:
|
||||
uint64_t mCountRecv;
|
||||
uint64_t mCountSent;
|
||||
uint32_t mAppId;
|
||||
@ -351,7 +347,6 @@ private:
|
||||
nsMainThreadPtrHandle<nsINetworkInterface> mActiveNetwork;
|
||||
#endif
|
||||
nsresult SaveNetworkStats(bool);
|
||||
void GetActiveNetwork();
|
||||
void CountRecvBytes(uint64_t recvBytes)
|
||||
{
|
||||
mCountRecv += recvBytes;
|
||||
|
@ -965,8 +965,7 @@ WebSocketChannel::WebSocketChannel() :
|
||||
mConnectionLogService(nullptr),
|
||||
mCountRecv(0),
|
||||
mCountSent(0),
|
||||
mAppId(0),
|
||||
mIsInBrowser(false)
|
||||
mAppId(NECKO_NO_APP_ID)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(NS_IsMainThread(), "not main thread");
|
||||
|
||||
@ -1075,15 +1074,16 @@ WebSocketChannel::BeginOpen()
|
||||
return;
|
||||
}
|
||||
|
||||
// obtain app info
|
||||
if (localChannel) {
|
||||
NS_GetAppInfo(localChannel, &mAppId, &mIsInBrowser);
|
||||
bool isInBrowser;
|
||||
NS_GetAppInfo(localChannel, &mAppId, &isInBrowser);
|
||||
}
|
||||
|
||||
// obtain active network
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
if (mAppId != NECKO_NO_APP_ID) {
|
||||
GetActiveNetwork();
|
||||
NS_GetActiveNetworkInterface(mActiveNetwork);
|
||||
}
|
||||
#endif
|
||||
|
||||
rv = localChannel->AsyncOpen(this, mHttpChannel);
|
||||
if (NS_FAILED(rv)) {
|
||||
@ -3271,28 +3271,6 @@ WebSocketChannel::OnDataAvailable(nsIRequest *aRequest,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
WebSocketChannel::GetActiveNetwork()
|
||||
{
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsresult result;
|
||||
nsCOMPtr<nsINetworkManager> networkManager = do_GetService("@mozilla.org/network/manager;1", &result);
|
||||
|
||||
if (NS_FAILED(result) || !networkManager) {
|
||||
mActiveNetwork = nullptr;
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
result = networkManager->GetActive(getter_AddRefs(mActiveNetwork));
|
||||
|
||||
return NS_OK;
|
||||
#else
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
nsresult
|
||||
WebSocketChannel::SaveNetworkStats(bool enforce)
|
||||
{
|
||||
|
@ -257,18 +257,12 @@ private:
|
||||
|
||||
// These members are used for network per-app metering (bug 855949)
|
||||
// Currently, they are only available on gonk.
|
||||
public:
|
||||
const static uint64_t NETWORK_STATS_THRESHOLD = 65536;
|
||||
|
||||
private:
|
||||
uint64_t mCountRecv;
|
||||
uint64_t mCountSent;
|
||||
uint32_t mAppId;
|
||||
bool mIsInBrowser;
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
nsCOMPtr<nsINetworkInterface> mActiveNetwork;
|
||||
#endif
|
||||
nsresult GetActiveNetwork();
|
||||
nsresult SaveNetworkStats(bool);
|
||||
void CountRecvBytes(uint64_t recvBytes)
|
||||
{
|
||||
|
@ -504,6 +504,7 @@
|
||||
"dom/indexedDB/test/test_autoIncrement_indexes.html": "Bug 931116, b2g desktop specific, initial triage",
|
||||
"dom/indexedDB/test/test_bfcache.html": "Bug 931116, b2g desktop specific, initial triage",
|
||||
"dom/indexedDB/test/test_blob_archive.html": "Bug 931116, b2g desktop specific, initial triage",
|
||||
"dom/indexedDB/test/test_blob_worker_crash.html": "Bug 931116, b2g desktop specific, bug 927889 still present",
|
||||
"dom/indexedDB/test/test_blob_simple.html": "Bug 931116, b2g desktop specific, initial triage",
|
||||
"dom/indexedDB/test/test_clear.html": "Bug 931116, b2g desktop specific, initial triage",
|
||||
"dom/indexedDB/test/test_complex_keyPaths.html": "Bug 931116, b2g desktop specific, initial triage",
|
||||
|
426
testing/modules/Assert.jsm
Normal file
426
testing/modules/Assert.jsm
Normal file
@ -0,0 +1,426 @@
|
||||
/* 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/. */
|
||||
|
||||
// http://wiki.commonjs.org/wiki/Unit_Testing/1.0
|
||||
// When you see a javadoc comment that contains a number, it's a reference to a
|
||||
// specific section of the CommonJS spec.
|
||||
//
|
||||
// Originally from narwhal.js (http://narwhaljs.org)
|
||||
// Copyright (c) 2009 Thomas Robinson <280north.com>
|
||||
// MIT license: http://opensource.org/licenses/MIT
|
||||
|
||||
"use strict";
|
||||
|
||||
this.EXPORTED_SYMBOLS = [
|
||||
"Assert"
|
||||
];
|
||||
|
||||
/**
|
||||
* 1. The assert module provides functions that throw AssertionError's when
|
||||
* particular conditions are not met.
|
||||
*
|
||||
* To use the module you'll need to instantiate it first, which allows consumers
|
||||
* to override certain behavior on the newly obtained instance. For examples,
|
||||
* see the javadoc comments for the `report` member function.
|
||||
*/
|
||||
let Assert = this.Assert = function(reporterFunc) {
|
||||
if (reporterFunc)
|
||||
this.setReporter(reporterFunc);
|
||||
};
|
||||
|
||||
function instanceOf(object, type) {
|
||||
return Object.prototype.toString.call(object) == "[object " + type + "]";
|
||||
}
|
||||
|
||||
function replacer(key, value) {
|
||||
if (value === undefined) {
|
||||
return "" + value;
|
||||
}
|
||||
if (typeof value === "number" && (isNaN(value) || !isFinite(value))) {
|
||||
return value.toString();
|
||||
}
|
||||
if (typeof value === "function" || instanceOf(value, "RegExp")) {
|
||||
return value.toString();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
const kTruncateLength = 128;
|
||||
|
||||
function truncate(text, newLength = kTruncateLength) {
|
||||
if (typeof text == "string") {
|
||||
return text.length < newLength ? text : text.slice(0, newLength);
|
||||
} else {
|
||||
return text;
|
||||
}
|
||||
}
|
||||
|
||||
function getMessage(error) {
|
||||
return truncate(JSON.stringify(error.actual, replacer)) + " " +
|
||||
(error.operator ? error.operator + " " : "") +
|
||||
truncate(JSON.stringify(error.expected, replacer));
|
||||
}
|
||||
|
||||
/**
|
||||
* 2. The AssertionError is defined in assert.
|
||||
*
|
||||
* Example:
|
||||
* new assert.AssertionError({
|
||||
* message: message,
|
||||
* actual: actual,
|
||||
* expected: expected,
|
||||
* operator: operator
|
||||
* });
|
||||
*
|
||||
* At present only the four keys mentioned above are used and
|
||||
* understood by the spec. Implementations or sub modules can pass
|
||||
* other keys to the AssertionError's constructor - they will be
|
||||
* ignored.
|
||||
*/
|
||||
Assert.AssertionError = function(options) {
|
||||
this.name = "AssertionError";
|
||||
this.actual = options.actual;
|
||||
this.expected = options.expected;
|
||||
this.operator = options.operator;
|
||||
this.message = options.message || getMessage(this);
|
||||
// The part of the stack that comes from this module is not interesting.
|
||||
let stack = Components.stack;
|
||||
do {
|
||||
stack = stack.caller;
|
||||
} while(stack.filename && stack.filename.contains("Assert.jsm"))
|
||||
this.stack = stack;
|
||||
};
|
||||
|
||||
// assert.AssertionError instanceof Error
|
||||
Assert.AssertionError.prototype = Object.create(Error.prototype, {
|
||||
constructor: {
|
||||
value: Assert.AssertionError,
|
||||
enumerable: false,
|
||||
writable: true,
|
||||
configurable: true
|
||||
}
|
||||
});
|
||||
|
||||
let proto = Assert.prototype;
|
||||
|
||||
proto._reporter = null;
|
||||
/**
|
||||
* Set a custom assertion report handler function. Arguments passed in to this
|
||||
* function are:
|
||||
* err (AssertionError|null) An error object when the assertion failed or null
|
||||
* when it passed
|
||||
* message (string) Message describing the assertion
|
||||
* stack (stack) Stack trace of the assertion function
|
||||
*
|
||||
* Example:
|
||||
* ```js
|
||||
* Assert.setReporter(function customReporter(err, message, stack) {
|
||||
* if (err) {
|
||||
* do_report_result(false, err.message, err.stack);
|
||||
* } else {
|
||||
* do_report_result(true, message, stack);
|
||||
* }
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* @param reporterFunc
|
||||
* (function) Report handler function
|
||||
*/
|
||||
proto.setReporter = function(reporterFunc) {
|
||||
this._reporter = reporterFunc;
|
||||
};
|
||||
|
||||
/**
|
||||
* 3. All of the following functions must throw an AssertionError when a
|
||||
* corresponding condition is not met, with a message that may be undefined if
|
||||
* not provided. All assertion methods provide both the actual and expected
|
||||
* values to the assertion error for display purposes.
|
||||
*
|
||||
* This report method only throws errors on assertion failures, as per spec,
|
||||
* but consumers of this module (think: xpcshell-test, mochitest) may want to
|
||||
* override this default implementation.
|
||||
*
|
||||
* Example:
|
||||
* ```js
|
||||
* // The following will report an assertion failure.
|
||||
* this.report(1 != 2, 1, 2, "testing JS number math!", "==");
|
||||
* ```
|
||||
*
|
||||
* @param failed
|
||||
* (boolean) Indicates if the assertion failed or not
|
||||
* @param actual
|
||||
* (mixed) The result of evaluating the assertion
|
||||
* @param expected (optional)
|
||||
* (mixed) Expected result from the test author
|
||||
* @param message (optional)
|
||||
* (string) Short explanation of the expected result
|
||||
* @param operator (optional)
|
||||
* (string) Operation qualifier used by the assertion method (ex: '==')
|
||||
*/
|
||||
proto.report = function(failed, actual, expected, message, operator) {
|
||||
let err = new Assert.AssertionError({
|
||||
message: message,
|
||||
actual: actual,
|
||||
expected: expected,
|
||||
operator: operator
|
||||
});
|
||||
if (!this._reporter) {
|
||||
// If no custom reporter is set, throw the error.
|
||||
if (failed) {
|
||||
throw err;
|
||||
}
|
||||
} else {
|
||||
this._reporter(failed ? err : null, message, err.stack);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 4. Pure assertion tests whether a value is truthy, as determined by !!guard.
|
||||
* assert.ok(guard, message_opt);
|
||||
* This statement is equivalent to assert.equal(true, !!guard, message_opt);.
|
||||
* To test strictly for the value true, use assert.strictEqual(true, guard,
|
||||
* message_opt);.
|
||||
*
|
||||
* @param value
|
||||
* (mixed) Test subject to be evaluated as truthy
|
||||
* @param message (optional)
|
||||
* (string) Short explanation of the expected result
|
||||
*/
|
||||
proto.ok = function(value, message) {
|
||||
this.report(!value, value, true, message, "==");
|
||||
};
|
||||
|
||||
/**
|
||||
* 5. The equality assertion tests shallow, coercive equality with ==.
|
||||
* assert.equal(actual, expected, message_opt);
|
||||
*
|
||||
* @param actual
|
||||
* (mixed) Test subject to be evaluated as equivalent to `expected`
|
||||
* @param expected
|
||||
* (mixed) Test reference to evaluate against `actual`
|
||||
* @param message (optional)
|
||||
* (string) Short explanation of the expected result
|
||||
*/
|
||||
proto.equal = function equal(actual, expected, message) {
|
||||
this.report(actual != expected, actual, expected, message, "==");
|
||||
};
|
||||
|
||||
/**
|
||||
* 6. The non-equality assertion tests for whether two objects are not equal
|
||||
* with != assert.notEqual(actual, expected, message_opt);
|
||||
*
|
||||
* @param actual
|
||||
* (mixed) Test subject to be evaluated as NOT equivalent to `expected`
|
||||
* @param expected
|
||||
* (mixed) Test reference to evaluate against `actual`
|
||||
* @param message (optional)
|
||||
* (string) Short explanation of the expected result
|
||||
*/
|
||||
proto.notEqual = function notEqual(actual, expected, message) {
|
||||
this.report(actual == expected, actual, expected, message, "!=");
|
||||
};
|
||||
|
||||
/**
|
||||
* 7. The equivalence assertion tests a deep equality relation.
|
||||
* assert.deepEqual(actual, expected, message_opt);
|
||||
*
|
||||
* We check using the most exact approximation of equality between two objects
|
||||
* to keep the chance of false positives to a minimum.
|
||||
* `JSON.stringify` is not designed to be used for this purpose; objects may
|
||||
* have ambiguous `toJSON()` implementations that would influence the test.
|
||||
*
|
||||
* @param actual
|
||||
* (mixed) Test subject to be evaluated as equivalent to `expected`, including nested properties
|
||||
* @param expected
|
||||
* (mixed) Test reference to evaluate against `actual`
|
||||
* @param message (optional)
|
||||
* (string) Short explanation of the expected result
|
||||
*/
|
||||
proto.deepEqual = function deepEqual(actual, expected, message) {
|
||||
this.report(!_deepEqual(actual, expected), actual, expected, message, "deepEqual");
|
||||
};
|
||||
|
||||
function _deepEqual(actual, expected) {
|
||||
// 7.1. All identical values are equivalent, as determined by ===.
|
||||
if (actual === expected) {
|
||||
return true;
|
||||
// 7.2. If the expected value is a Date object, the actual value is
|
||||
// equivalent if it is also a Date object that refers to the same time.
|
||||
} else if (instanceOf(actual, "Date") && instanceOf(expected, "Date")) {
|
||||
return actual.getTime() === expected.getTime();
|
||||
// 7.3 If the expected value is a RegExp object, the actual value is
|
||||
// equivalent if it is also a RegExp object with the same source and
|
||||
// properties (`global`, `multiline`, `lastIndex`, `ignoreCase`).
|
||||
} else if (instanceOf(actual, "RegExp") && instanceOf(expected, "RegExp")) {
|
||||
return actual.source === expected.source &&
|
||||
actual.global === expected.global &&
|
||||
actual.multiline === expected.multiline &&
|
||||
actual.lastIndex === expected.lastIndex &&
|
||||
actual.ignoreCase === expected.ignoreCase;
|
||||
// 7.4. Other pairs that do not both pass typeof value == "object",
|
||||
// equivalence is determined by ==.
|
||||
} else if (typeof actual != "object" && typeof expected != "object") {
|
||||
return actual == expected;
|
||||
// 7.5 For all other Object pairs, including Array objects, equivalence is
|
||||
// determined by having the same number of owned properties (as verified
|
||||
// with Object.prototype.hasOwnProperty.call), the same set of keys
|
||||
// (although not necessarily the same order), equivalent values for every
|
||||
// corresponding key, and an identical 'prototype' property. Note: this
|
||||
// accounts for both named and indexed properties on Arrays.
|
||||
} else {
|
||||
return objEquiv(actual, expected);
|
||||
}
|
||||
}
|
||||
|
||||
function isUndefinedOrNull(value) {
|
||||
return value === null || value === undefined;
|
||||
}
|
||||
|
||||
function isArguments(object) {
|
||||
return instanceOf(object, "Arguments");
|
||||
}
|
||||
|
||||
function objEquiv(a, b) {
|
||||
if (isUndefinedOrNull(a) || isUndefinedOrNull(b)) {
|
||||
return false;
|
||||
}
|
||||
// An identical 'prototype' property.
|
||||
if (a.prototype !== b.prototype) {
|
||||
return false;
|
||||
}
|
||||
// Object.keys may be broken through screwy arguments passing. Converting to
|
||||
// an array solves the problem.
|
||||
if (isArguments(a)) {
|
||||
if (!isArguments(b)) {
|
||||
return false;
|
||||
}
|
||||
a = pSlice.call(a);
|
||||
b = pSlice.call(b);
|
||||
return _deepEqual(a, b);
|
||||
}
|
||||
let ka, kb, key, i;
|
||||
try {
|
||||
ka = Object.keys(a);
|
||||
kb = Object.keys(b);
|
||||
} catch (e) {
|
||||
// Happens when one is a string literal and the other isn't
|
||||
return false;
|
||||
}
|
||||
// Having the same number of owned properties (keys incorporates
|
||||
// hasOwnProperty)
|
||||
if (ka.length != kb.length)
|
||||
return false;
|
||||
// The same set of keys (although not necessarily the same order),
|
||||
ka.sort();
|
||||
kb.sort();
|
||||
// Equivalent values for every corresponding key, and possibly expensive deep
|
||||
// test
|
||||
for (i = ka.length - 1; i >= 0; i--) {
|
||||
key = ka[i];
|
||||
if (!_deepEqual(a[key], b[key])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 8. The non-equivalence assertion tests for any deep inequality.
|
||||
* assert.notDeepEqual(actual, expected, message_opt);
|
||||
*
|
||||
* @param actual
|
||||
* (mixed) Test subject to be evaluated as NOT equivalent to `expected`, including nested properties
|
||||
* @param expected
|
||||
* (mixed) Test reference to evaluate against `actual`
|
||||
* @param message (optional)
|
||||
* (string) Short explanation of the expected result
|
||||
*/
|
||||
proto.notDeepEqual = function notDeepEqual(actual, expected, message) {
|
||||
this.report(_deepEqual(actual, expected), actual, expected, message, "notDeepEqual");
|
||||
};
|
||||
|
||||
/**
|
||||
* 9. The strict equality assertion tests strict equality, as determined by ===.
|
||||
* assert.strictEqual(actual, expected, message_opt);
|
||||
*
|
||||
* @param actual
|
||||
* (mixed) Test subject to be evaluated as strictly equivalent to `expected`
|
||||
* @param expected
|
||||
* (mixed) Test reference to evaluate against `actual`
|
||||
* @param message (optional)
|
||||
* (string) Short explanation of the expected result
|
||||
*/
|
||||
proto.strictEqual = function strictEqual(actual, expected, message) {
|
||||
this.report(actual !== expected, actual, expected, message, "===");
|
||||
};
|
||||
|
||||
/**
|
||||
* 10. The strict non-equality assertion tests for strict inequality, as
|
||||
* determined by !==. assert.notStrictEqual(actual, expected, message_opt);
|
||||
*
|
||||
* @param actual
|
||||
* (mixed) Test subject to be evaluated as NOT strictly equivalent to `expected`
|
||||
* @param expected
|
||||
* (mixed) Test reference to evaluate against `actual`
|
||||
* @param message (optional)
|
||||
* (string) Short explanation of the expected result
|
||||
*/
|
||||
proto.notStrictEqual = function notStrictEqual(actual, expected, message) {
|
||||
this.report(actual === expected, actual, expected, message, "!==");
|
||||
};
|
||||
|
||||
function expectedException(actual, expected) {
|
||||
if (!actual || !expected) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (instanceOf(expected, "RegExp")) {
|
||||
return expected.test(actual);
|
||||
} else if (actual instanceof expected) {
|
||||
return true;
|
||||
} else if (expected.call({}, actual) === true) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 11. Expected to throw an error:
|
||||
* assert.throws(block, Error_opt, message_opt);
|
||||
*
|
||||
* @param block
|
||||
* (function) Function block to evaluate and catch eventual thrown errors
|
||||
* @param expected (optional)
|
||||
* (mixed) Test reference to evaluate against the thrown result from `block`
|
||||
* @param message (optional)
|
||||
* (string) Short explanation of the expected result
|
||||
*/
|
||||
proto.throws = function(block, expected, message) {
|
||||
let actual;
|
||||
|
||||
if (typeof expected === "string") {
|
||||
message = expected;
|
||||
expected = null;
|
||||
}
|
||||
|
||||
try {
|
||||
block();
|
||||
} catch (e) {
|
||||
actual = e;
|
||||
}
|
||||
|
||||
message = (expected && expected.name ? " (" + expected.name + ")." : ".") +
|
||||
(message ? " " + message : ".");
|
||||
|
||||
if (!actual) {
|
||||
this.report(true, actual, expected, "Missing expected exception" + message);
|
||||
}
|
||||
|
||||
if ((actual && expected && !expectedException(actual, expected))) {
|
||||
throw actual;
|
||||
}
|
||||
|
||||
this.report(false, expected, expected, message);
|
||||
};
|
@ -4,4 +4,5 @@
|
||||
|
||||
TESTING_JS_MODULES := \
|
||||
AppInfo.jsm \
|
||||
Assert.jsm \
|
||||
$(NULL)
|
||||
|
@ -4,3 +4,4 @@
|
||||
# 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/.
|
||||
|
||||
XPCSHELL_TESTS_MANIFESTS += ['tests/xpcshell/xpcshell.ini']
|
||||
|
291
testing/modules/tests/xpcshell/test_assert.js
Normal file
291
testing/modules/tests/xpcshell/test_assert.js
Normal file
@ -0,0 +1,291 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Test cases borrowed and adapted from:
|
||||
// https://github.com/joyent/node/blob/6101eb184db77d0b11eb96e48744e57ecce4b73d/test/simple/test-assert.js
|
||||
// MIT license: http://opensource.org/licenses/MIT
|
||||
|
||||
function run_test() {
|
||||
let ns = {};
|
||||
Components.utils.import("resource://testing-common/Assert.jsm", ns);
|
||||
let assert = new ns.Assert();
|
||||
|
||||
function makeBlock(f, ...args) {
|
||||
return function() {
|
||||
return f.apply(assert, args);
|
||||
};
|
||||
}
|
||||
|
||||
function protoCtrChain(o) {
|
||||
let result = [];
|
||||
while (o = o.__proto__) {
|
||||
result.push(o.constructor);
|
||||
}
|
||||
return result.join();
|
||||
}
|
||||
|
||||
function indirectInstanceOf(obj, cls) {
|
||||
if (obj instanceof cls) {
|
||||
return true;
|
||||
}
|
||||
let clsChain = protoCtrChain(cls.prototype);
|
||||
let objChain = protoCtrChain(obj);
|
||||
return objChain.slice(-clsChain.length) === clsChain;
|
||||
};
|
||||
|
||||
assert.ok(indirectInstanceOf(ns.Assert.AssertionError.prototype, Error),
|
||||
"Assert.AssertionError instanceof Error");
|
||||
|
||||
assert.throws(makeBlock(assert.ok, false),
|
||||
ns.Assert.AssertionError, "ok(false)");
|
||||
|
||||
assert.ok(true, "ok(true)");
|
||||
|
||||
assert.ok("test", "ok('test')");
|
||||
|
||||
assert.throws(makeBlock(assert.equal, true, false), ns.Assert.AssertionError, "equal");
|
||||
|
||||
assert.equal(null, null, "equal");
|
||||
|
||||
assert.equal(undefined, undefined, "equal");
|
||||
|
||||
assert.equal(null, undefined, "equal");
|
||||
|
||||
assert.equal(true, true, "equal");
|
||||
|
||||
assert.notEqual(true, false, "notEqual");
|
||||
|
||||
assert.throws(makeBlock(assert.notEqual, true, true),
|
||||
ns.Assert.AssertionError, "notEqual");
|
||||
|
||||
assert.throws(makeBlock(assert.strictEqual, 2, "2"),
|
||||
ns.Assert.AssertionError, "strictEqual");
|
||||
|
||||
assert.throws(makeBlock(assert.strictEqual, null, undefined),
|
||||
ns.Assert.AssertionError, "strictEqual");
|
||||
|
||||
assert.notStrictEqual(2, "2", "notStrictEqual");
|
||||
|
||||
// deepEquals joy!
|
||||
// 7.2
|
||||
assert.deepEqual(new Date(2000, 3, 14), new Date(2000, 3, 14), "deepEqual date");
|
||||
|
||||
assert.throws(makeBlock(assert.deepEqual, new Date(), new Date(2000, 3, 14)),
|
||||
ns.Assert.AssertionError,
|
||||
"deepEqual date");
|
||||
|
||||
// 7.3
|
||||
assert.deepEqual(/a/, /a/);
|
||||
assert.deepEqual(/a/g, /a/g);
|
||||
assert.deepEqual(/a/i, /a/i);
|
||||
assert.deepEqual(/a/m, /a/m);
|
||||
assert.deepEqual(/a/igm, /a/igm);
|
||||
assert.throws(makeBlock(assert.deepEqual, /ab/, /a/));
|
||||
assert.throws(makeBlock(assert.deepEqual, /a/g, /a/));
|
||||
assert.throws(makeBlock(assert.deepEqual, /a/i, /a/));
|
||||
assert.throws(makeBlock(assert.deepEqual, /a/m, /a/));
|
||||
assert.throws(makeBlock(assert.deepEqual, /a/igm, /a/im));
|
||||
|
||||
let re1 = /a/;
|
||||
re1.lastIndex = 3;
|
||||
assert.throws(makeBlock(assert.deepEqual, re1, /a/));
|
||||
|
||||
// 7.4
|
||||
assert.deepEqual(4, "4", "deepEqual == check");
|
||||
assert.deepEqual(true, 1, "deepEqual == check");
|
||||
assert.throws(makeBlock(assert.deepEqual, 4, "5"),
|
||||
ns.Assert.AssertionError,
|
||||
"deepEqual == check");
|
||||
|
||||
// 7.5
|
||||
// having the same number of owned properties && the same set of keys
|
||||
assert.deepEqual({a: 4}, {a: 4});
|
||||
assert.deepEqual({a: 4, b: "2"}, {a: 4, b: "2"});
|
||||
assert.deepEqual([4], ["4"]);
|
||||
assert.throws(makeBlock(assert.deepEqual, {a: 4}, {a: 4, b: true}),
|
||||
ns.Assert.AssertionError);
|
||||
assert.deepEqual(["a"], {0: "a"});
|
||||
|
||||
let a1 = [1, 2, 3];
|
||||
let a2 = [1, 2, 3];
|
||||
a1.a = "test";
|
||||
a1.b = true;
|
||||
a2.b = true;
|
||||
a2.a = "test";
|
||||
assert.throws(makeBlock(assert.deepEqual, Object.keys(a1), Object.keys(a2)),
|
||||
ns.Assert.AssertionError);
|
||||
assert.deepEqual(a1, a2);
|
||||
|
||||
let nbRoot = {
|
||||
toString: function() { return this.first + " " + this.last; }
|
||||
};
|
||||
|
||||
function nameBuilder(first, last) {
|
||||
this.first = first;
|
||||
this.last = last;
|
||||
return this;
|
||||
}
|
||||
nameBuilder.prototype = nbRoot;
|
||||
|
||||
function nameBuilder2(first, last) {
|
||||
this.first = first;
|
||||
this.last = last;
|
||||
return this;
|
||||
}
|
||||
nameBuilder2.prototype = nbRoot;
|
||||
|
||||
let nb1 = new nameBuilder("Ryan", "Dahl");
|
||||
let nb2 = new nameBuilder2("Ryan", "Dahl");
|
||||
|
||||
assert.deepEqual(nb1, nb2);
|
||||
|
||||
nameBuilder2.prototype = Object;
|
||||
nb2 = new nameBuilder2("Ryan", "Dahl");
|
||||
assert.throws(makeBlock(assert.deepEqual, nb1, nb2), ns.Assert.AssertionError);
|
||||
|
||||
// String literal + object
|
||||
assert.throws(makeBlock(assert.deepEqual, "a", {}), ns.Assert.AssertionError);
|
||||
|
||||
// Testing the throwing
|
||||
function thrower(errorConstructor) {
|
||||
throw new errorConstructor("test");
|
||||
}
|
||||
let aethrow = makeBlock(thrower, ns.Assert.AssertionError);
|
||||
aethrow = makeBlock(thrower, ns.Assert.AssertionError);
|
||||
|
||||
// the basic calls work
|
||||
assert.throws(makeBlock(thrower, ns.Assert.AssertionError),
|
||||
ns.Assert.AssertionError, "message");
|
||||
assert.throws(makeBlock(thrower, ns.Assert.AssertionError), ns.Assert.AssertionError);
|
||||
assert.throws(makeBlock(thrower, ns.Assert.AssertionError));
|
||||
|
||||
// if not passing an error, catch all.
|
||||
assert.throws(makeBlock(thrower, TypeError));
|
||||
|
||||
// when passing a type, only catch errors of the appropriate type
|
||||
let threw = false;
|
||||
try {
|
||||
assert.throws(makeBlock(thrower, TypeError), ns.Assert.AssertionError);
|
||||
} catch (e) {
|
||||
threw = true;
|
||||
assert.ok(e instanceof TypeError, "type");
|
||||
}
|
||||
assert.equal(true, threw,
|
||||
"Assert.throws with an explicit error is eating extra errors",
|
||||
ns.Assert.AssertionError);
|
||||
threw = false;
|
||||
|
||||
function ifError(err) {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
assert.throws(function() {
|
||||
ifError(new Error("test error"));
|
||||
});
|
||||
|
||||
// make sure that validating using constructor really works
|
||||
threw = false;
|
||||
try {
|
||||
assert.throws(
|
||||
function() {
|
||||
throw ({});
|
||||
},
|
||||
Array
|
||||
);
|
||||
} catch (e) {
|
||||
threw = true;
|
||||
}
|
||||
assert.ok(threw, "wrong constructor validation");
|
||||
|
||||
// use a RegExp to validate error message
|
||||
assert.throws(makeBlock(thrower, TypeError), /test/);
|
||||
|
||||
// use a fn to validate error object
|
||||
assert.throws(makeBlock(thrower, TypeError), function(err) {
|
||||
if ((err instanceof TypeError) && /test/.test(err)) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
// Make sure deepEqual doesn't loop forever on circular refs
|
||||
|
||||
let b = {};
|
||||
b.b = b;
|
||||
|
||||
let c = {};
|
||||
c.b = c;
|
||||
|
||||
let gotError = false;
|
||||
try {
|
||||
assert.deepEqual(b, c);
|
||||
} catch (e) {
|
||||
gotError = true;
|
||||
}
|
||||
|
||||
dump("All OK\n");
|
||||
assert.ok(gotError);
|
||||
|
||||
function testAssertionMessage(actual, expected) {
|
||||
try {
|
||||
assert.equal(actual, "");
|
||||
} catch (e) {
|
||||
assert.equal(e.toString(),
|
||||
["AssertionError:", expected, "==", '""'].join(" "));
|
||||
}
|
||||
}
|
||||
testAssertionMessage(undefined, '"undefined"');
|
||||
testAssertionMessage(null, "null");
|
||||
testAssertionMessage(true, "true");
|
||||
testAssertionMessage(false, "false");
|
||||
testAssertionMessage(0, "0");
|
||||
testAssertionMessage(100, "100");
|
||||
testAssertionMessage(NaN, '"NaN"');
|
||||
testAssertionMessage(Infinity, '"Infinity"');
|
||||
testAssertionMessage(-Infinity, '"-Infinity"');
|
||||
testAssertionMessage("", '""');
|
||||
testAssertionMessage("foo", '"foo"');
|
||||
testAssertionMessage([], "[]");
|
||||
testAssertionMessage([1, 2, 3], "[1,2,3]");
|
||||
testAssertionMessage(/a/, '"/a/"');
|
||||
testAssertionMessage(/abc/gim, '"/abc/gim"');
|
||||
testAssertionMessage(function f() {}, '"function f() {}"');
|
||||
testAssertionMessage({}, "{}");
|
||||
testAssertionMessage({a: undefined, b: null}, '{"a":"undefined","b":null}');
|
||||
testAssertionMessage({a: NaN, b: Infinity, c: -Infinity},
|
||||
'{"a":"NaN","b":"Infinity","c":"-Infinity"}');
|
||||
|
||||
// https://github.com/joyent/node/issues/2893
|
||||
try {
|
||||
assert.throws(function () {
|
||||
ifError(null);
|
||||
});
|
||||
} catch (e) {
|
||||
threw = true;
|
||||
assert.equal(e.message, "Missing expected exception..");
|
||||
}
|
||||
assert.ok(threw);
|
||||
|
||||
// https://github.com/joyent/node/issues/5292
|
||||
try {
|
||||
assert.equal(1, 2);
|
||||
} catch (e) {
|
||||
assert.equal(e.toString().split("\n")[0], "AssertionError: 1 == 2")
|
||||
}
|
||||
|
||||
try {
|
||||
assert.equal(1, 2, "oh no");
|
||||
} catch (e) {
|
||||
assert.equal(e.toString().split("\n")[0], "AssertionError: oh no")
|
||||
}
|
||||
|
||||
// Export Assert.jsm methods to become globally accessible.
|
||||
export_assertions();
|
||||
|
||||
// Test XPCShell-test integration:
|
||||
ok(true, "OK, this went well");
|
||||
deepEqual(/a/g, /a/g, "deep equal should work on RegExp");
|
||||
deepEqual(/a/igm, /a/igm, "deep equal should work on RegExp");
|
||||
deepEqual({a: 4, b: "1"}, {b: "1", a: 4}, "deep equal should work on regular Object");
|
||||
deepEqual(a1, a2, "deep equal should work on Array with Object properties");
|
||||
}
|
5
testing/modules/tests/xpcshell/xpcshell.ini
Normal file
5
testing/modules/tests/xpcshell/xpcshell.ini
Normal file
@ -0,0 +1,5 @@
|
||||
[DEFAULT]
|
||||
head =
|
||||
tail =
|
||||
|
||||
[test_assert.js]
|
@ -184,6 +184,15 @@ function _do_quit() {
|
||||
}
|
||||
|
||||
function _format_exception_stack(stack) {
|
||||
if (typeof stack == "object" && stack.caller) {
|
||||
let frame = stack;
|
||||
let strStack = "";
|
||||
while (frame != null) {
|
||||
strStack += frame + "\n";
|
||||
frame = frame.caller;
|
||||
}
|
||||
stack = strStack;
|
||||
}
|
||||
// frame is of the form "fname@file:line"
|
||||
let frame_regexp = new RegExp("(.*)@(.*):(\\d*)", "g");
|
||||
return stack.split("\n").reduce(function(stack_msg, frame) {
|
||||
@ -343,6 +352,24 @@ function _execute_test() {
|
||||
// _TEST_FILE is dynamically defined by <runxpcshelltests.py>.
|
||||
_load_files(_TEST_FILE);
|
||||
|
||||
// Support a common assertion library, Assert.jsm.
|
||||
let Assert = Components.utils.import("resource://testing-common/Assert.jsm", null).Assert;
|
||||
// Pass a custom report function for xpcshell-test style reporting.
|
||||
let assertImpl = new Assert(function(err, message, stack) {
|
||||
if (err) {
|
||||
do_report_result(false, err.message, err.stack);
|
||||
} else {
|
||||
do_report_result(true, message, stack);
|
||||
}
|
||||
});
|
||||
// Allow Assert.jsm methods to be tacked to the current scope.
|
||||
this.export_assertions = function() {
|
||||
for (let func in assertImpl) {
|
||||
this[func] = assertImpl[func].bind(assertImpl);
|
||||
}
|
||||
};
|
||||
this.Assert = assertImpl;
|
||||
|
||||
try {
|
||||
do_test_pending("MAIN run_test");
|
||||
run_test();
|
||||
|
@ -3671,6 +3671,18 @@
|
||||
"n_values": 3,
|
||||
"description": "User actions taken in the plugin notification: 0: allownow 1: allowalways 2: block"
|
||||
},
|
||||
"PLUGINS_INFOBAR_SHOWN": {
|
||||
"kind": "boolean",
|
||||
"description": "Count of when the hidden-plugin infobar was displayed."
|
||||
},
|
||||
"PLUGINS_INFOBAR_BLOCK": {
|
||||
"kind": "boolean",
|
||||
"description": "Count the number of times the user clicked 'block' on the hidden-plugin infobar."
|
||||
},
|
||||
"PLUGINS_INFOBAR_ALLOW": {
|
||||
"kind": "boolean",
|
||||
"description": "Count the number of times the user clicked 'allow' on the hidden-plugin infobar."
|
||||
},
|
||||
"POPUP_NOTIFICATION_MAINACTION_TRIGGERED_MS": {
|
||||
"kind": "linear",
|
||||
"low": 25,
|
||||
|
@ -452,6 +452,7 @@ var PageStyleActor = protocol.ActorClass({
|
||||
// We compute and update the values of margins & co.
|
||||
let style = node.rawNode.ownerDocument.defaultView.getComputedStyle(node.rawNode);
|
||||
for (let prop of [
|
||||
"position",
|
||||
"margin-top",
|
||||
"margin-right",
|
||||
"margin-bottom",
|
||||
|
@ -730,7 +730,7 @@ CssLogic.getSelectors = function CssLogic_getSelectors(aDOMRule)
|
||||
CssLogic.l10n = function(aName) CssLogic._strings.GetStringFromName(aName);
|
||||
|
||||
XPCOMUtils.defineLazyGetter(CssLogic, "_strings", function() Services.strings
|
||||
.createBundle("chrome://browser/locale/devtools/styleinspector.properties"));
|
||||
.createBundle("chrome://global/locale/devtools/styleinspector.properties"));
|
||||
|
||||
/**
|
||||
* Is the given property sheet a content stylesheet?
|
||||
|
@ -32,6 +32,7 @@
|
||||
locale/@AB_CD@/global/datetimepicker.dtd (%chrome/global/datetimepicker.dtd)
|
||||
locale/@AB_CD@/global/dateFormat.properties (%chrome/global/dateFormat.properties)
|
||||
locale/@AB_CD@/global/devtools/debugger.properties (%chrome/global/devtools/debugger.properties)
|
||||
locale/@AB_CD@/global/devtools/styleinspector.properties (%chrome/global/devtools/styleinspector.properties)
|
||||
locale/@AB_CD@/global/dialogOverlay.dtd (%chrome/global/dialogOverlay.dtd)
|
||||
locale/@AB_CD@/global/editMenuOverlay.dtd (%chrome/global/editMenuOverlay.dtd)
|
||||
locale/@AB_CD@/global/filefield.properties (%chrome/global/filefield.properties)
|
||||
|
@ -1461,30 +1461,33 @@ function recursiveRemove(aFile) {
|
||||
* Returns the timestamp and leaf file name of the most recently modified
|
||||
* entry in a directory,
|
||||
* or simply the file's own timestamp if it is not a directory.
|
||||
* Also returns the total number of items (directories and files) visited in the scan
|
||||
*
|
||||
* @param aFile
|
||||
* A non-null nsIFile object
|
||||
* @return [File Name, Epoch time], as described above.
|
||||
* @return [File Name, Epoch time, items visited], as described above.
|
||||
*/
|
||||
function recursiveLastModifiedTime(aFile) {
|
||||
try {
|
||||
let modTime = aFile.lastModifiedTime;
|
||||
let fileName = aFile.leafName;
|
||||
if (aFile.isFile())
|
||||
return [fileName, modTime];
|
||||
return [fileName, modTime, 1];
|
||||
|
||||
if (aFile.isDirectory()) {
|
||||
let entries = aFile.directoryEntries.QueryInterface(Ci.nsIDirectoryEnumerator);
|
||||
let entry;
|
||||
let totalItems = 1;
|
||||
while ((entry = entries.nextFile)) {
|
||||
let [subName, subTime] = recursiveLastModifiedTime(entry);
|
||||
let [subName, subTime, items] = recursiveLastModifiedTime(entry);
|
||||
totalItems += items;
|
||||
if (subTime > modTime) {
|
||||
modTime = subTime;
|
||||
fileName = subName;
|
||||
}
|
||||
}
|
||||
entries.close();
|
||||
return [fileName, modTime];
|
||||
return [fileName, modTime, totalItems];
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
@ -1492,7 +1495,7 @@ function recursiveLastModifiedTime(aFile) {
|
||||
}
|
||||
|
||||
// If the file is something else, just ignore it.
|
||||
return ["", 0];
|
||||
return ["", 0, 0];
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1638,6 +1641,49 @@ var Prefs = {
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to compare JSON saved version of the directory state
|
||||
// with the new state returned by getInstallLocationStates()
|
||||
// Structure is: ordered array of {'name':?, 'addons': {addonID: {'descriptor':?, 'mtime':?} ...}}
|
||||
function directoryStateDiffers(aState, aCache)
|
||||
{
|
||||
// check equality of an object full of addons; fortunately we can destroy the 'aOld' object
|
||||
function addonsMismatch(aNew, aOld) {
|
||||
for (let [id, val] of aNew) {
|
||||
if (!id in aOld)
|
||||
return true;
|
||||
if (val.descriptor != aOld[id].descriptor ||
|
||||
val.mtime != aOld[id].mtime)
|
||||
return true;
|
||||
delete aOld[id];
|
||||
}
|
||||
// make sure aOld doesn't have any extra entries
|
||||
for (let id in aOld)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!aCache)
|
||||
return true;
|
||||
try {
|
||||
let old = JSON.parse(aCache);
|
||||
if (aState.length != old.length)
|
||||
return true;
|
||||
for (let i = 0; i < aState.length; i++) {
|
||||
// conveniently, any missing fields would require a 'true' return, which is
|
||||
// handled by our catch wrapper
|
||||
if (aState[i].name != old[i].name)
|
||||
return true;
|
||||
if (addonsMismatch(aState[i].addons, old[i].addons))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
var XPIProvider = {
|
||||
// An array of known install locations
|
||||
installLocations: null,
|
||||
@ -2178,9 +2224,10 @@ var XPIProvider = {
|
||||
getAddonStates: function XPI_getAddonStates(aLocation) {
|
||||
let addonStates = {};
|
||||
for (let file of aLocation.addonLocations) {
|
||||
let scanStarted = Date.now();
|
||||
let id = aLocation.getIDForLocation(file);
|
||||
let unpacked = 0;
|
||||
let [modFile, modTime] = recursiveLastModifiedTime(file);
|
||||
let [modFile, modTime, items] = recursiveLastModifiedTime(file);
|
||||
addonStates[id] = {
|
||||
descriptor: file.persistentDescriptor,
|
||||
mtime: modTime
|
||||
@ -2196,6 +2243,8 @@ var XPIProvider = {
|
||||
this._mostRecentlyModifiedFile[id] = modFile;
|
||||
this.setTelemetry(id, "unpacked", unpacked);
|
||||
this.setTelemetry(id, "location", aLocation.name);
|
||||
this.setTelemetry(id, "scan_MS", Date.now() - scanStarted);
|
||||
this.setTelemetry(id, "scan_items", items);
|
||||
}
|
||||
|
||||
return addonStates;
|
||||
@ -3372,8 +3421,15 @@ var XPIProvider = {
|
||||
|
||||
// If the install directory state has changed then we must update the database
|
||||
let cache = Prefs.getCharPref(PREF_INSTALL_CACHE, null);
|
||||
// For a little while, gather telemetry on whether the deep comparison
|
||||
// makes a difference
|
||||
if (cache != JSON.stringify(state)) {
|
||||
updateReasons.push("directoryState");
|
||||
if (directoryStateDiffers(state, cache)) {
|
||||
updateReasons.push("directoryState");
|
||||
}
|
||||
else {
|
||||
AddonManagerPrivate.recordSimpleMeasure("XPIDB_startup_state_badCompare", 1);
|
||||
}
|
||||
}
|
||||
|
||||
// If the database doesn't exist and there are add-ons installed then we
|
||||
@ -5500,7 +5556,9 @@ AddonInstall.prototype = {
|
||||
// Update the metadata in the database
|
||||
this.addon._sourceBundle = file;
|
||||
this.addon._installLocation = this.installLocation;
|
||||
let [mFile, mTime] = recursiveLastModifiedTime(file);
|
||||
let scanStarted = Date.now();
|
||||
let [, mTime, scanItems] = recursiveLastModifiedTime(file);
|
||||
let scanTime = Date.now() - scanStarted;
|
||||
this.addon.updateDate = mTime;
|
||||
this.addon.visible = true;
|
||||
if (isUpgrade) {
|
||||
@ -5547,6 +5605,8 @@ AddonInstall.prototype = {
|
||||
}
|
||||
XPIProvider.setTelemetry(this.addon.id, "unpacked", installedUnpacked);
|
||||
XPIProvider.setTelemetry(this.addon.id, "location", this.installLocation.name);
|
||||
XPIProvider.setTelemetry(this.addon.id, "scan_MS", scanTime);
|
||||
XPIProvider.setTelemetry(this.addon.id, "scan_items", scanItems);
|
||||
let loc = this.addon.defaultLocale;
|
||||
if (loc) {
|
||||
XPIProvider.setTelemetry(this.addon.id, "name", loc.name);
|
||||
|
@ -104,6 +104,13 @@ SharedLibraryInfo SharedLibraryInfo::GetInfoForSelf()
|
||||
// no associated phdrs
|
||||
if (strcmp(name, "/dev/ashmem/dalvik-jit-code-cache") != 0)
|
||||
continue;
|
||||
#else
|
||||
if (strcmp(perm, "r-xp") != 0) {
|
||||
// Ignore entries that are writable and/or shared.
|
||||
// At least one graphics driver uses short-lived "rwxs" mappings
|
||||
// (see bug 926734 comment 5), so just checking for 'x' isn't enough.
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
SharedLibrary shlib(start, end, offset, "", name);
|
||||
info.AddSharedLibrary(shlib);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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
|
||||
@ -26,6 +26,7 @@
|
||||
#include "BasicLayers.h"
|
||||
#include "FrameMetrics.h"
|
||||
#include "Windows.Graphics.Display.h"
|
||||
#include "nsNativeDragTarget.h"
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
#include "nsExceptionHandler.h"
|
||||
#endif
|
||||
@ -333,6 +334,28 @@ MetroWidget::IsVisible() const
|
||||
return mView->IsVisible();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MetroWidget::EnableDragDrop(bool aEnable) {
|
||||
if (aEnable) {
|
||||
if (nullptr == mNativeDragTarget) {
|
||||
mNativeDragTarget = new nsNativeDragTarget(this);
|
||||
if (!mNativeDragTarget) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT hr = ::RegisterDragDrop(mWnd, static_cast<LPDROPTARGET>(mNativeDragTarget));
|
||||
return SUCCEEDED(hr) ? NS_OK : NS_ERROR_FAILURE;
|
||||
} else {
|
||||
if (nullptr == mNativeDragTarget) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
HRESULT hr = ::RevokeDragDrop(mWnd);
|
||||
return SUCCEEDED(hr) ? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MetroWidget::IsEnabled(bool *aState)
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/. */
|
||||
@ -34,6 +34,7 @@
|
||||
#include <Windows.ApplicationModel.h>
|
||||
#include <Windows.Applicationmodel.Activation.h>
|
||||
|
||||
class nsNativeDragTarget;
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
@ -94,6 +95,7 @@ public:
|
||||
nsDeviceContext *aContext,
|
||||
nsWidgetInitData *aInitData = nullptr);
|
||||
NS_IMETHOD Destroy();
|
||||
NS_IMETHOD EnableDragDrop(bool aEnable);
|
||||
NS_IMETHOD SetParent(nsIWidget *aNewParent);
|
||||
NS_IMETHOD Show(bool bState);
|
||||
NS_IMETHOD IsVisible(bool & aState);
|
||||
@ -260,4 +262,5 @@ protected:
|
||||
nsDeque mEventQueue;
|
||||
nsDeque mKeyEventQueue;
|
||||
nsRefPtr<APZController> mController;
|
||||
nsRefPtr<nsNativeDragTarget> mNativeDragTarget;
|
||||
};
|
||||
|
@ -2816,6 +2816,11 @@ nsCycleCollector::Shutdown()
|
||||
// Always delete snow white objects.
|
||||
FreeSnowWhite(true);
|
||||
|
||||
#ifdef MOZ_VALGRIND
|
||||
char *e = PR_GetEnv("XPCOM_CC_RUN_DURING_SHUTDOWN");
|
||||
fprintf(stderr, "XPCOM_CC_RUN_DURING_SHUTDOWN = %s\n", e);
|
||||
#endif
|
||||
|
||||
#ifndef DEBUG
|
||||
if (PR_GetEnv("XPCOM_CC_RUN_DURING_SHUTDOWN"))
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user