Merge inbound to central, a=merge

This commit is contained in:
Wes Kocher 2015-09-03 12:20:40 -07:00
commit 67f1a2cfde
87 changed files with 1921 additions and 855 deletions

View File

@ -68,7 +68,6 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
this._mayTrimURLs = this._prefs.getBoolPref("trimURLs");
this._userMadeSearchSuggestionsChoice =
this._prefs.getBoolPref("userMadeSearchSuggestionsChoice");
this._ignoreNextSelect = false;
this.inputField.controllers.insertControllerAt(0, this._copyCutController);
this.inputField.addEventListener("paste", this, false);
@ -854,15 +853,6 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
]]></body>
</method>
<method name="selectTextRange">
<parameter name="aStartIndex"/>
<parameter name="aEndIndex"/>
<body><![CDATA[
this._ignoreNextSelect = true;
this.inputField.setSelectionRange(aStartIndex, aEndIndex);
]]></body>
</method>
<method name="onInput">
<parameter name="aEvent"/>
<body><![CDATA[
@ -1015,20 +1005,16 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
<handler event="dragover" phase="capturing" action="this.onDragOver(event, this);"/>
<handler event="drop" phase="capturing" action="this.onDrop(event, this);"/>
<handler event="select"><![CDATA[
if (this._ignoreNextSelect) {
// If this select event is coming from autocomplete's selectTextRange,
// then we don't need to adjust what's on the selection keyboard here,
// but make sure to reset the flag since this should be a one-time
// suppression.
this._ignoreNextSelect = false;
return;
}
if (!Cc["@mozilla.org/widget/clipboard;1"]
.getService(Ci.nsIClipboard)
.supportsSelectionClipboard())
return;
if (!window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils)
.isHandlingUserInput)
return;
var val = this._getSelectedValueForClipboard();
if (!val)
return;

View File

@ -38,33 +38,14 @@ leak:nr_reg_local_init
leak:r_log_register
leak:nr_reg_set
# Additional WebRTC leak suppressions added for Mochitest 3.
leak:mozilla::TransportLayerDtls::Setup
# Bug 1187424 - DesktopApplication does not free any of its string members.
leak:webrtc::DesktopApplication::
# Bug 1187518 - SCTP leaks in child process while running WebRTC tests.
leak:recv_function_udp
# Bug 1074310 - Very large e10s vp8 leaks, maybe in WebRTC tests.
leak:set_noise_sensitivity
leak:vp8_alloc_compressor_data
leak:vp8_change_config
leak:vp8_lookahead_init
leak:vpx_codec_enc_init_ver
###
### Many leaks only affect some test suites. The suite annotations are not checked.
###
# Bug 981195 - Small leak in the parser. m4
leak:ObjectGroup::fixPlainObjectGroup
# Bug 982111 - WebM is leaking. m1
leak:nestegg_read_packet
# Bug 987385 - Various plugin leaks. m3
leak:mozilla::plugins::PPluginInstanceParent::CallNPP_HandleEvent
leak:mozilla::plugins::PPluginModuleParent::OnCallReceived
@ -89,7 +70,7 @@ leak:_render_glyph_outline
# Bug 1023548 - Small leak under SECITEM_AllocItem_Util. bc1, bc3
leak:SECITEM_AllocItem_Util
# This is a one-time leak, so it is probably okay to ignore. bc1, oth
# This is a one-time leak, so it is probably okay to ignore. bc3, oth
leak:GlobalPrinters::InitializeGlobalPrinters
leak:nsPSPrinterList::GetPrinterList

View File

@ -23,10 +23,22 @@ using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::dom::workers;
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(PerformanceObserver,
mOwner,
mPerformance,
mCallback)
NS_IMPL_CYCLE_COLLECTION_CLASS(PerformanceObserver)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(PerformanceObserver)
tmp->Disconnect();
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCallback)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPerformance)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwner)
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(PerformanceObserver)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCallback)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPerformance)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(PerformanceObserver)
NS_IMPL_CYCLE_COLLECTING_ADDREF(PerformanceObserver)
NS_IMPL_CYCLE_COLLECTING_RELEASE(PerformanceObserver)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PerformanceObserver)
@ -95,7 +107,22 @@ PerformanceObserver::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProt
}
void
PerformanceObserver::Notify(PerformanceEntry* aEntry)
PerformanceObserver::Notify()
{
if (mQueuedEntries.IsEmpty()) {
return;
}
nsRefPtr<PerformanceObserverEntryList> list =
new PerformanceObserverEntryList(this, mQueuedEntries);
ErrorResult rv;
mCallback->Call(this, *list, *this, rv);
NS_WARN_IF(rv.Failed());
mQueuedEntries.Clear();
}
void
PerformanceObserver::QueueEntry(PerformanceEntry* aEntry)
{
MOZ_ASSERT(aEntry);
@ -105,12 +132,7 @@ PerformanceObserver::Notify(PerformanceEntry* aEntry)
return;
}
nsRefPtr<PerformanceObserverEntryList> list = new PerformanceObserverEntryList(this);
list->AppendEntry(aEntry);
ErrorResult rv;
mCallback->Call(this, *list, *this, rv);
NS_WARN_IF(rv.Failed());
mQueuedEntries.AppendElement(aEntry);
}
static nsString sValidTypeNames[7] = {

View File

@ -59,7 +59,8 @@ public:
void Disconnect();
void Notify(PerformanceEntry* entry);
void Notify();
void QueueEntry(PerformanceEntry* aEntry);
private:
~PerformanceObserver();
@ -69,6 +70,7 @@ private:
nsRefPtr<PerformanceBase> mPerformance;
nsTArray<nsString> mEntryTypes;
bool mConnected;
nsTArray<nsRefPtr<PerformanceEntry>> mQueuedEntries;
};
} // namespace dom

View File

@ -94,10 +94,3 @@ PerformanceObserverEntryList::GetEntriesByName(
}
}
}
void
PerformanceObserverEntryList::AppendEntry(PerformanceEntry* aEntry)
{
mEntries.AppendElement(aEntry);
}

View File

@ -26,8 +26,11 @@ class PerformanceObserverEntryList final : public nsISupports,
~PerformanceObserverEntryList();
public:
explicit PerformanceObserverEntryList(nsISupports* aOwner)
PerformanceObserverEntryList(nsISupports* aOwner,
nsTArray<nsRefPtr<PerformanceEntry>>&
aEntries)
: mOwner(aOwner)
, mEntries(aEntries)
{
}
@ -50,8 +53,6 @@ public:
const Optional<nsAString>& aEntryType,
nsTArray<nsRefPtr<PerformanceEntry>>& aRetval);
void AppendEntry(PerformanceEntry* aEntry);
private:
nsCOMPtr<nsISupports> mOwner;
nsTArray<nsRefPtr<PerformanceEntry>> mEntries;

View File

@ -7915,15 +7915,13 @@ nsDocument::GetViewportInfo(const ScreenIntSize& aDisplaySize)
ScreenSize viewportSize(viewportWidth, viewportWidth * aspectRatio);
return nsViewportInfo(RoundedToInt(viewportSize),
CSSToScreenScale(scaleToFit),
/*allowZoom*/false,
/*allowDoubleTapZoom*/ false);
/*allowZoom*/ true);
}
if (!gfxPrefs::MetaViewportEnabled()) {
return nsViewportInfo(aDisplaySize,
defaultScale,
/*allowZoom*/ false,
/*allowDoubleTapZoom*/ false);
/*allowZoom*/ false);
}
// In cases where the width of the CSS viewport is less than or equal to the width
@ -7934,13 +7932,7 @@ nsDocument::GetViewportInfo(const ScreenIntSize& aDisplaySize)
case DisplayWidthHeight:
return nsViewportInfo(aDisplaySize,
defaultScale,
/*allowZoom*/ true,
/*allowDoubleTapZoom*/ true);
case DisplayWidthHeightNoZoom:
return nsViewportInfo(aDisplaySize,
defaultScale,
/*allowZoom*/ false,
/*allowDoubleTapZoom*/ false);
/*allowZoom*/ true);
case Unknown:
{
nsAutoString viewport;
@ -7962,8 +7954,7 @@ nsDocument::GetViewportInfo(const ScreenIntSize& aDisplaySize)
mViewportType = DisplayWidthHeight;
return nsViewportInfo(aDisplaySize,
defaultScale,
/*allowZoom*/true,
/*allowDoubleTapZoom*/false);
/*allowZoom*/true);
}
}
}
@ -7974,8 +7965,7 @@ nsDocument::GetViewportInfo(const ScreenIntSize& aDisplaySize)
mViewportType = DisplayWidthHeight;
return nsViewportInfo(aDisplaySize,
defaultScale,
/*allowZoom*/true,
/*allowDoubleTapZoom*/false);
/*allowZoom*/true);
}
}
@ -8049,7 +8039,6 @@ nsDocument::GetViewportInfo(const ScreenIntSize& aDisplaySize)
(userScalable.EqualsLiteral("false"))) {
mAllowZoom = false;
}
mAllowDoubleTapZoom = mAllowZoom;
mScaleStrEmpty = scaleStr.IsEmpty();
mWidthStrEmpty = widthStr.IsEmpty();
@ -8060,6 +8049,24 @@ nsDocument::GetViewportInfo(const ScreenIntSize& aDisplaySize)
}
case Specified:
default:
LayoutDeviceToScreenScale effectiveMinScale = mScaleMinFloat;
LayoutDeviceToScreenScale effectiveMaxScale = mScaleMaxFloat;
bool effectiveValidMaxScale = mValidMaxScale;
bool effectiveAllowZoom = mAllowZoom;
if (gfxPrefs::ForceUserScalable()) {
// If the pref to force user-scalable is enabled, we ignore the values
// from the meta-viewport tag for these properties and just assume they
// allow the page to be scalable. Note in particular that this code is
// in the "Specified" branch of the enclosing switch statement, so that
// calls to GetViewportInfo always use the latest value of the
// ForceUserScalable pref. Other codepaths that return nsViewportInfo
// instances are all consistent with ForceUserScalable() already.
effectiveMinScale = kViewportMinScale;
effectiveMaxScale = kViewportMaxScale;
effectiveValidMaxScale = true;
effectiveAllowZoom = true;
}
CSSSize size = mViewportSize;
if (!mValidWidth) {
@ -8082,8 +8089,8 @@ nsDocument::GetViewportInfo(const ScreenIntSize& aDisplaySize)
}
CSSToScreenScale scaleFloat = mScaleFloat * layoutDeviceScale;
CSSToScreenScale scaleMinFloat = mScaleMinFloat * layoutDeviceScale;
CSSToScreenScale scaleMaxFloat = mScaleMaxFloat * layoutDeviceScale;
CSSToScreenScale scaleMinFloat = effectiveMinScale * layoutDeviceScale;
CSSToScreenScale scaleMaxFloat = effectiveMaxScale * layoutDeviceScale;
if (mAutoSize) {
// aDisplaySize is in screen pixels; convert them to CSS pixels for the viewport size.
@ -8108,14 +8115,14 @@ nsDocument::GetViewportInfo(const ScreenIntSize& aDisplaySize)
CSSSize displaySize = ScreenSize(aDisplaySize) / scaleFloat;
size.width = std::max(size.width, displaySize.width);
size.height = std::max(size.height, displaySize.height);
} else if (mValidMaxScale) {
} else if (effectiveValidMaxScale) {
CSSSize displaySize = ScreenSize(aDisplaySize) / scaleMaxFloat;
size.width = std::max(size.width, displaySize.width);
size.height = std::max(size.height, displaySize.height);
}
return nsViewportInfo(scaleFloat, scaleMinFloat, scaleMaxFloat, size,
mAutoSize, mAllowZoom, mAllowDoubleTapZoom);
mAutoSize, effectiveAllowZoom);
}
}

View File

@ -1850,7 +1850,6 @@ private:
enum ViewportType {
DisplayWidthHeight,
DisplayWidthHeightNoZoom,
Specified,
Unknown
};

View File

@ -812,6 +812,7 @@ NS_IMPL_RELEASE_INHERITED(PerformanceBase, DOMEventTargetHelper)
PerformanceBase::PerformanceBase()
: mResourceTimingBufferSize(kDefaultResourceTimingBufferSize)
, mPendingNotificationObserversTask(false)
{
MOZ_ASSERT(!NS_IsMainThread());
}
@ -819,6 +820,7 @@ PerformanceBase::PerformanceBase()
PerformanceBase::PerformanceBase(nsPIDOMWindow* aWindow)
: DOMEventTargetHelper(aWindow)
, mResourceTimingBufferSize(kDefaultResourceTimingBufferSize)
, mPendingNotificationObserversTask(false)
{
MOZ_ASSERT(NS_IsMainThread());
}
@ -1050,9 +1052,7 @@ PerformanceBase::InsertUserEntry(PerformanceEntry* aEntry)
mUserEntries.InsertElementSorted(aEntry,
PerformanceEntryComparator());
NS_OBSERVER_ARRAY_NOTIFY_XPCOM_OBSERVERS(mObservers,
PerformanceObserver,
Notify, (aEntry));
QueueEntry(aEntry);
}
void
@ -1076,9 +1076,7 @@ PerformanceBase::InsertResourceEntry(PerformanceEntry* aEntry)
// call onresourcetimingbufferfull
DispatchBufferFullEvent();
}
NS_OBSERVER_ARRAY_NOTIFY_XPCOM_OBSERVERS(mObservers,
PerformanceObserver,
Notify, (aEntry));
QueueEntry(aEntry);
}
void
@ -1092,3 +1090,75 @@ PerformanceBase::RemoveObserver(PerformanceObserver* aObserver)
{
mObservers.RemoveElement(aObserver);
}
void
PerformanceBase::NotifyObservers()
{
mPendingNotificationObserversTask = false;
NS_OBSERVER_ARRAY_NOTIFY_XPCOM_OBSERVERS(mObservers,
PerformanceObserver,
Notify, ());
}
void
PerformanceBase::CancelNotificationObservers()
{
mPendingNotificationObserversTask = false;
}
class NotifyObserversTask final : public nsCancelableRunnable
{
public:
explicit NotifyObserversTask(PerformanceBase* aPerformance)
: mPerformance(aPerformance)
{
MOZ_ASSERT(mPerformance);
}
NS_IMETHOD Run() override
{
MOZ_ASSERT(mPerformance);
mPerformance->NotifyObservers();
return NS_OK;
}
NS_IMETHOD Cancel() override
{
mPerformance->CancelNotificationObservers();
mPerformance = nullptr;
return NS_OK;
}
private:
~NotifyObserversTask()
{
}
nsRefPtr<PerformanceBase> mPerformance;
};
void
PerformanceBase::RunNotificationObserversTask()
{
mPendingNotificationObserversTask = true;
nsCOMPtr<nsIRunnable> task = new NotifyObserversTask(this);
nsresult rv = NS_DispatchToCurrentThread(task);
if (NS_WARN_IF(NS_FAILED(rv))) {
mPendingNotificationObserversTask = false;
}
}
void
PerformanceBase::QueueEntry(PerformanceEntry* aEntry)
{
if (mObservers.IsEmpty()) {
return;
}
NS_OBSERVER_ARRAY_NOTIFY_XPCOM_OBSERVERS(mObservers,
PerformanceObserver,
QueueEntry, (aEntry));
if (!mPendingNotificationObserversTask) {
RunNotificationObserversTask();
}
}

View File

@ -325,6 +325,8 @@ public:
void AddObserver(PerformanceObserver* aObserver);
void RemoveObserver(PerformanceObserver* aObserver);
void NotifyObservers();
void CancelNotificationObservers();
protected:
virtual ~PerformanceBase();
@ -358,6 +360,9 @@ protected:
void LogEntry(PerformanceEntry* aEntry, const nsACString& aOwner) const;
void TimingNotification(PerformanceEntry* aEntry, const nsACString& aOwner, uint64_t epoch);
void RunNotificationObserversTask();
void QueueEntry(PerformanceEntry* aEntry);
nsTObserverArray<PerformanceObserver*> mObservers;
private:
@ -366,6 +371,7 @@ private:
uint64_t mResourceTimingBufferSize;
static const uint64_t kDefaultResourceTimingBufferSize = 150;
bool mPendingNotificationObserversTask;
};
// Script "performance" object

View File

@ -26,16 +26,11 @@ class MOZ_STACK_CLASS nsViewportInfo
public:
nsViewportInfo(const mozilla::ScreenIntSize& aDisplaySize,
const mozilla::CSSToScreenScale& aDefaultZoom,
bool aAllowZoom,
bool aAllowDoubleTapZoom) :
bool aAllowZoom) :
mDefaultZoom(aDefaultZoom),
mAutoSize(true),
mAllowZoom(aAllowZoom),
mAllowDoubleTapZoom(aAllowDoubleTapZoom)
mAllowZoom(aAllowZoom)
{
// Don't allow double-tap zooming unless zooming is also allowed
MOZ_ASSERT(mAllowZoom || !mAllowDoubleTapZoom);
mSize = mozilla::ScreenSize(aDisplaySize) / mDefaultZoom;
mozilla::CSSToLayoutDeviceScale pixelRatio(1.0f);
mMinZoom = pixelRatio * kViewportMinScale;
@ -48,19 +43,14 @@ class MOZ_STACK_CLASS nsViewportInfo
const mozilla::CSSToScreenScale& aMaxZoom,
const mozilla::CSSSize& aSize,
bool aAutoSize,
bool aAllowZoom,
bool aAllowDoubleTapZoom) :
bool aAllowZoom) :
mDefaultZoom(aDefaultZoom),
mMinZoom(aMinZoom),
mMaxZoom(aMaxZoom),
mSize(aSize),
mAutoSize(aAutoSize),
mAllowZoom(aAllowZoom),
mAllowDoubleTapZoom(aAllowDoubleTapZoom)
mAllowZoom(aAllowZoom)
{
// Don't allow double-tap zooming unless zooming is also allowed
MOZ_ASSERT(mAllowZoom || !mAllowDoubleTapZoom);
ConstrainViewportValues();
}
@ -73,9 +63,6 @@ class MOZ_STACK_CLASS nsViewportInfo
bool IsAutoSizeEnabled() const { return mAutoSize; }
bool IsZoomAllowed() const { return mAllowZoom; }
bool IsDoubleTapZoomAllowed() const { return mAllowDoubleTapZoom; }
void SetAllowDoubleTapZoom(bool aAllowDoubleTapZoom) { mAllowDoubleTapZoom = aAllowDoubleTapZoom; }
private:
@ -107,11 +94,6 @@ class MOZ_STACK_CLASS nsViewportInfo
// Whether or not the user can zoom in and out on the page. Default is true.
bool mAllowZoom;
// Whether or not the user can double-tap to zoom in. When this is disabled
// we can dispatch click events faster on a single tap because we don't have
// to wait to detect the double-tap
bool mAllowDoubleTapZoom;
};
#endif

View File

@ -10,9 +10,9 @@
<script>
'use strict';
[
"async_test", "test", "setup",
"promise_test", "test", "setup",
"assert_true", "assert_equals", "assert_array_equals",
"assert_throws"
"assert_throws", "assert_unreached"
].forEach(func => {
window[func] = opener[func].bind(opener);
});
@ -29,49 +29,43 @@ function done() {
<body>
<div id="log"></div>
<script>
function promiseXHR(aUrl) {
return new Promise(resolve => {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onload = resolve;
xmlhttp.open("get", aUrl, true);
xmlhttp.send();
});
function makeXHR(aUrl) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("get", aUrl, true);
xmlhttp.send();
}
async_test(t => {
performance.clearResourceTimings();
promise_test(t => {
var promise = new Promise(resolve => {
performance.clearResourceTimings();
var observedEntryList;
var observedEntries = [];
var observer = new PerformanceObserver(list => {
list.getEntries().forEach(entry => observedEntries.push(entry));
observedEntryList = list;
var observer = new PerformanceObserver(list => resolve(list));
observer.observe({entryTypes: ['resource']});
t.add_cleanup(() => observer.disconnect());
});
observer.observe({entryTypes: ['resource']});
t.add_cleanup(() => observer.disconnect());
assert_equals(observedEntries.length, 0);
makeXHR("test-data.json");
promiseXHR("test-data.json").then(t.step_func_done(() => {
assert_equals(observedEntries.length, 1);
assert_array_equals(observedEntries,
return promise.then(list => {
assert_equals(list.getEntries().length, 1);
assert_array_equals(list.getEntries(),
performance.getEntriesByType("resource"),
"Observed 'resource' entries should equal to entries obtained by getEntriesByType.");
// getEntries filtering tests
assert_array_equals(observedEntryList.getEntries({name: "http://mochi.test:8888/tests/dom/base/test/test-data.json"}),
assert_array_equals(list.getEntries({name: "http://mochi.test:8888/tests/dom/base/test/test-data.json"}),
performance.getEntriesByName("http://mochi.test:8888/tests/dom/base/test/test-data.json"),
"getEntries with name filter should return correct results.");
assert_array_equals(observedEntryList.getEntries({entryType: "resource"}),
assert_array_equals(list.getEntries({entryType: "resource"}),
performance.getEntriesByType("resource"),
"getEntries with entryType filter should return correct results.");
assert_array_equals(observedEntryList.getEntries({initiatorType: "xmlhttprequest"}),
assert_array_equals(list.getEntries({initiatorType: "xmlhttprequest"}),
performance.getEntriesByType("resource"),
"getEntries with initiatorType filter should return correct results.");
assert_array_equals(observedEntryList.getEntries({initiatorType: "link"}),
assert_array_equals(list.getEntries({initiatorType: "link"}),
[],
"getEntries with non-existent initiatorType filter should return an empty array.");
}));
});
}, "resource-timing test");
done();

View File

@ -35,213 +35,192 @@ test(t => {
}, "obsrve() should throw TypeError exception if 'entryTypes' attribute value is invalid.");
}, "Test that PerformanceObserver.observe throws exception");
test(t => {
performance.clearMarks();
performance.clearMeasures();
function promiseObserve(test, options) {
return new Promise(resolve => {
performance.clearMarks();
performance.clearMeasures();
var observedEntries = [];
var observer = new PerformanceObserver(list => {
list.getEntries().forEach(entry => observedEntries.push(entry));
var observer = new PerformanceObserver(list => resolve(list));
observer.observe(options);
test.add_cleanup(() => observer.disconnect());
});
observer.observe({entryTypes: ['mark', 'measure']});
t.add_cleanup(() => observer.disconnect());
}
assert_equals(observedEntries.length, 0,
"User timing entries should never be observed.");
assert_equals(performance.getEntriesByType("mark").length, 0,
"There should be no 'mark' entries.");
assert_equals(performance.getEntriesByType("measure").length, 0,
"There should be no 'measure' entries.");
promise_test(t => {
var promise = promiseObserve(t, {entryTypes: ['mark', 'measure']});
performance.mark("test-start");
performance.mark("test-end");
performance.measure("test-measure", "test-start", "test-end");
assert_equals(observedEntries.length, 3,
"There should be three observed entries.");
return promise.then(list => {
assert_equals(list.getEntries().length, 3,
"There should be three observed entries.");
var markEntries = observedEntries.filter(entry => {
return entry.entryType == "mark";
});
assert_array_equals(markEntries, performance.getEntriesByType("mark"),
"Observed 'mark' entries should equal to entries obtained by getEntriesByType.");
var markEntries = list.getEntries().filter(entry => {
return entry.entryType == "mark";
});
assert_array_equals(markEntries, performance.getEntriesByType("mark"),
"Observed 'mark' entries should equal to entries obtained by getEntriesByType.");
var measureEntries = observedEntries.filter(entry => {
return entry.entryType == "measure";
var measureEntries = list.getEntries().filter(entry => {
return entry.entryType == "measure";
});
assert_array_equals(measureEntries, performance.getEntriesByType("measure"),
"Observed 'measure' entries should equal to entries obtained by getEntriesByType.");
});
assert_array_equals(measureEntries, performance.getEntriesByType("measure"),
"Observed 'measure' entries should equal to entries obtained by getEntriesByType.");
}, "Test for user-timing with PerformanceObserver");
test(t => {
performance.clearMarks();
performance.clearMeasures();
promise_test(t => {
var promise = new Promise((resolve, reject) => {
performance.clearMarks();
performance.clearMeasures();
var observedEntries = [];
var observer = new PerformanceObserver(list => {
list.getEntries().forEach(entry => observedEntries.push(entry));
var observer = new PerformanceObserver(list => reject(list));
observer.observe({entryTypes: ['mark', 'measure']});
observer.disconnect();
t.step_timeout(resolve, 100);
});
observer.observe({entryTypes: ['mark', 'measure']});
observer.disconnect();
assert_equals(observedEntries.length, 0,
"User timing entries should be never observed.");
performance.mark("test-start");
performance.mark("test-end");
performance.measure("test-measure", "test-start", "test-end");
assert_equals(performance.getEntriesByType("mark").length, 2);
assert_equals(performance.getEntriesByType("measure").length, 1);
return promise.then(() => {
assert_equals(performance.getEntriesByType("mark").length, 2);
assert_equals(performance.getEntriesByType("measure").length, 1);
}, list => {
assert_unreached("Observer callback should never be called.");
});
assert_equals(observedEntries.length, 0,
"User timing entries should be never observed after disconnecting observer.");
}, "Nothing should be notified after disconnecting observer");
test(t => {
performance.clearMarks();
performance.clearMeasures();
var observedEntryList;
var observer = new PerformanceObserver(list => {
observedEntryList = list;
});
observer.observe({entryTypes: ['mark']});
t.add_cleanup(() => observer.disconnect());
promise_test(t => {
var promise = promiseObserve(t, {entryTypes: ['mark']});
performance.mark("test");
assert_array_equals(observedEntryList.getEntries({"entryType": "mark"}),
performance.getEntriesByType("mark"),
"getEntries with entryType filter should return correct results.");
assert_array_equals(observedEntryList.getEntries({"name": "test"}),
performance.getEntriesByName("test"),
"getEntries with name filter should return correct results.");
return promise.then(list => {
assert_array_equals(list.getEntries({"entryType": "mark"}),
performance.getEntriesByType("mark"),
"getEntries with entryType filter should return correct results.");
assert_array_equals(observedEntryList.getEntries({"name": "test",
"entryType": "mark"}),
performance.getEntriesByName("test"),
"getEntries with name and entryType filter should return correct results.");
assert_array_equals(list.getEntries({"name": "test"}),
performance.getEntriesByName("test"),
"getEntries with name filter should return correct results.");
assert_array_equals(observedEntryList.getEntries({"name": "invalid"}),
[],
"getEntries with non-existent name filter should return an empty array.");
assert_array_equals(list.getEntries({"name": "test",
"entryType": "mark"}),
performance.getEntriesByName("test"),
"getEntries with name and entryType filter should return correct results.");
assert_array_equals(observedEntryList.getEntries({"name": "test",
"entryType": "measure"}),
[],
"getEntries with name filter and non-existent entryType should return an empty array.");
assert_array_equals(list.getEntries({"name": "invalid"}),
[],
"getEntries with non-existent name filter should return an empty array.");
assert_array_equals(observedEntryList.getEntries({"name": "invalid",
"entryType": "mark"}),
[],
"getEntries with non-existent name and entryType filter should return an empty array.");
assert_array_equals(list.getEntries({"name": "test",
"entryType": "measure"}),
[],
"getEntries with name filter and non-existent entryType should return an empty array.");
assert_array_equals(observedEntryList.getEntries({initiatorType: "xmlhttprequest"}),
[],
"getEntries with initiatorType filter should return an empty array.");
assert_array_equals(list.getEntries({"name": "invalid",
"entryType": "mark"}),
[],
"getEntries with non-existent name and entryType filter should return an empty array.");
assert_array_equals(list.getEntries({initiatorType: "xmlhttprequest"}),
[],
"getEntries with initiatorType filter should return an empty array.");
});
}, "Test for PerformanceObserverEntryList.getEntries");
test(t => {
performance.clearMarks();
performance.clearMeasures();
var observedEntryList;
var observer = new PerformanceObserver(list => {
observedEntryList = list;
});
observer.observe({entryTypes: ['mark', 'measure']});
t.add_cleanup(() => observer.disconnect());
promise_test(t => {
var promise = promiseObserve(t, {entryTypes: ['mark', 'measure']});
performance.mark("test");
assert_array_equals(observedEntryList.getEntriesByType("mark"),
performance.getEntriesByType("mark"));
performance.measure("test-measure", "test", "test");
assert_array_equals(observedEntryList.getEntriesByType("measure"),
performance.getEntriesByType("measure"));
return promise.then(list => {
assert_array_equals(list.getEntriesByType("mark"),
performance.getEntriesByType("mark"));
assert_array_equals(list.getEntriesByType("measure"),
performance.getEntriesByType("measure"));
});
}, "Test for PerformanceObserverEntryList.getEntriesByType");
test(t => {
performance.clearMarks();
performance.clearMeasures();
var observedEntryList;
var observer = new PerformanceObserver(list => {
observedEntryList = list;
});
observer.observe({entryTypes: ['mark', 'measure']});
t.add_cleanup(() => observer.disconnect());
promise_test(t => {
var promise = promiseObserve(t, {entryTypes: ['mark', 'measure']});
performance.mark("test");
assert_array_equals(observedEntryList.getEntriesByName("test"),
performance.getEntriesByName("test"));
performance.measure("test-measure", "test", "test");
assert_array_equals(observedEntryList.getEntriesByName("test-measure"),
performance.getEntriesByName("test-measure"));
return promise.then(list => {
assert_array_equals(list.getEntriesByName("test"),
performance.getEntriesByName("test"));
assert_array_equals(list.getEntriesByName("test-measure"),
performance.getEntriesByName("test-measure"));
});
}, "Test for PerformanceObserverEntryList.getEntriesByName");
test(t => {
performance.clearMarks();
performance.clearMeasures();
promise_test(t => {
var promise = new Promise(resolve => {
performance.clearMarks();
performance.clearMeasures();
var observedEntries = [];
var observer = new PerformanceObserver(list => {
list.getEntries().forEach(entry => observedEntries.push(entry));
var observer = new PerformanceObserver(list => resolve(list));
observer.observe({entryTypes: ['mark', 'measure']});
observer.observe({entryTypes: ['mark', 'measure']});
t.add_cleanup(() => observer.disconnect());
});
observer.observe({entryTypes: ['mark', 'measure']});
observer.observe({entryTypes: ['mark', 'measure']});
t.add_cleanup(() => observer.disconnect());
performance.mark("test-start");
performance.mark("test-end");
performance.measure("test-measure", "test-start", "test-end");
assert_equals(observedEntries.length, 3,
"Observed user timing entries should have only three entries.");
return promise.then(list => {
assert_equals(list.getEntries().length, 3,
"Observed user timing entries should have only three entries.");
});
}, "Test that invoking observe method twice affects nothing");
test(t => {
performance.clearMarks();
performance.clearMeasures();
promise_test(t => {
var promise = new Promise(resolve => {
performance.clearMarks();
performance.clearMeasures();
var observedEntries = [];
var observer = new PerformanceObserver(list => {
list.getEntries().forEach(entry => observedEntries.push(entry));
var observer = new PerformanceObserver(list => resolve(list));
observer.observe({entryTypes: ['mark', 'measure']});
observer.observe({entryTypes: ['mark']});
t.add_cleanup(() => observer.disconnect());
});
observer.observe({entryTypes: ['mark', 'measure']});
observer.observe({entryTypes: ['mark']});
t.add_cleanup(() => observer.disconnect());
performance.mark("test-start");
performance.mark("test-end");
performance.measure("test-measure", "test-start", "test-end");
assert_equals(observedEntries.length, 2,
"Observed user timing entries should have only two entries.");
return promise.then(list => {
assert_equals(list.getEntries().length, 2,
"Observed user timing entries should have only two entries.");
});
}, "Test that observing filter is replaced by a new filter");
test(t => {
performance.clearMarks();
performance.clearMeasures();
promise_test(t => {
var promise = new Promise(resolve => {
performance.clearMarks();
performance.clearMeasures();
var observedEntries = [];
var observer = new PerformanceObserver(list => {
list.getEntries().forEach(entry => observedEntries.push(entry));
var observer = new PerformanceObserver(list => resolve(list));
observer.observe({entryTypes: ['mark']});
observer.observe({entryTypes: ['measure']});
t.add_cleanup(() => observer.disconnect());
});
observer.observe({entryTypes: ['mark']});
observer.observe({entryTypes: ['measure']});
t.add_cleanup(() => observer.disconnect());
performance.mark("test-start");
performance.mark("test-end");
performance.measure("test-measure", "test-start", "test-end");
assert_equals(observedEntries.length, 1,
"Observed user timing entries should have only 1 entries.");
return promise.then(list => {
assert_equals(list.getEntries().length, 1,
"Observed user timing entries should have only 1 entries.");
});
}, "Test that observing filter is replaced by a new filter");

View File

@ -367,7 +367,7 @@ public:
: mRecorder(aRecorder)
, mTimeSlice(aTimeSlice)
, mStopIssued(false)
, mCanRetrieveData(false)
, mIsStartEventFired(false)
, mIsRegisterProfiler(false)
, mNeedSessionEndTask(true)
{
@ -494,10 +494,10 @@ private:
if (!encodedBuf[i].IsEmpty()) {
mEncodedBufferCache->AppendBuffer(encodedBuf[i]);
// Fire the start event when encoded data is available.
if (!mCanRetrieveData) {
if (!mIsStartEventFired) {
NS_DispatchToMainThread(
new DispatchStartEventRunnable(this, NS_LITERAL_STRING("start")));
mCanRetrieveData = true;
mIsStartEventFired = true;
}
}
}
@ -510,6 +510,12 @@ private:
pushBlob = true;
}
if (pushBlob || aForceFlush) {
// Fire the start event before the blob.
if (!mIsStartEventFired) {
NS_DispatchToMainThread(
new DispatchStartEventRunnable(this, NS_LITERAL_STRING("start")));
mIsStartEventFired = true;
}
if (NS_FAILED(NS_DispatchToMainThread(new EncoderErrorNotifierRunnable(this)))) {
MOZ_ASSERT(false, "NS_DispatchToMainThread EncoderErrorNotifierRunnable failed");
}
@ -639,6 +645,9 @@ private:
{
MOZ_ASSERT(NS_IsMainThread());
CleanupStreams();
NS_DispatchToMainThread(
new DispatchStartEventRunnable(this, NS_LITERAL_STRING("start")));
if (NS_FAILED(rv)) {
nsCOMPtr<nsIRunnable> runnable =
NS_NewRunnableMethodWithArg<nsresult>(mRecorder,
@ -724,8 +733,8 @@ private:
const int32_t mTimeSlice;
// Indicate this session's stop has been called.
bool mStopIssued;
// Indicate session has encoded data. This can be changed in recording thread.
bool mCanRetrieveData;
// Indicate the session had fire start event. Encoding thread only.
bool mIsStartEventFired;
// The register flag for "Media_Encoder" thread to profiler
bool mIsRegisterProfiler;
// False if the InitEncoder called successfully, ensure the

View File

@ -1321,14 +1321,6 @@ MediaStreamGraphImpl::ProduceDataForStreamsBlockByBlock(uint32_t aStreamIndex,
ps->ProcessInput(t, next, (next == aTo) ? ProcessedMediaStream::ALLOW_FINISH : 0);
}
}
// Remove references to shared AudioChunk buffers from downstream nodes
// first so that upstream nodes can re-use next iteration.
for (uint32_t i = mStreams.Length(); i--; ) {
AudioNodeStream* ns = mStreams[i]->AsAudioNodeStream();
if (ns) {
ns->ReleaseSharedBuffers();
}
}
t = next;
}
NS_ASSERTION(t == aTo, "Something went wrong with rounding to block boundaries");

View File

@ -134,11 +134,8 @@ OmxVideoTrackEncoder::GetEncodedTrack(EncodedFrameContainer& aData)
layers::Image* img = (!mLastFrame.GetImage() || mLastFrame.GetForceBlack())
? nullptr : mLastFrame.GetImage();
rv = mEncoder->Encode(img, mFrameWidth, mFrameHeight, totalDurationUs,
OMXCodecWrapper::BUFFER_EOS);
OMXCodecWrapper::BUFFER_EOS, &mEosSetInEncoder);
NS_ENSURE_SUCCESS(rv, rv);
// Keep sending EOS signal until OMXVideoEncoder gets it.
mEosSetInEncoder = true;
}
// Dequeue an encoded frame from the output buffers of OMXCodecWrapper.
@ -219,6 +216,7 @@ OmxAudioTrackEncoder::GetEncodedTrack(EncodedFrameContainer& aData)
PROFILER_LABEL("OmxAACAudioTrackEncoder", "GetEncodedTrack",
js::ProfileEntry::Category::OTHER);
AudioSegment segment;
bool EOS;
// Move all the samples from mRawSegment to segment. We only hold
// the monitor in this block.
{
@ -234,14 +232,15 @@ OmxAudioTrackEncoder::GetEncodedTrack(EncodedFrameContainer& aData)
}
segment.AppendFrom(&mRawSegment);
EOS = mEndOfStream;
}
nsresult rv;
if (segment.GetDuration() == 0) {
// Notify EOS at least once, even if segment is empty.
if (mEndOfStream && !mEosSetInEncoder) {
mEosSetInEncoder = true;
rv = mEncoder->Encode(segment, OMXCodecWrapper::BUFFER_EOS);
if (EOS && !mEosSetInEncoder) {
rv = mEncoder->Encode(segment, OMXCodecWrapper::BUFFER_EOS,
&mEosSetInEncoder);
NS_ENSURE_SUCCESS(rv, rv);
}
// Nothing to encode but encoder could still have encoded data for earlier
@ -252,8 +251,7 @@ OmxAudioTrackEncoder::GetEncodedTrack(EncodedFrameContainer& aData)
// OMX encoder has limited input buffers only so we have to feed input and get
// output more than once if there are too many samples pending in segment.
while (segment.GetDuration() > 0) {
rv = mEncoder->Encode(segment,
mEndOfStream ? OMXCodecWrapper::BUFFER_EOS : 0);
rv = mEncoder->Encode(segment, 0);
NS_ENSURE_SUCCESS(rv, rv);
rv = AppendEncodedFrames(aData);

View File

@ -446,6 +446,7 @@ VP8TrackEncoder::GetEncodedTrack(EncodedFrameContainer& aData)
{
PROFILER_LABEL("VP8TrackEncoder", "GetEncodedTrack",
js::ProfileEntry::Category::OTHER);
bool EOS;
{
// Move all the samples from mRawSegment to mSourceSegment. We only hold
// the monitor in this block.
@ -461,6 +462,7 @@ VP8TrackEncoder::GetEncodedTrack(EncodedFrameContainer& aData)
return NS_ERROR_FAILURE;
}
mSourceSegment.AppendFrom(&mRawSegment);
EOS = mEndOfStream;
}
VideoSegment::ChunkIterator iter(mSourceSegment);
@ -534,7 +536,7 @@ VP8TrackEncoder::GetEncodedTrack(EncodedFrameContainer& aData)
VP8LOG("RemoveLeading %lld\n",totalProcessedDuration);
// End of stream, pull the rest frames in encoder.
if (mEndOfStream) {
if (EOS) {
VP8LOG("mEndOfStream is true\n");
mEncodingComplete = true;
if (vpx_codec_encode(mVPXContext, nullptr, mEncodedTimestamp,

View File

@ -382,7 +382,7 @@ ConvertGrallocImageToNV12(GrallocImage* aSource, uint8_t* aDestination)
nsresult
OMXVideoEncoder::Encode(const Image* aImage, int aWidth, int aHeight,
int64_t aTimestamp, int aInputFlags)
int64_t aTimestamp, int aInputFlags, bool* aSendEOS)
{
MOZ_ASSERT(mStarted, "Configure() should be called before Encode().");
@ -456,6 +456,9 @@ OMXVideoEncoder::Encode(const Image* aImage, int aWidth, int aHeight,
// Queue this input buffer.
result = mCodec->queueInputBuffer(index, 0, dstSize, aTimestamp, aInputFlags);
if (aSendEOS && (aInputFlags & BUFFER_EOS) && result == OK) {
*aSendEOS = true;
}
return result == OK ? NS_OK : NS_ERROR_FAILURE;
}
@ -822,7 +825,8 @@ OMXAudioEncoder::~OMXAudioEncoder()
}
nsresult
OMXAudioEncoder::Encode(AudioSegment& aSegment, int aInputFlags)
OMXAudioEncoder::Encode(AudioSegment& aSegment, int aInputFlags,
bool* aSendEOS)
{
#ifndef MOZ_SAMPLE_TYPE_S16
#error MediaCodec accepts only 16-bit PCM data.
@ -877,7 +881,9 @@ OMXAudioEncoder::Encode(AudioSegment& aSegment, int aInputFlags)
}
result = buffer.Enqueue(mTimestamp, flags);
NS_ENSURE_TRUE(result == OK, NS_ERROR_FAILURE);
if (aSendEOS && (aInputFlags & BUFFER_EOS)) {
*aSendEOS = true;
}
return NS_OK;
}

View File

@ -224,8 +224,13 @@ public:
* stream, set aInputFlags to BUFFER_EOS. Since encoder has limited buffers,
* this function might not be able to encode all chunks in one call, however
* it will remove chunks it consumes from aSegment.
* aSendEOS is the output to tell the caller EOS signal sent into MediaCodec
* because the signal might not be sent due to the dequeueInputBuffer timeout.
* And the value of aSendEOS won't be set to any default value, only set to
* true when EOS signal sent into MediaCodec.
*/
nsresult Encode(mozilla::AudioSegment& aSegment, int aInputFlags = 0);
nsresult Encode(mozilla::AudioSegment& aSegment, int aInputFlags = 0,
bool* aSendEOS = nullptr);
~OMXAudioEncoder();
protected:
@ -298,9 +303,14 @@ public:
* semi-planar YUV420 format stored in the buffer of aImage. aTimestamp gives
* the frame timestamp/presentation time (in microseconds). To notify end of
* stream, set aInputFlags to BUFFER_EOS.
* aSendEOS is the output to tell the caller EOS signal sent into MediaCodec
* because the signal might not be sent due to the dequeueInputBuffer timeout.
* And the value of aSendEOS won't be set to any default value, only set to
* true when EOS signal sent into MediaCodec.
*/
nsresult Encode(const mozilla::layers::Image* aImage, int aWidth, int aHeight,
int64_t aTimestamp, int aInputFlags = 0);
int64_t aTimestamp, int aInputFlags = 0,
bool* aSendEOS = nullptr);
#if ANDROID_VERSION >= 18
/** Set encoding bitrate (in kbps). */

View File

@ -678,7 +678,6 @@ tags=msg
tags=msg
[test_mediarecorder_record_gum_video_timeslice.html]
tags=msg
skip-if = buildapp == 'b2g' || toolkit == 'android' # mimetype check, bug 969289
[test_mediarecorder_record_immediate_stop.html]
tags=msg capturestream
[test_mediarecorder_record_no_timeslice.html]

View File

@ -40,12 +40,10 @@ function startTest() {
is(evt.type, 'dataavailable',
'Event type should dataavailable');
ok(evt.data.size >= 0,
'Blob data size received is greater than or equal to zero');
is(evt.data.type, 'video/webm',
'Blob data received should have type = ' + 'video/webm');
is(mediaRecorder.mimeType, 'video/webm',
'Mime type in ondataavailable = ' + mediaRecorder.mimeType);
'Blob data size ' + evt.data.size + ' received is greater than or equal to zero');
is(mediaRecorder.mimeType, evt.data.type,
'Mime type in MediaRecorder and ondataavailable : '
+ mediaRecorder.mimeType + ' == ' + evt.data.type);
// We'll stop recording upon the 1st blob being received
if (dataAvailableCount === 1) {

View File

@ -957,8 +957,11 @@ AudioContext::UpdateNodeCount(int32_t aDelta)
bool firstNode = mNodeCount == 0;
mNodeCount += aDelta;
MOZ_ASSERT(mNodeCount >= 0);
// mDestinationNode may be null when we're destroying nodes unlinked by CC
if (!firstNode && mDestination) {
// mDestinationNode may be null when we're destroying nodes unlinked by CC.
// Skipping unnecessary calls after shutdown avoids RunInStableState events
// getting stuck in CycleCollectedJSRuntime during final cycle collection
// (bug 1200514).
if (!firstNode && mDestination && !mIsShutDown) {
mDestination->SetIsOnlyNodeForContext(mNodeCount == 1);
}
}

View File

@ -538,6 +538,12 @@ AudioNodeStream::ProcessInput(GraphTime aFrom, GraphTime aTo, uint32_t aFlags)
mEngine->ProcessBlocksOnPorts(this, mInputChunks, mLastChunks, &finished);
}
}
for (auto& chunk : mInputChunks) {
// If the buffer is shared then it won't be reused, so release the
// reference now. Keep the channel data array to save a free/alloc
// pair.
chunk.ReleaseBufferIfShared();
}
for (uint16_t i = 0; i < outputCount; ++i) {
NS_ASSERTION(mLastChunks[i].GetDuration() == WEBAUDIO_BLOCK_SIZE,
"Invalid WebAudio chunk size");
@ -613,22 +619,6 @@ AudioNodeStream::AdvanceOutputSegment()
}
}
void
AudioNodeStream::ReleaseSharedBuffers()
{
// A shared buffer can't be reused, so release the reference now. Keep
// the channel data arrays to save unnecessary free/alloc.
// Release shared output buffers first, as they may be shared with input
// buffers which can be re-used if there are no other references.
for (auto& chunk : mLastChunks) {
chunk.ReleaseBufferIfShared();
}
for (auto& chunk : mInputChunks) {
chunk.ReleaseBufferIfShared();
}
}
StreamTime
AudioNodeStream::GetCurrentPosition()
{

View File

@ -117,14 +117,6 @@ public:
* the output. This is used only for DelayNodeEngine in a feedback loop.
*/
void ProduceOutputBeforeInput(GraphTime aFrom);
/**
* Remove references to shared AudioChunk buffers. Called on downstream
* nodes first after an iteration has called ProcessInput() on the entire
* graph, so that upstream nodes can re-use their buffers on the next
* iteration.
*/
void ReleaseSharedBuffers();
StreamTime GetCurrentPosition();
bool IsAudioParamStream() const
{
@ -192,7 +184,7 @@ protected:
// The engine that will generate output for this node.
nsAutoPtr<AudioNodeEngine> mEngine;
// The mixed input blocks are kept from iteration to iteration to avoid
// reallocating channel data arrays and any buffers for mixing.
// reallocating channel data arrays.
OutputChunks mInputChunks;
// The last block produced by this node.
OutputChunks mLastChunks;

View File

@ -114,9 +114,6 @@ public:
// ProduceBlockBeforeInput() when in a cycle.
if (!mHaveProducedBeforeInput) {
UpdateOutputBlock(aOutput, 0.0);
// Not in cycle, so no need for additional buffer reference.
// See ProduceBlockBeforeInput().
mLastOutput.SetNull(0);
}
mHaveProducedBeforeInput = false;
mBuffer.NextBlock();
@ -159,13 +156,7 @@ public:
if (mLeftOverData <= 0) {
aOutput->SetNull(WEBAUDIO_BLOCK_SIZE);
} else {
// AudioNodeStream::ReleaseSharedBuffers() is called on delay nodes in
// cycles first and so may release the buffer reference in aOutput
// because downstream nodes may still be sharing when called. Therefore
// keep a separate reference to the output buffer for re-use next
// iteration.
UpdateOutputBlock(&mLastOutput, WEBAUDIO_BLOCK_SIZE);
*aOutput = mLastOutput;
UpdateOutputBlock(aOutput, WEBAUDIO_BLOCK_SIZE);
}
mHaveProducedBeforeInput = true;
}
@ -186,7 +177,6 @@ public:
return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
}
AudioChunk mLastOutput; // Used only when in a cycle.
AudioNodeStream* mSource;
AudioNodeStream* mDestination;
AudioParamTimeline mDelay;

View File

@ -0,0 +1,8 @@
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<textarea id="textarea" lang="en"></textarea>
</body>
</html>

View File

@ -5,3 +5,4 @@ skip-if = buildapp == 'b2g' || os == 'android'
[test_bug338427.html]
[test_bug434998.xul]
[test_bug678842.html]
[test_bug717433.html]

View File

@ -0,0 +1,2 @@
# Affix file for British English dictionary
# Fake file, nothing here.

View File

@ -0,0 +1,4 @@
3
Mary
Paul
Peter

View File

@ -1,6 +1,10 @@
[DEFAULT]
skip-if = buildapp == 'b2g' || buildapp == 'mulet'
support-files = bug678842_subframe.html
support-files =
bug678842_subframe.html
bug717433_subframe.html
en-GB/en_GB.dic
en-GB/en_GB.aff
[test_bug348497.html]
[test_bug384147.html]

View File

@ -0,0 +1,98 @@
<!DOCTYPE html>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=717433
-->
<head>
<title>Test for Bug 717433</title>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
</head>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=717433">Mozilla Bug 717433</a>
<p id="display"></p>
<iframe id="content"></iframe>
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
/** Test for Bug 717433 **/
SimpleTest.waitForExplicitFinish();
var content = document.getElementById('content');
// Load a subframe containing an editor with language "en". At first
// load, it will set the dictionary to en-GB or en-US. We set the other one.
// At second load, it will return the current dictionary. We can check that the
// dictionary is correctly remembered between loads.
var firstLoad = true;
var expected = "";
var en_GB;
var hunspell;
var loadListener = function(evt) {
Components.utils.import("resource://gre/modules/AsyncSpellCheckTestHelper.jsm");
if (firstLoad) {
var dir = Components.classes["@mozilla.org/file/directory_service;1"]
.getService(Components.interfaces.nsIProperties)
.get("CurWorkD", Components.interfaces.nsIFile);
dir.append("tests");
dir.append("editor");
dir.append("composer");
dir.append("test");
hunspell = Components.classes["@mozilla.org/spellchecker/engine;1"]
.getService(Components.interfaces.mozISpellCheckingEngine);
// Install en-GB dictionary.
en_GB = dir.clone();
en_GB.append("en-GB");
is(en_GB.exists(), true, "true expected (en-GB directory should exist)");
hunspell.addDirectory(en_GB);
}
var doc = evt.target.contentDocument;
var elem = doc.getElementById('textarea');
var editor = elem.QueryInterface(Components.interfaces.nsIDOMNSEditableElement).editor;
editor.setSpellcheckUserOverride(true);
var inlineSpellChecker = editor.getInlineSpellChecker(true);
onSpellCheck(elem, function () {
var spellchecker = inlineSpellChecker.spellChecker;
try {
var currentDictonary = spellchecker.GetCurrentDictionary();
} catch(e) {}
if (firstLoad) {
firstLoad = false;
// First time around, we get a random dictionary based on the language "en".
if (currentDictonary == "en-GB") {
spellchecker.SetCurrentDictionary("en-US");
expected = "en-US";
} else if (currentDictonary == "en-US") {
spellchecker.SetCurrentDictionary("en-GB");
expected = "en-GB";
} else {
is(true, false, "Neither en-US nor en-GB are current");
}
content.src = 'http://mochi.test:8888/tests/editor/composer/test/bug717433_subframe.html?firstload=false';
} else {
is(currentDictonary, expected, expected + " expected");
content.removeEventListener('load', loadListener, false);
// Remove the fake en-GB dictionary again, since it's otherwise picked up by later tests.
hunspell.removeDirectory(en_GB);
SimpleTest.finish();
}
});
}
content.addEventListener('load', loadListener, false);
content.src = 'http://mochi.test:8888/tests/editor/composer/test/bug717433_subframe.html?firstload=true';
</script>
</pre>
</body>
</html>

View File

@ -1234,7 +1234,7 @@ public:
#if defined(USE_SKIA) && defined(MOZ_ENABLE_FREETYPE)
static already_AddRefed<GlyphRenderingOptions>
CreateCairoGlyphRenderingOptions(FontHinting aHinting, bool aAutoHinting);
CreateCairoGlyphRenderingOptions(FontHinting aHinting, bool aAutoHinting, AntialiasMode aAntialiasMode = AntialiasMode::DEFAULT);
#endif
static already_AddRefed<DrawTarget>
CreateDualDrawTarget(DrawTarget *targetA, DrawTarget *targetB);

View File

@ -10,6 +10,7 @@
#include "ScaledFontCairo.h"
#include "skia/include/core/SkBitmapDevice.h"
#include "FilterNodeSoftware.h"
#include "HelpersSkia.h"
#ifdef USE_SKIA_GPU
#include "skia/include/gpu/SkGpuDevice.h"
@ -571,23 +572,17 @@ DrawTargetSkia::FillGlyphs(ScaledFont *aFont,
paint.mPaint.setLCDRenderText(shouldLCDRenderText);
if (aRenderingOptions && aRenderingOptions->GetType() == FontType::CAIRO) {
switch (static_cast<const GlyphRenderingOptionsCairo*>(aRenderingOptions)->GetHinting()) {
case FontHinting::NONE:
paint.mPaint.setHinting(SkPaint::kNo_Hinting);
break;
case FontHinting::LIGHT:
paint.mPaint.setHinting(SkPaint::kSlight_Hinting);
break;
case FontHinting::NORMAL:
paint.mPaint.setHinting(SkPaint::kNormal_Hinting);
break;
case FontHinting::FULL:
paint.mPaint.setHinting(SkPaint::kFull_Hinting);
break;
const GlyphRenderingOptionsCairo* cairoOptions =
static_cast<const GlyphRenderingOptionsCairo*>(aRenderingOptions);
paint.mPaint.setHinting(GfxHintingToSkiaHinting(cairoOptions->GetHinting()));
if (cairoOptions->GetAutoHinting()) {
paint.mPaint.setAutohinted(true);
}
if (static_cast<const GlyphRenderingOptionsCairo*>(aRenderingOptions)->GetAutoHinting()) {
paint.mPaint.setAutohinted(true);
if (cairoOptions->GetAntialiasMode() == AntialiasMode::NONE) {
paint.mPaint.setAntiAlias(false);
}
} else if (aFont->GetType() == FontType::MAC && shouldLCDRenderText) {
// SkFontHost_mac only supports subpixel antialiasing when hinting is turned off.

View File

@ -758,13 +758,14 @@ Factory::PurgeAllCaches()
#ifdef USE_SKIA_FREETYPE
already_AddRefed<GlyphRenderingOptions>
Factory::CreateCairoGlyphRenderingOptions(FontHinting aHinting, bool aAutoHinting)
Factory::CreateCairoGlyphRenderingOptions(FontHinting aHinting, bool aAutoHinting, AntialiasMode aAntialiasMode)
{
RefPtr<GlyphRenderingOptionsCairo> options =
new GlyphRenderingOptionsCairo();
options->SetHinting(aHinting);
options->SetAutoHinting(aAutoHinting);
options->SetAntialiasMode(aAntialiasMode);
return options.forget();
}
#endif

View File

@ -88,10 +88,24 @@ GfxAntialiasToCairoAntialias(AntialiasMode antialias)
return CAIRO_ANTIALIAS_GRAY;
case AntialiasMode::SUBPIXEL:
return CAIRO_ANTIALIAS_SUBPIXEL;
case AntialiasMode::DEFAULT:
default:
return CAIRO_ANTIALIAS_DEFAULT;
}
return CAIRO_ANTIALIAS_DEFAULT;
}
static inline AntialiasMode
CairoAntialiasToGfxAntialias(cairo_antialias_t aAntialias)
{
switch(aAntialias) {
case CAIRO_ANTIALIAS_NONE:
return AntialiasMode::NONE;
case CAIRO_ANTIALIAS_GRAY:
return AntialiasMode::GRAY;
case CAIRO_ANTIALIAS_SUBPIXEL:
return AntialiasMode::SUBPIXEL;
default:
return AntialiasMode::DEFAULT;
}
}
static inline cairo_filter_t
@ -232,6 +246,23 @@ CairoFormatToGfxFormat(cairo_format_t format)
}
}
static inline FontHinting
CairoHintingToGfxHinting(cairo_hint_style_t aHintStyle)
{
switch (aHintStyle) {
case CAIRO_HINT_STYLE_NONE:
return FontHinting::NONE;
case CAIRO_HINT_STYLE_SLIGHT:
return FontHinting::LIGHT;
case CAIRO_HINT_STYLE_MEDIUM:
return FontHinting::NORMAL;
case CAIRO_HINT_STYLE_FULL:
return FontHinting::FULL;
default:
return FontHinting::NORMAL;
}
}
SurfaceFormat GfxFormatForCairoSurface(cairo_surface_t* surface);
static inline void

View File

@ -296,6 +296,22 @@ ExtendModeToTileMode(ExtendMode aMode)
return SkShader::kClamp_TileMode;
}
static inline SkPaint::Hinting
GfxHintingToSkiaHinting(FontHinting aHinting)
{
switch (aHinting) {
case FontHinting::NONE:
return SkPaint::kNo_Hinting;
case FontHinting::LIGHT:
return SkPaint::kSlight_Hinting;
case FontHinting::NORMAL:
return SkPaint::kNormal_Hinting;
case FontHinting::FULL:
return SkPaint::kFull_Hinting;
}
return SkPaint::kNormal_Hinting;
}
} // namespace gfx
} // namespace mozilla

View File

@ -37,6 +37,7 @@ public:
GlyphRenderingOptionsCairo()
: mHinting(FontHinting::NORMAL)
, mAutoHinting(false)
, mAntialiasMode(AntialiasMode::DEFAULT)
{
}
@ -44,10 +45,13 @@ public:
void SetAutoHinting(bool aAutoHinting) { mAutoHinting = aAutoHinting; }
FontHinting GetHinting() const { return mHinting; }
bool GetAutoHinting() const { return mAutoHinting; }
void SetAntialiasMode(AntialiasMode aAntialiasMode) { mAntialiasMode = aAntialiasMode; }
virtual AntialiasMode GetAntialiasMode() const { return mAntialiasMode; }
virtual FontType GetType() const { return FontType::CAIRO; }
private:
FontHinting mHinting;
bool mAutoHinting;
AntialiasMode mAntialiasMode;
};
} // namespace gfx

View File

@ -307,8 +307,6 @@ CompositorChild::RecvUpdatePluginConfigurations(const nsIntPoint& aContentOffset
// Handle invalidation, this can be costly, avoid if it is not needed.
if (isVisible) {
// invalidate region (widget origin)
gfx::IntRect bounds = aPlugins[pluginsIdx].bounds();
gfx::IntRect rect(0, 0, bounds.width, bounds.height);
#if defined(XP_WIN)
// Work around for flash's crummy sandbox. See bug 762948. This call
// digs down into the window hirearchy, invalidating regions on
@ -330,16 +328,16 @@ CompositorChild::RecvUpdatePluginConfigurations(const nsIntPoint& aContentOffset
}
bool
CompositorChild::RecvUpdatePluginVisibility(const uintptr_t& aOwnerWidget,
nsTArray<uintptr_t>&& aVisibleIdList)
CompositorChild::RecvHideAllPlugins(const uintptr_t& aParentWidget)
{
#if !defined(XP_WIN) && !defined(MOZ_WIDGET_GTK)
NS_NOTREACHED("CompositorChild::RecvUpdatePluginVisibility calls "
NS_NOTREACHED("CompositorChild::RecvHideAllPlugins calls "
"unexpected on this platform.");
return false;
#else
MOZ_ASSERT(NS_IsMainThread());
nsIWidget::UpdateRegisteredPluginWindowVisibility(aOwnerWidget, aVisibleIdList);
nsTArray<uintptr_t> list;
nsIWidget::UpdateRegisteredPluginWindowVisibility(aParentWidget, list);
return true;
#endif // !defined(XP_WIN) && !defined(MOZ_WIDGET_GTK)
}

View File

@ -90,8 +90,7 @@ public:
nsTArray<PluginWindowData>&& aPlugins) override;
virtual bool
RecvUpdatePluginVisibility(const uintptr_t& aOwnerWidget,
nsTArray<uintptr_t>&& aWindowList) override;
RecvHideAllPlugins(const uintptr_t& aParentWidget) override;
/**
* Request that the parent tell us when graphics are ready on GPU.

View File

@ -1013,6 +1013,52 @@ CompositorParent::SetShadowProperties(Layer* aLayer)
}
}
// handles firing of before and after composite events through
// an raii type helper class.
class AutoFireCompositorEvents {
public:
explicit AutoFireCompositorEvents(CompositorParent* aTarget, bool aEnabled) :
mCompositor(aTarget),
mStart(TimeStamp::Now()),
mEnabled(aEnabled),
mWillSent(false),
mDidSent(false)
{
}
~AutoFireCompositorEvents()
{
WillComposite();
DidComposite();
}
void WillComposite() {
if (mEnabled && mCompositor && !mWillSent) {
TimeStamp now = TimeStamp::Now();
mCompositor->CompositeEvent(WILL_COMPOSITE, mStart, now);
}
mWillSent = true;
}
void DidComposite() {
if (mEnabled && mCompositor && !mDidSent) {
TimeStamp now = TimeStamp::Now();
mCompositor->CompositeEvent(DID_COMPOSITE, mStart, now);
}
mDidSent = true;
}
void Cancel() {
mEnabled = false;
}
CompositorParent* mCompositor;
TimeStamp mStart;
bool mEnabled;
bool mWillSent;
bool mDidSent;
};
void
CompositorParent::CompositeToTarget(DrawTarget* aTarget, const gfx::IntRect* aRect)
{
@ -1033,9 +1079,10 @@ CompositorParent::CompositeToTarget(DrawTarget* aTarget, const gfx::IntRect* aRe
}
#endif
// Takes care of fireing 'will' and 'did' composite events.
AutoFireCompositorEvents afce(this, !aTarget);
if (!CanComposite()) {
TimeStamp end = TimeStamp::Now();
DidComposite(start, end);
return;
}
@ -1054,10 +1101,13 @@ CompositorParent::CompositeToTarget(DrawTarget* aTarget, const gfx::IntRect* aRe
mForceCompositionTask->Cancel();
mForceCompositionTask = nullptr;
} else {
afce.Cancel();
return;
}
}
afce.WillComposite();
mCompositionManager->ComputeRotation();
TimeStamp time = mIsTesting ? mTestTime : mCompositorScheduler->GetLastComposeTime();
@ -1077,11 +1127,6 @@ CompositorParent::CompositeToTarget(DrawTarget* aTarget, const gfx::IntRect* aRe
mLayerManager->SetDebugOverlayWantsNextFrame(false);
mLayerManager->EndTransaction(time);
if (!aTarget) {
TimeStamp end = TimeStamp::Now();
DidComposite(start, end);
}
// We're not really taking advantage of the stored composite-again-time here.
// We might be able to skip the next few composites altogether. However,
// that's a bit complex to implement and we'll get most of the advantage
@ -1722,9 +1767,10 @@ public:
virtual AsyncCompositionManager* GetCompositionManager(LayerTransactionParent* aParent) override;
void DidComposite(uint64_t aId,
TimeStamp& aCompositeStart,
TimeStamp& aCompositeEnd);
void CompositeEvent(CallbackType aType,
uint64_t aId,
TimeStamp& aCompositeStart,
TimeStamp& aCompositeEnd);
private:
// Private destructor, to discourage deletion outside of Release():
@ -1745,18 +1791,21 @@ private:
};
void
CompositorParent::DidComposite(TimeStamp& aCompositeStart,
TimeStamp& aCompositeEnd)
CompositorParent::CompositeEvent(CallbackType aType,
TimeStamp& aCompositeStart,
TimeStamp& aCompositeEnd)
{
if (mPendingTransaction) {
unused << SendDidComposite(0, mPendingTransaction, aCompositeStart, aCompositeEnd);
mPendingTransaction = 0;
}
if (mLayerManager) {
nsTArray<ImageCompositeNotification> notifications;
mLayerManager->ExtractImageCompositeNotifications(&notifications);
if (!notifications.IsEmpty()) {
unused << ImageBridgeParent::NotifyImageComposites(notifications);
if (aType == DID_COMPOSITE) {
if (mPendingTransaction) {
unused << SendDidComposite(0, mPendingTransaction, aCompositeStart, aCompositeEnd);
mPendingTransaction = 0;
}
if (mLayerManager) {
nsTArray<ImageCompositeNotification> notifications;
mLayerManager->ExtractImageCompositeNotifications(&notifications);
if (!notifications.IsEmpty()) {
unused << ImageBridgeParent::NotifyImageComposites(notifications);
}
}
}
@ -1765,8 +1814,8 @@ CompositorParent::DidComposite(TimeStamp& aCompositeStart,
it != sIndirectLayerTrees.end(); it++) {
LayerTreeState* lts = &it->second;
if (lts->mParent == this && lts->mCrossProcessParent) {
static_cast<CrossProcessCompositorParent*>(lts->mCrossProcessParent)->DidComposite(
it->first, aCompositeStart, aCompositeEnd);
static_cast<CrossProcessCompositorParent*>(lts->mCrossProcessParent)->CompositeEvent(
aType, it->first, aCompositeStart, aCompositeEnd);
}
}
}
@ -2002,10 +2051,8 @@ UpdatePluginWindowState(uint64_t aId)
// tree contained visible plugins and the new tree does not. All we need
// to do here is hide the plugins for the old tree, so don't waste time
// calculating clipping.
nsTArray<uintptr_t> aVisibleIdList;
uintptr_t parentWidget = (uintptr_t)lts.mParent->GetWidget();
unused << lts.mParent->SendUpdatePluginVisibility(parentWidget,
aVisibleIdList);
unused << lts.mParent->SendHideAllPlugins(parentWidget);
lts.mUpdatedPluginDataAvailable = false;
return;
}
@ -2030,18 +2077,10 @@ UpdatePluginWindowState(uint64_t aId)
}
}
// Hide all plugins, this remote layer tree is no longer active
// Hide all of our plugins, this remote layer tree is no longer active.
if (shouldHidePlugin) {
// hide all the plugins
for (uint32_t pluginsIdx = 0; pluginsIdx < lts.mPluginData.Length();
pluginsIdx++) {
lts.mPluginData[pluginsIdx].visible() = false;
}
nsIntPoint offset;
nsIntRegion region;
unused << lts.mParent->SendUpdatePluginConfigurations(offset,
region,
lts.mPluginData);
uintptr_t parentWidget = (uintptr_t)lts.mParent->GetWidget();
unused << lts.mParent->SendHideAllPlugins(parentWidget);
// Clear because there's no recovering from this until we receive
// new shadow layer plugin data in ShadowLayersUpdated.
lts.mPluginData.Clear();
@ -2050,19 +2089,32 @@ UpdatePluginWindowState(uint64_t aId)
#endif // #if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
void
CrossProcessCompositorParent::DidComposite(uint64_t aId,
TimeStamp& aCompositeStart,
TimeStamp& aCompositeEnd)
CrossProcessCompositorParent::CompositeEvent(CallbackType aType,
uint64_t aId,
TimeStamp& aCompositeStart,
TimeStamp& aCompositeEnd)
{
sIndirectLayerTreesLock->AssertCurrentThreadOwns();
LayerTransactionParent *layerTree = sIndirectLayerTrees[aId].mLayerTree;
if (layerTree && layerTree->GetPendingTransactionId()) {
unused << SendDidComposite(aId, layerTree->GetPendingTransactionId(), aCompositeStart, aCompositeEnd);
layerTree->SetPendingTransactionId(0);
}
switch (aType) {
case WILL_COMPOSITE: {
#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
UpdatePluginWindowState(aId);
UpdatePluginWindowState(aId);
#endif
break;
}
case DID_COMPOSITE: {
sIndirectLayerTreesLock->AssertCurrentThreadOwns();
LayerTransactionParent *layerTree = sIndirectLayerTrees[aId].mLayerTree;
if (layerTree && layerTree->GetPendingTransactionId()) {
unused << SendDidComposite(aId, layerTree->GetPendingTransactionId(), aCompositeStart, aCompositeEnd);
layerTree->SetPendingTransactionId(0);
}
break;
}
default:
NS_RUNTIMEABORT("not reached");
}
}
void

View File

@ -55,6 +55,12 @@ class CompositorParent;
class LayerManagerComposite;
class LayerTransactionParent;
// CompositeEvent related events
enum CallbackType {
WILL_COMPOSITE,
DID_COMPOSITE
};
struct ScopedLayerTreeRegistration
{
ScopedLayerTreeRegistration(uint64_t aLayersId,
@ -439,7 +445,14 @@ protected:
*/
bool CanComposite();
void DidComposite(TimeStamp& aCompositeStart, TimeStamp& aCompositeEnd);
// Fires before and after composite events
void CompositeEvent(CallbackType aType, TimeStamp& aCompositeStart,
TimeStamp& aCompositeEnd);
void DidComposite(TimeStamp& aCompositeStart, TimeStamp& aCompositeEnd) {
CompositeEvent(DID_COMPOSITE, aCompositeStart, aCompositeEnd);
}
friend class AutoFireCompositorEvents;
nsRefPtr<LayerManagerComposite> mLayerManager;
nsRefPtr<Compositor> mCompositor;

View File

@ -42,7 +42,6 @@ using mozilla::layers::DiagnosticTypes from "mozilla/layers/CompositorTypes.h";
using struct mozilla::layers::FrameMetrics from "FrameMetrics.h";
using mozilla::layers::FrameMetrics::ViewID from "FrameMetrics.h";
using struct mozilla::layers::FenceHandle from "mozilla/layers/FenceUtils.h";
using std::string from "string";
namespace mozilla {
namespace layers {
@ -232,7 +231,6 @@ struct CommonLayerAttributes {
Animation[] animations;
nsIntRegion invalidRegion;
FrameMetrics[] metrics;
string contentDescription;
nsCString displayListLog;
};

View File

@ -70,11 +70,10 @@ child:
PluginWindowData[] aPlugins);
/**
* Sets the list of currently visible plugin windows based on a
* list of plugin window ids.
* Hides all registered plugin widgets associated with a particular chrome
* widget.
*/
async UpdatePluginVisibility(uintptr_t aOwnerWidget,
uintptr_t[] aVisibleIdList);
async HideAllPlugins(uintptr_t aParentWidget);
/**
* Drop any buffers that might be retained on the child compositor

View File

@ -276,6 +276,10 @@ SkScalerContext_CairoFT::SkScalerContext_CairoFT(SkTypeface* typeface, const SkD
// See http://code.google.com/p/skia/issues/detail?id=222.
loadFlags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
#ifdef FT_LOAD_COLOR
loadFlags |= FT_LOAD_COLOR;
#endif
fLoadGlyphFlags = loadFlags;
}

View File

@ -21,6 +21,8 @@
#include "nsDirectoryServiceDefs.h"
#include "nsAppDirectoryServiceDefs.h"
#include "mozilla/gfx/HelpersCairo.h"
#include <fontconfig/fcfreetype.h>
#ifdef MOZ_WIDGET_GTK
@ -902,27 +904,18 @@ gfxFontconfigFont::GetGlyphRenderingOptions(const TextRunDrawParams* aRunParams)
cairo_font_options_t *options = cairo_font_options_create();
cairo_scaled_font_get_font_options(scaled_font, options);
cairo_hint_style_t hint_style = cairo_font_options_get_hint_style(options);
cairo_antialias_t antialias = cairo_font_options_get_antialias(options);
cairo_font_options_destroy(options);
mozilla::gfx::FontHinting hinting;
mozilla::gfx::FontHinting hinting =
mozilla::gfx::CairoHintingToGfxHinting(hint_style);
switch (hint_style) {
case CAIRO_HINT_STYLE_NONE:
hinting = mozilla::gfx::FontHinting::NONE;
break;
case CAIRO_HINT_STYLE_SLIGHT:
hinting = mozilla::gfx::FontHinting::LIGHT;
break;
case CAIRO_HINT_STYLE_FULL:
hinting = mozilla::gfx::FontHinting::FULL;
break;
default:
hinting = mozilla::gfx::FontHinting::NORMAL;
break;
}
mozilla::gfx::AntialiasMode aaMode =
mozilla::gfx::CairoAntialiasToGfxAntialias(antialias);
// We don't want to force the use of the autohinter over the font's built in hints
return mozilla::gfx::Factory::CreateCairoGlyphRenderingOptions(hinting, false);
// The fontconfig AA mode must be passed along because it may override the hinting style.
return mozilla::gfx::Factory::CreateCairoGlyphRenderingOptions(hinting, false, aaMode);
}
#endif

View File

@ -28,6 +28,7 @@
#include <cairo.h>
#include <cairo-ft.h>
#include "mozilla/gfx/HelpersCairo.h"
#include <fontconfig/fcfreetype.h>
#include <pango/pango.h>
@ -2143,27 +2144,18 @@ gfxFcFont::GetGlyphRenderingOptions(const TextRunDrawParams* aRunParams)
cairo_font_options_t *options = cairo_font_options_create();
cairo_scaled_font_get_font_options(scaled_font, options);
cairo_hint_style_t hint_style = cairo_font_options_get_hint_style(options);
cairo_antialias_t antialias = cairo_font_options_get_antialias(options);
cairo_font_options_destroy(options);
mozilla::gfx::FontHinting hinting;
mozilla::gfx::FontHinting hinting =
mozilla::gfx::CairoHintingToGfxHinting(hint_style);
switch (hint_style) {
case CAIRO_HINT_STYLE_NONE:
hinting = mozilla::gfx::FontHinting::NONE;
break;
case CAIRO_HINT_STYLE_SLIGHT:
hinting = mozilla::gfx::FontHinting::LIGHT;
break;
case CAIRO_HINT_STYLE_FULL:
hinting = mozilla::gfx::FontHinting::FULL;
break;
default:
hinting = mozilla::gfx::FontHinting::NORMAL;
break;
}
mozilla::gfx::AntialiasMode aaMode =
mozilla::gfx::CairoAntialiasToGfxAntialias(antialias);
// We don't want to force the use of the autohinter over the font's built in hints
return mozilla::gfx::Factory::CreateCairoGlyphRenderingOptions(hinting, false);
// The fontconfig AA mode must be passed along because it may override the hinting style.
return mozilla::gfx::Factory::CreateCairoGlyphRenderingOptions(hinting, false, aaMode);
}
#endif

View File

@ -187,6 +187,7 @@ private:
DECL_GFX_PREF(Live, "apz.y_stationary_size_multiplier", APZYStationarySizeMultiplier, float, 3.5f);
DECL_GFX_PREF(Live, "apz.zoom_animation_duration_ms", APZZoomAnimationDuration, int32_t, 250);
DECL_GFX_PREF(Live, "browser.ui.zoom.force-user-scalable", ForceUserScalable, bool, false);
DECL_GFX_PREF(Live, "browser.viewport.desktopWidth", DesktopViewportWidth, int32_t, 980);
DECL_GFX_PREF(Live, "dom.meta-viewport.enabled", MetaViewportEnabled, bool, false);

View File

@ -2189,7 +2189,7 @@ InlineTransparentTypedObject::getOrCreateBuffer(JSContext* cx)
ObjectWeakMap*& table = cx->compartment()->lazyArrayBuffers;
if (!table) {
table = cx->new_<ObjectWeakMap>(cx);
if (!table)
if (!table || !table->init())
return nullptr;
}

View File

@ -807,7 +807,7 @@ JSCompartment::setNewObjectMetadata(JSContext* cx, JSObject* obj)
assertSameCompartment(cx, metadata);
if (!objectMetadataTable) {
objectMetadataTable = cx->new_<ObjectWeakMap>(cx);
if (!objectMetadataTable)
if (!objectMetadataTable || !objectMetadataTable->init())
CrashAtUnhandlableOOM("setNewObjectMetadata");
}
if (!objectMetadataTable->add(cx, obj, metadata))

View File

@ -683,9 +683,12 @@ js::InitBareWeakMapCtor(JSContext* cx, HandleObject obj)
ObjectWeakMap::ObjectWeakMap(JSContext* cx)
: map(cx, nullptr)
{}
bool
ObjectWeakMap::init()
{
if (!map.init())
CrashAtUnhandlableOOM("ObjectWeakMap");
return map.init();
}
ObjectWeakMap::~ObjectWeakMap()
@ -696,6 +699,7 @@ ObjectWeakMap::~ObjectWeakMap()
JSObject*
ObjectWeakMap::lookup(const JSObject* obj)
{
MOZ_ASSERT(map.initialized());
if (ObjectValueMap::Ptr p = map.lookup(const_cast<JSObject*>(obj)))
return &p->value().toObject();
return nullptr;
@ -705,6 +709,7 @@ bool
ObjectWeakMap::add(JSContext* cx, JSObject* obj, JSObject* target)
{
MOZ_ASSERT(obj && target);
MOZ_ASSERT(map.initialized());
MOZ_ASSERT(!map.has(obj));
if (!map.put(obj, ObjectValue(*target))) {
@ -720,18 +725,21 @@ ObjectWeakMap::add(JSContext* cx, JSObject* obj, JSObject* target)
void
ObjectWeakMap::clear()
{
MOZ_ASSERT(map.initialized());
map.clear();
}
void
ObjectWeakMap::trace(JSTracer* trc)
{
MOZ_ASSERT(map.initialized());
map.trace(trc);
}
size_t
ObjectWeakMap::sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf)
{
MOZ_ASSERT(map.initialized());
return map.sizeOfExcludingThis(mallocSizeOf);
}
@ -739,6 +747,7 @@ ObjectWeakMap::sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf)
void
ObjectWeakMap::checkAfterMovingGC()
{
MOZ_ASSERT(map.initialized());
for (ObjectValueMap::Range r = map.all(); !r.empty(); r.popFront()) {
CheckGCThingAfterMovingGC(r.front().key().get());
CheckGCThingAfterMovingGC(&r.front().value().toObject());

View File

@ -51,11 +51,11 @@ js::DestroyHelperThreadsState()
gHelperThreadState = nullptr;
}
void
bool
js::EnsureHelperThreadsInitialized()
{
MOZ_ASSERT(gHelperThreadState);
gHelperThreadState->ensureInitialized();
return gHelperThreadState->ensureInitialized();
}
static size_t
@ -453,7 +453,7 @@ static const uint32_t HELPER_STACK_SIZE = kDefaultHelperStackSize;
static const uint32_t HELPER_STACK_QUOTA = kDefaultHelperStackQuota;
#endif
void
bool
GlobalHelperThreadState::ensureInitialized()
{
MOZ_ASSERT(CanUseExtraThreads());
@ -462,11 +462,11 @@ GlobalHelperThreadState::ensureInitialized()
AutoLockHelperThreadState lock;
if (threads)
return;
return true;
threads = js_pod_calloc<HelperThread>(threadCount);
if (!threads)
CrashAtUnhandlableOOM("GlobalHelperThreadState::ensureInitialized");
return false;
for (size_t i = 0; i < threadCount; i++) {
HelperThread& helper = threads[i];
@ -474,11 +474,15 @@ GlobalHelperThreadState::ensureInitialized()
helper.thread = PR_CreateThread(PR_USER_THREAD,
HelperThread::ThreadMain, &helper,
PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, HELPER_STACK_SIZE);
if (!helper.thread || !helper.threadData->init())
CrashAtUnhandlableOOM("GlobalHelperThreadState::ensureInitialized");
if (!helper.thread || !helper.threadData->init()) {
finishThreads();
return false;
}
}
resetAsmJSFailureState();
return true;
}
GlobalHelperThreadState::GlobalHelperThreadState()
@ -510,12 +514,7 @@ GlobalHelperThreadState::GlobalHelperThreadState()
void
GlobalHelperThreadState::finish()
{
if (threads) {
MOZ_ASSERT(CanUseExtraThreads());
for (size_t i = 0; i < threadCount; i++)
threads[i].destroy();
js_free(threads);
}
finishThreads();
PR_DestroyCondVar(consumerWakeup);
PR_DestroyCondVar(producerWakeup);
@ -525,6 +524,19 @@ GlobalHelperThreadState::finish()
ionLazyLinkList_.clear();
}
void
GlobalHelperThreadState::finishThreads()
{
if (!threads)
return;
MOZ_ASSERT(CanUseExtraThreads());
for (size_t i = 0; i < threadCount; i++)
threads[i].destroy();
js_free(threads);
threads = nullptr;
}
void
GlobalHelperThreadState::lock()
{

View File

@ -103,8 +103,9 @@ class GlobalHelperThreadState
GlobalHelperThreadState();
void ensureInitialized();
bool ensureInitialized();
void finish();
void finishThreads();
void lock();
void unlock();
@ -351,7 +352,7 @@ void
DestroyHelperThreadsState();
// Initialize helper threads unless already initialized.
void
bool
EnsureHelperThreadsInitialized();
// This allows the JS shell to override GetCPUCount() when passed the

View File

@ -283,10 +283,10 @@ JSRuntime::init(uint32_t maxbytes, uint32_t maxNurseryBytes)
if (!regexpStack.init())
return false;
js::TlsPerThreadData.set(&mainThread);
if (CanUseExtraThreads() && !EnsureHelperThreadsInitialized())
return false;
if (CanUseExtraThreads())
EnsureHelperThreadsInitialized();
js::TlsPerThreadData.set(&mainThread);
if (!gc.init(maxbytes, maxNurseryBytes))
return false;

View File

@ -1921,7 +1921,7 @@ DebugScopes::~DebugScopes()
bool
DebugScopes::init()
{
return liveScopes.init() && missingScopes.init();
return proxiedScopes.init() && missingScopes.init() && liveScopes.init();
}
void

View File

@ -38,6 +38,7 @@ class ObjectWeakMap
public:
explicit ObjectWeakMap(JSContext* cx);
bool init();
~ObjectWeakMap();
JSObject* lookup(const JSObject* obj);

View File

@ -27,6 +27,7 @@ NS_IMPL_ISUPPORTS(ZoomConstraintsClient, nsIDOMEventListener, nsIObserver)
static const nsLiteralString DOM_META_ADDED = NS_LITERAL_STRING("DOMMetaAdded");
static const nsLiteralString DOM_META_CHANGED = NS_LITERAL_STRING("DOMMetaChanged");
static const nsLiteralCString BEFORE_FIRST_PAINT = NS_LITERAL_CSTRING("before-first-paint");
static const nsLiteralCString NS_PREF_CHANGED = NS_LITERAL_CSTRING("nsPref:changed");
using namespace mozilla;
using namespace mozilla::layers;
@ -76,6 +77,8 @@ ZoomConstraintsClient::Destroy()
observerService->RemoveObserver(this, BEFORE_FIRST_PAINT.Data());
}
Preferences::RemoveObserver(this, "browser.ui.zoom.force-user-scalable");
if (mGuid) {
if (nsIWidget* widget = GetWidget(mPresShell)) {
ZCC_LOG("Sending null constraints in %p for { %u, %" PRIu64 " }\n",
@ -111,6 +114,8 @@ ZoomConstraintsClient::Init(nsIPresShell* aPresShell, nsIDocument* aDocument)
if (observerService) {
observerService->AddObserver(this, BEFORE_FIRST_PAINT.Data(), false);
}
Preferences::AddStrongObserver(this, "browser.ui.zoom.force-user-scalable");
}
NS_IMETHODIMP
@ -136,6 +141,13 @@ ZoomConstraintsClient::Observe(nsISupports* aSubject, const char* aTopic, const
if (SameCOMIdentity(aSubject, mDocument) && BEFORE_FIRST_PAINT.EqualsASCII(aTopic)) {
ZCC_LOG("Got a before-first-paint event in %p\n", this);
RefreshZoomConstraints();
} else if (NS_PREF_CHANGED.EqualsASCII(aTopic)) {
ZCC_LOG("Got a pref-change event in %p\n", this);
// We need to run this later because all the pref change listeners need
// to execute before we can be guaranteed that gfxPrefs::ForceUserScalable()
// returns the updated value.
NS_DispatchToMainThread(NS_NewRunnableMethod(
this, &ZoomConstraintsClient::RefreshZoomConstraints));
}
return NS_OK;
}
@ -152,9 +164,14 @@ ComputeZoomConstraintsFromViewportInfo(const nsViewportInfo& aViewportInfo)
{
mozilla::layers::ZoomConstraints constraints;
constraints.mAllowZoom = aViewportInfo.IsZoomAllowed() && gfxPrefs::APZAllowZooming();
constraints.mAllowDoubleTapZoom = aViewportInfo.IsDoubleTapZoomAllowed() && gfxPrefs::APZAllowZooming();
constraints.mMinZoom.scale = aViewportInfo.GetMinZoom().scale;
constraints.mMaxZoom.scale = aViewportInfo.GetMaxZoom().scale;
constraints.mAllowDoubleTapZoom = constraints.mAllowZoom;
if (constraints.mAllowZoom) {
constraints.mMinZoom.scale = aViewportInfo.GetMinZoom().scale;
constraints.mMaxZoom.scale = aViewportInfo.GetMaxZoom().scale;
} else {
constraints.mMinZoom.scale = aViewportInfo.GetDefaultZoom().scale;
constraints.mMaxZoom.scale = aViewportInfo.GetDefaultZoom().scale;
}
return constraints;
}

View File

@ -490,7 +490,10 @@ JsepSessionImpl::AddRecvonlyMsections(SdpMediaSection::MediaType mediatype,
{
while (count--) {
nsresult rv = CreateOfferMSection(
mediatype, SdpDirectionAttribute::kRecvonly, sdp);
mediatype,
mSdpHelper.GetProtocolForMediaType(mediatype),
SdpDirectionAttribute::kRecvonly,
sdp);
NS_ENSURE_SUCCESS(rv, rv);
}
@ -510,6 +513,7 @@ JsepSessionImpl::AddReofferMsections(const Sdp& oldLocalSdp,
// We do not set the direction in this function (or disable when previously
// disabled), that happens in |SetupOfferMSectionsByType|
rv = CreateOfferMSection(oldLocalSdp.GetMediaSection(i).GetMediaType(),
oldLocalSdp.GetMediaSection(i).GetProtocol(),
SdpDirectionAttribute::kInactive,
newSdp);
NS_ENSURE_SUCCESS(rv, rv);
@ -975,12 +979,10 @@ JsepSessionImpl::CreateAnswer(const JsepAnswerOptions& options,
nsresult
JsepSessionImpl::CreateOfferMSection(SdpMediaSection::MediaType mediatype,
SdpMediaSection::Protocol proto,
SdpDirectionAttribute::Direction dir,
Sdp* sdp)
{
SdpMediaSection::Protocol proto =
mSdpHelper.GetProtocolForMediaType(mediatype);
SdpMediaSection* msection =
&sdp->AddMediaSection(mediatype, dir, 0, proto, sdp::kIPv4, "0.0.0.0");
@ -1019,6 +1021,7 @@ JsepSessionImpl::GetFreeMsectionForSend(
// Ok, no pre-existing m-section. Make a new one.
nsresult rv = CreateOfferMSection(type,
mSdpHelper.GetProtocolForMediaType(type),
SdpDirectionAttribute::kInactive,
sdp);
NS_ENSURE_SUCCESS(rv, rv);

View File

@ -256,6 +256,7 @@ private:
std::string* streamId,
std::string* trackId);
nsresult CreateOfferMSection(SdpMediaSection::MediaType type,
SdpMediaSection::Protocol proto,
SdpDirectionAttribute::Direction direction,
Sdp* sdp);
nsresult GetFreeMsectionForSend(SdpMediaSection::MediaType type,

View File

@ -634,8 +634,7 @@ SdpHelper::GetProtocolForMediaType(SdpMediaSection::MediaType type)
return SdpMediaSection::kDtlsSctp;
}
// TODO(bug 1094447): Use kUdpTlsRtpSavpf once it interops well
return SdpMediaSection::kRtpSavpf;
return SdpMediaSection::kUdpTlsRtpSavpf;
}
void

View File

@ -917,7 +917,7 @@ private:
if (msection.GetMediaType() == SdpMediaSection::kApplication) {
ASSERT_EQ(SdpMediaSection::kDtlsSctp, msection.GetProtocol());
} else {
ASSERT_EQ(SdpMediaSection::kRtpSavpf, msection.GetProtocol());
ASSERT_EQ(SdpMediaSection::kUdpTlsRtpSavpf, msection.GetProtocol());
}
if (msection.GetPort() == 0) {
@ -3759,6 +3759,53 @@ TEST_P(JsepSessionTest, TestMaxBundle)
EXPECT_EQ(1U, GetActiveTransportCount(mSessionAns));
}
TEST_F(JsepSessionTest, TestNonDefaultProtocol)
{
AddTracks(mSessionOff, "audio,video,datachannel");
AddTracks(mSessionAns, "audio,video,datachannel");
std::string offer;
ASSERT_EQ(NS_OK, mSessionOff.CreateOffer(JsepOfferOptions(), &offer));
offer.replace(offer.find("UDP/TLS/RTP/SAVPF"),
strlen("UDP/TLS/RTP/SAVPF"),
"RTP/SAVPF");
offer.replace(offer.find("UDP/TLS/RTP/SAVPF"),
strlen("UDP/TLS/RTP/SAVPF"),
"RTP/SAVPF");
mSessionOff.SetLocalDescription(kJsepSdpOffer, offer);
mSessionAns.SetRemoteDescription(kJsepSdpOffer, offer);
std::string answer;
mSessionAns.CreateAnswer(JsepAnswerOptions(), &answer);
UniquePtr<Sdp> parsedAnswer = Parse(answer);
ASSERT_EQ(3U, parsedAnswer->GetMediaSectionCount());
ASSERT_EQ(SdpMediaSection::kRtpSavpf,
parsedAnswer->GetMediaSection(0).GetProtocol());
ASSERT_EQ(SdpMediaSection::kRtpSavpf,
parsedAnswer->GetMediaSection(1).GetProtocol());
mSessionAns.SetLocalDescription(kJsepSdpAnswer, answer);
mSessionOff.SetRemoteDescription(kJsepSdpAnswer, answer);
// Make sure reoffer uses the same protocol as before
mSessionOff.CreateOffer(JsepOfferOptions(), &offer);
UniquePtr<Sdp> parsedOffer = Parse(offer);
ASSERT_EQ(3U, parsedOffer->GetMediaSectionCount());
ASSERT_EQ(SdpMediaSection::kRtpSavpf,
parsedOffer->GetMediaSection(0).GetProtocol());
ASSERT_EQ(SdpMediaSection::kRtpSavpf,
parsedOffer->GetMediaSection(1).GetProtocol());
// Make sure reoffer from other side uses the same protocol as before
mSessionAns.CreateOffer(JsepOfferOptions(), &offer);
parsedOffer = Parse(offer);
ASSERT_EQ(3U, parsedOffer->GetMediaSectionCount());
ASSERT_EQ(SdpMediaSection::kRtpSavpf,
parsedOffer->GetMediaSection(0).GetProtocol());
ASSERT_EQ(SdpMediaSection::kRtpSavpf,
parsedOffer->GetMediaSection(1).GetProtocol());
}
} // namespace mozilla
int

View File

@ -2315,8 +2315,10 @@ TEST_P(SignalingTest, OfferAnswerNothingDisabledFullCycle)
OfferOptions options;
OfferAnswer(options, OFFER_AV | ANSWER_AV);
// verify the default codec priorities
ASSERT_NE(a1_->getLocalDescription().find("RTP/SAVPF 109 9 0 8\r"), std::string::npos);
ASSERT_NE(a2_->getLocalDescription().find("RTP/SAVPF 109\r"), std::string::npos);
ASSERT_NE(a1_->getLocalDescription().find("UDP/TLS/RTP/SAVPF 109 9 0 8\r"),
std::string::npos);
ASSERT_NE(a2_->getLocalDescription().find("UDP/TLS/RTP/SAVPF 109\r"),
std::string::npos);
}
TEST_P(SignalingTest, OfferAnswerAudioInactive)
@ -2535,7 +2537,8 @@ TEST_P(SignalingTest, OfferAndAnswerWithExtraCodec)
a2_->CreateAnswer(OFFER_AUDIO | ANSWER_AUDIO);
a2_->SetLocal(TestObserver::ANSWER, a2_->answer());
ParsedSDP sdpWrapper(a2_->answer());
sdpWrapper.ReplaceLine("m=audio", "m=audio 65375 RTP/SAVPF 109 8\r\n");
sdpWrapper.ReplaceLine("m=audio",
"m=audio 65375 UDP/TLS/RTP/SAVPF 109 8\r\n");
sdpWrapper.AddLine("a=rtpmap:8 PCMA/8000\r\n");
std::cout << "Modified SDP " << std::endl
<< indent(sdpWrapper.getSdp()) << std::endl;
@ -2638,7 +2641,7 @@ TEST_P(SignalingTest, IncomingOfferIceLite)
"a=ice-lite\r\n"
"a=fingerprint:sha-1 "
"E7:FA:17:DA:3F:3C:1E:D8:E4:9C:8C:4C:13:B9:2E:D5:C6:78:AB:B3\r\n"
"m=audio 40014 RTP/SAVPF 8 0 101\r\n"
"m=audio 40014 UDP/TLS/RTP/SAVPF 8 0 101\r\n"
"a=rtpmap:8 PCMA/8000\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"a=rtpmap:101 telephone-event/8000\r\n"
@ -2675,7 +2678,7 @@ TEST_P(SignalingTest, ChromeOfferAnswer)
"t=0 0\r\n"
"a=group:BUNDLE audio video\r\n"
"m=audio 1 RTP/SAVPF 103 104 111 0 8 107 106 105 13 126\r\n"
"m=audio 1 UDP/TLS/RTP/SAVPF 103 104 111 0 8 107 106 105 13 126\r\n"
"a=fingerprint:sha-1 4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:"
"5D:49:6B:19:E5:7C:AB\r\n"
"a=setup:active\r\n"
@ -2709,7 +2712,7 @@ TEST_P(SignalingTest, ChromeOfferAnswer)
"a=ssrc:661333377 mslabel:A5UL339RyGxT7zwgyF12BFqesxkmbUsaycp5\r\n"
"a=ssrc:661333377 label:A5UL339RyGxT7zwgyF12BFqesxkmbUsaycp5a0\r\n"
"m=video 1 RTP/SAVPF 100 101 102\r\n"
"m=video 1 UDP/TLS/RTP/SAVPF 100 101 102\r\n"
"a=fingerprint:sha-1 4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:"
"6B:19:E5:7C:AB\r\n"
"a=setup:active\r\n"
@ -2754,7 +2757,7 @@ TEST_P(SignalingTest, FullChromeHandshake)
"t=0 0\r\n"
"a=group:BUNDLE audio video\r\n"
"a=msid-semantic: WMS ahheYQXHFU52slYMrWNtKUyHCtWZsOJgjlOH\r\n"
"m=audio 1 RTP/SAVPF 103 104 111 0 8 107 106 105 13 126\r\n"
"m=audio 1 UDP/TLS/RTP/SAVPF 103 104 111 0 8 107 106 105 13 126\r\n"
"c=IN IP4 1.1.1.1\r\n"
"a=rtcp:1 IN IP4 1.1.1.1\r\n"
"a=ice-ufrag:jz9UBk9RT8eCQXiL\r\n"
@ -2782,7 +2785,7 @@ TEST_P(SignalingTest, FullChromeHandshake)
"a=ssrc:3389377748 msid:ahheYQXHFU52slYMrWNtKUyHCtWZsOJgjlOH a0\r\n"
"a=ssrc:3389377748 mslabel:ahheYQXHFU52slYMrWNtKUyHCtWZsOJgjlOH\r\n"
"a=ssrc:3389377748 label:ahheYQXHFU52slYMrWNtKUyHCtWZsOJgjlOHa0\r\n"
"m=video 1 RTP/SAVPF 100 116 117\r\n"
"m=video 1 UDP/TLS/RTP/SAVPF 100 116 117\r\n"
"c=IN IP4 1.1.1.1\r\n"
"a=rtcp:1 IN IP4 1.1.1.1\r\n"
"a=ice-ufrag:jz9UBk9RT8eCQXiL\r\n"
@ -3234,7 +3237,7 @@ TEST_P(SignalingTest, missingUfrag)
"a=ice-pwd:4450d5a4a5f097855c16fa079893be18\r\n"
"a=fingerprint:sha-256 23:9A:2E:43:94:42:CF:46:68:FC:62:F9:F4:48:61:DB:"
"2F:8C:C9:FF:6B:25:54:9D:41:09:EF:83:A8:19:FC:B6\r\n"
"m=audio 56187 RTP/SAVPF 109 0 8 101\r\n"
"m=audio 56187 UDP/TLS/RTP/SAVPF 109 0 8 101\r\n"
"c=IN IP4 77.9.79.167\r\n"
"a=rtpmap:109 opus/48000/2\r\n"
"a=ptime:20\r\n"
@ -3249,7 +3252,7 @@ TEST_P(SignalingTest, missingUfrag)
"a=candidate:0 2 UDP 2113601790 192.168.178.20 52955 typ host\r\n"
"a=candidate:1 2 UDP 1694236670 77.9.79.167 52955 typ srflx raddr "
"192.168.178.20 rport 52955\r\n"
"m=video 49929 RTP/SAVPF 120\r\n"
"m=video 49929 UDP/TLS/RTP/SAVPF 120\r\n"
"c=IN IP4 77.9.79.167\r\n"
"a=rtpmap:120 VP8/90000\r\n"
"a=recvonly\r\n"
@ -3319,14 +3322,15 @@ TEST_P(SignalingTest, AudioOnlyG722Only)
a1_->SetLocal(TestObserver::OFFER, a1_->offer(), false);
ParsedSDP sdpWrapper(a1_->offer());
sdpWrapper.ReplaceLine("m=audio",
"m=audio 65375 RTP/SAVPF 9\r\n");
"m=audio 65375 UDP/TLS/RTP/SAVPF 9\r\n");
std::cout << "Modified SDP " << std::endl
<< indent(sdpWrapper.getSdp()) << std::endl;
a2_->SetRemote(TestObserver::OFFER, sdpWrapper.getSdp(), false);
a2_->CreateAnswer(OFFER_AUDIO | ANSWER_AUDIO);
a2_->SetLocal(TestObserver::ANSWER, a2_->answer(), false);
a1_->SetRemote(TestObserver::ANSWER, a2_->answer(), false);
ASSERT_NE(a2_->getLocalDescription().find("RTP/SAVPF 9\r"), std::string::npos);
ASSERT_NE(a2_->getLocalDescription().find("UDP/TLS/RTP/SAVPF 9\r"),
std::string::npos);
ASSERT_NE(a2_->getLocalDescription().find("a=rtpmap:9 G722/8000"), std::string::npos);
WaitForCompleted();
@ -3347,14 +3351,15 @@ TEST_P(SignalingTest, AudioOnlyG722MostPreferred)
a1_->SetLocal(TestObserver::OFFER, a1_->offer(), false);
ParsedSDP sdpWrapper(a1_->offer());
sdpWrapper.ReplaceLine("m=audio",
"m=audio 65375 RTP/SAVPF 9 0 8 109\r\n");
"m=audio 65375 UDP/TLS/RTP/SAVPF 9 0 8 109\r\n");
std::cout << "Modified SDP " << std::endl
<< indent(sdpWrapper.getSdp()) << std::endl;
a2_->SetRemote(TestObserver::OFFER, sdpWrapper.getSdp(), false);
a2_->CreateAnswer(OFFER_AUDIO | ANSWER_AUDIO);
a2_->SetLocal(TestObserver::ANSWER, a2_->answer(), false);
a1_->SetRemote(TestObserver::ANSWER, a2_->answer(), false);
ASSERT_NE(a2_->getLocalDescription().find("RTP/SAVPF 9"), std::string::npos);
ASSERT_NE(a2_->getLocalDescription().find("UDP/TLS/RTP/SAVPF 9"),
std::string::npos);
ASSERT_NE(a2_->getLocalDescription().find("a=rtpmap:9 G722/8000"), std::string::npos);
CheckPipelines();
@ -3375,16 +3380,17 @@ TEST_P(SignalingTest, AudioOnlyG722Rejected)
a1_->SetLocal(TestObserver::OFFER, a1_->offer(), false);
ParsedSDP sdpWrapper(a1_->offer());
sdpWrapper.ReplaceLine("m=audio",
"m=audio 65375 RTP/SAVPF 0 8\r\n");
"m=audio 65375 UDP/TLS/RTP/SAVPF 0 8\r\n");
std::cout << "Modified SDP offer " << std::endl
<< indent(sdpWrapper.getSdp()) << std::endl;
a2_->SetRemote(TestObserver::OFFER, sdpWrapper.getSdp(), false);
a2_->CreateAnswer(OFFER_AUDIO | ANSWER_AUDIO);
a2_->SetLocal(TestObserver::ANSWER, a2_->answer(), false);
a1_->SetRemote(TestObserver::ANSWER, a2_->answer(), false);
// TODO(bug 1099351): Use commented out code instead.
ASSERT_NE(a2_->getLocalDescription().find("RTP/SAVPF 0\r"), std::string::npos);
// ASSERT_NE(a2_->getLocalDescription().find("RTP/SAVPF 0 8\r"), std::string::npos);
// TODO(bug 814227): Use commented out code instead.
ASSERT_NE(a2_->getLocalDescription().find("UDP/TLS/RTP/SAVPF 0\r"),
std::string::npos);
// ASSERT_NE(a2_->getLocalDescription().find("UDP/TLS/RTP/SAVPF 0 8\r"), std::string::npos);
ASSERT_NE(a2_->getLocalDescription().find("a=rtpmap:0 PCMU/8000"), std::string::npos);
ASSERT_EQ(a2_->getLocalDescription().find("a=rtpmap:109 opus/48000/2"), std::string::npos);
ASSERT_EQ(a2_->getLocalDescription().find("a=rtpmap:9 G722/8000"), std::string::npos);
@ -3869,7 +3875,7 @@ TEST_P(SignalingTest, hugeSdp)
"t=0 0\r\n"
"a=group:BUNDLE audio video\r\n"
"a=msid-semantic: WMS 1PBxet5BYh0oYodwsvNM4k6KiO2eWCX40VIP\r\n"
"m=audio 32952 RTP/SAVPF 111 103 104 0 8 107 106 105 13 126\r\n"
"m=audio 32952 UDP/TLS/RTP/SAVPF 111 103 104 0 8 107 106 105 13 126\r\n"
"c=IN IP4 128.64.32.16\r\n"
"a=rtcp:32952 IN IP4 128.64.32.16\r\n"
"a=candidate:77142221 1 udp 2113937151 192.168.137.1 54081 typ host generation 0\r\n"
@ -3914,7 +3920,7 @@ TEST_P(SignalingTest, hugeSdp)
"a=ssrc:2271517329 msid:1PBxet5BYh0oYodwsvNM4k6KiO2eWCX40VIP 1PBxet5BYh0oYodwsvNM4k6KiO2eWCX40VIPa0\r\n"
"a=ssrc:2271517329 mslabel:1PBxet5BYh0oYodwsvNM4k6KiO2eWCX40VIP\r\n"
"a=ssrc:2271517329 label:1PBxet5BYh0oYodwsvNM4k6KiO2eWCX40VIPa0\r\n"
"m=video 32952 RTP/SAVPF 100 116 117\r\n"
"m=video 32952 UDP/TLS/RTP/SAVPF 100 116 117\r\n"
"c=IN IP4 128.64.32.16\r\n"
"a=rtcp:32952 IN IP4 128.64.32.16\r\n"
"a=candidate:77142221 1 udp 2113937151 192.168.137.1 54081 typ host generation 0\r\n"
@ -4113,9 +4119,9 @@ TEST_P(SignalingTest, ValidateMultipleVideoCodecsInOffer)
std::string offer = a1_->offer();
#ifdef H264_P0_SUPPORTED
ASSERT_NE(offer.find("RTP/SAVPF 120 126 97"), std::string::npos);
ASSERT_NE(offer.find("UDP/TLS/RTP/SAVPF 120 126 97"), std::string::npos);
#else
ASSERT_NE(offer.find("RTP/SAVPF 120 126"), std::string::npos);
ASSERT_NE(offer.find("UDP/TLS/RTP/SAVPF 120 126"), std::string::npos);
#endif
ASSERT_NE(offer.find("a=rtpmap:120 VP8/90000"), std::string::npos);
ASSERT_NE(offer.find("a=rtpmap:126 H264/90000"), std::string::npos);
@ -4147,9 +4153,9 @@ TEST_P(SignalingTest, RemoveVP8FromOfferWithP1First)
// Remove VP8 from offer
std::string offer = a1_->offer();
match = offer.find("RTP/SAVPF 120");
match = offer.find("UDP/TLS/RTP/SAVPF 120");
ASSERT_NE(std::string::npos, match);
offer.replace(match, strlen("RTP/SAVPF 120"), "RTP/SAVPF");
offer.replace(match, strlen("UDP/TLS/RTP/SAVPF 120"), "UDP/TLS/RTP/SAVPF");
match = offer.find("profile-level-id");
ASSERT_NE(std::string::npos, match);
@ -4165,7 +4171,7 @@ TEST_P(SignalingTest, RemoveVP8FromOfferWithP1First)
<< indent(sdpWrapper.getSdp()) << std::endl;
// P1 should be offered first
ASSERT_NE(offer.find("RTP/SAVPF 126"), std::string::npos);
ASSERT_NE(offer.find("UDP/TLS/RTP/SAVPF 126"), std::string::npos);
a1_->SetLocal(TestObserver::OFFER, sdpWrapper.getSdp());
a2_->SetRemote(TestObserver::OFFER, sdpWrapper.getSdp(), false);
@ -4174,7 +4180,7 @@ TEST_P(SignalingTest, RemoveVP8FromOfferWithP1First)
std::string answer(a2_->answer());
// Validate answer SDP
ASSERT_NE(answer.find("RTP/SAVPF 126"), std::string::npos);
ASSERT_NE(answer.find("UDP/TLS/RTP/SAVPF 126"), std::string::npos);
ASSERT_NE(answer.find("a=rtpmap:126 H264/90000"), std::string::npos);
ASSERT_NE(answer.find("a=rtcp-fb:126 nack"), std::string::npos);
ASSERT_NE(answer.find("a=rtcp-fb:126 nack pli"), std::string::npos);
@ -4197,17 +4203,17 @@ TEST_P(SignalingTest, OfferWithH264BeforeVP8)
// Swap VP8 and P1 in offer
std::string offer = a1_->offer();
#ifdef H264_P0_SUPPORTED
match = offer.find("RTP/SAVPF 120 126 97");
match = offer.find("UDP/TLS/RTP/SAVPF 120 126 97");
ASSERT_NE(std::string::npos, match);
offer.replace(match,
strlen("RTP/SAVPF 126 120 97"),
"RTP/SAVPF 126 120 97");
strlen("UDP/TLS/RTP/SAVPF 126 120 97"),
"UDP/TLS/RTP/SAVPF 126 120 97");
#else
match = offer.find("RTP/SAVPF 120 126");
match = offer.find("UDP/TLS/RTP/SAVPF 120 126");
ASSERT_NE(std::string::npos, match);
offer.replace(match,
strlen("RTP/SAVPF 126 120"),
"RTP/SAVPF 126 120");
strlen("UDP/TLS/RTP/SAVPF 126 120"),
"UDP/TLS/RTP/SAVPF 126 120");
#endif
match = offer.find("a=rtpmap:126 H264/90000");
@ -4227,9 +4233,9 @@ TEST_P(SignalingTest, OfferWithH264BeforeVP8)
// P1 should be offered first
#ifdef H264_P0_SUPPORTED
ASSERT_NE(offer.find("RTP/SAVPF 126 120 97"), std::string::npos);
ASSERT_NE(offer.find("UDP/TLS/RTP/SAVPF 126 120 97"), std::string::npos);
#else
ASSERT_NE(offer.find("RTP/SAVPF 126 120"), std::string::npos);
ASSERT_NE(offer.find("UDP/TLS/RTP/SAVPF 126 120"), std::string::npos);
#endif
a1_->SetLocal(TestObserver::OFFER, offer);
@ -4239,7 +4245,7 @@ TEST_P(SignalingTest, OfferWithH264BeforeVP8)
std::string answer(a2_->answer());
// Validate answer SDP
ASSERT_NE(answer.find("RTP/SAVPF 126"), std::string::npos);
ASSERT_NE(answer.find("UDP/TLS/RTP/SAVPF 126"), std::string::npos);
ASSERT_NE(answer.find("a=rtpmap:126 H264/90000"), std::string::npos);
ASSERT_NE(answer.find("a=rtcp-fb:126 nack"), std::string::npos);
ASSERT_NE(answer.find("a=rtcp-fb:126 nack pli"), std::string::npos);
@ -4259,11 +4265,11 @@ TEST_P(SignalingTest, OfferWithOnlyH264P0)
// Remove VP8 from offer
std::string offer = a1_->offer();
match = offer.find("RTP/SAVPF 120 126");
match = offer.find("UDP/TLS/RTP/SAVPF 120 126");
ASSERT_NE(std::string::npos, match);
offer.replace(match,
strlen("RTP/SAVPF 120 126"),
"RTP/SAVPF");
strlen("UDP/TLS/RTP/SAVPF 120 126"),
"UDP/TLS/RTP/SAVPF");
ParsedSDP sdpWrapper(offer);
sdpWrapper.DeleteLines("a=rtcp-fb:120");
@ -4281,7 +4287,7 @@ TEST_P(SignalingTest, OfferWithOnlyH264P0)
ASSERT_EQ(offer.find("a=rtpmap:120 VP8/90000"), std::string::npos);
// P0 should be offered first
ASSERT_NE(offer.find("RTP/SAVPF 97"), std::string::npos);
ASSERT_NE(offer.find("UDP/TLS/RTP/SAVPF 97"), std::string::npos);
a1_->SetLocal(TestObserver::OFFER, offer);
a2_->SetRemote(TestObserver::OFFER, offer, false);
@ -4290,7 +4296,7 @@ TEST_P(SignalingTest, OfferWithOnlyH264P0)
std::string answer(a2_->answer());
// validate answer SDP
ASSERT_NE(answer.find("RTP/SAVPF 97"), std::string::npos);
ASSERT_NE(answer.find("UDP/TLS/RTP/SAVPF 97"), std::string::npos);
ASSERT_NE(answer.find("a=rtpmap:97 H264/90000"), std::string::npos);
ASSERT_NE(answer.find("a=rtcp-fb:97 nack"), std::string::npos);
ASSERT_NE(answer.find("a=rtcp-fb:97 nack pli"), std::string::npos);
@ -4327,9 +4333,11 @@ TEST_P(SignalingTest, AnswerWithoutVP8)
size_t match;
answer = sdpWrapper.getSdp();
match = answer.find("RTP/SAVPF 120");
match = answer.find("UDP/TLS/RTP/SAVPF 120");
ASSERT_NE(std::string::npos, match);
answer.replace(match, strlen("RTP/SAVPF 120"), "RTP/SAVPF 126");
answer.replace(match,
strlen("UDP/TLS/RTP/SAVPF 120"),
"UDP/TLS/RTP/SAVPF 126");
match = answer.find("\r\na=rtpmap:120 VP8/90000");
ASSERT_NE(std::string::npos, match);
@ -4392,9 +4400,11 @@ TEST_P(SignalingTest, UseNonPrefferedPayloadTypeOnAnswer)
// Replace VP8 Payload Type with a non preferred value
size_t match;
match = answer.find("RTP/SAVPF 120");
match = answer.find("UDP/TLS/RTP/SAVPF 120");
ASSERT_NE(std::string::npos, match);
answer.replace(match, strlen("RTP/SAVPF 121"), "RTP/SAVPF 121");
answer.replace(match,
strlen("UDP/TLS/RTP/SAVPF 121"),
"UDP/TLS/RTP/SAVPF 121");
match = answer.find("\r\na=rtpmap:120 VP8/90000");
ASSERT_NE(std::string::npos, match);

View File

@ -11,14 +11,12 @@ import org.json.JSONObject;
public final class ZoomConstraints {
private final boolean mAllowZoom;
private final boolean mAllowDoubleTapZoom;
private final float mDefaultZoom;
private final float mMinZoom;
private final float mMaxZoom;
public ZoomConstraints(boolean allowZoom) {
mAllowZoom = allowZoom;
mAllowDoubleTapZoom = allowZoom;
mDefaultZoom = 0.0f;
mMinZoom = 0.0f;
mMaxZoom = 0.0f;
}
@ -26,7 +24,6 @@ public final class ZoomConstraints {
ZoomConstraints(JSONObject message) throws JSONException {
mAllowZoom = message.getBoolean("allowZoom");
mAllowDoubleTapZoom = message.getBoolean("allowDoubleTapZoom");
mDefaultZoom = (float)message.getDouble("defaultZoom");
mMinZoom = (float)message.getDouble("minZoom");
mMaxZoom = (float)message.getDouble("maxZoom");
}
@ -39,10 +36,6 @@ public final class ZoomConstraints {
return mAllowDoubleTapZoom;
}
public final float getDefaultZoom() {
return mDefaultZoom;
}
public final float getMinZoom() {
return mMinZoom;
}

View File

@ -1045,14 +1045,11 @@ class JavaPanZoomController
ZoomConstraints constraints = mTarget.getZoomConstraints();
if (constraints.getMinZoom() > 0)
if (constraints.getMinZoom() > 0 || !constraints.getAllowZoom()) {
minZoomFactor = constraints.getMinZoom();
if (constraints.getMaxZoom() > 0)
}
if (constraints.getMaxZoom() > 0 || !constraints.getAllowZoom()) {
maxZoomFactor = constraints.getMaxZoom();
if (!constraints.getAllowZoom()) {
// If allowZoom is false, clamp to the default zoom level.
maxZoomFactor = minZoomFactor = constraints.getDefaultZoom();
}
// Ensure minZoomFactor keeps the page at least as big as the viewport.

View File

@ -1686,7 +1686,7 @@ var BrowserApp = {
shouldZoom = false;
// ZoomHelper.zoomToElement will handle not sending any message if this input is already mostly filling the screen
ZoomHelper.zoomToElement(focused, -1, false,
aAllowZoom && shouldZoom && !ViewportHandler.getViewportMetadata(aBrowser.contentWindow).isSpecified);
aAllowZoom && shouldZoom && !ViewportHandler.isViewportSpecified(aBrowser.contentWindow));
}
},
@ -3579,7 +3579,6 @@ Tab.prototype = {
Services.obs.addObserver(this, "before-first-paint", false);
Services.obs.addObserver(this, "after-viewport-change", false);
Services.prefs.addObserver("browser.ui.zoom.force-user-scalable", this, false);
if (aParams.delayLoad) {
// If this is a zombie tab, attach restore data so the tab will be
@ -3762,7 +3761,6 @@ Tab.prototype = {
Services.obs.removeObserver(this, "before-first-paint");
Services.obs.removeObserver(this, "after-viewport-change");
Services.prefs.removeObserver("browser.ui.zoom.force-user-scalable", this);
// Make sure the previously selected panel remains selected. The selected panel of a deck is
// not stable when panels are removed.
@ -4719,87 +4717,10 @@ Tab.prototype = {
// for now anyway.
},
get metadata() {
return ViewportHandler.getMetadataForDocument(this.browser.contentDocument);
},
/** Update viewport when the metadata changes. */
updateViewportMetadata: function updateViewportMetadata(aMetadata) {
if (Services.prefs.getBoolPref("browser.ui.zoom.force-user-scalable")) {
aMetadata.allowZoom = true;
aMetadata.allowDoubleTapZoom = true;
aMetadata.minZoom = aMetadata.maxZoom = NaN;
}
this.recomputeDoubleTapToZoomAllowed();
let scaleRatio = window.devicePixelRatio;
if (aMetadata.defaultZoom > 0)
aMetadata.defaultZoom *= scaleRatio;
if (aMetadata.minZoom > 0)
aMetadata.minZoom *= scaleRatio;
if (aMetadata.maxZoom > 0)
aMetadata.maxZoom *= scaleRatio;
aMetadata.isRTL = this.browser.contentDocument.documentElement.dir == "rtl";
ViewportHandler.setMetadataForDocument(this.browser.contentDocument, aMetadata);
this.sendViewportMetadata();
},
viewportSizeUpdated: function viewportSizeUpdated() {
if (this.recomputeDoubleTapToZoomAllowed()) {
this.sendViewportMetadata();
}
this.sendViewportUpdate(); // recompute displayport
},
recomputeDoubleTapToZoomAllowed: function recomputeDoubleTapToZoomAllowed() {
let metadata = this.metadata;
if (metadata.allowZoom && !Services.prefs.getBoolPref("browser.ui.zoom.force-user-scalable")) {
// If the CSS viewport is narrower than the screen (i.e. width <= device-width)
// then we disable double-tap-to-zoom behaviour.
var oldAllowDoubleTapZoom = metadata.allowDoubleTapZoom;
// XXX: the window.innerWidth in the next line should really be the CSS viewport width
// (but the innerWidth is the SPCSPS width)
var newAllowDoubleTapZoom = (!metadata.isSpecified) || (window.innerWidth > gScreenWidth / window.devicePixelRatio);
if (oldAllowDoubleTapZoom !== newAllowDoubleTapZoom) {
metadata.allowDoubleTapZoom = newAllowDoubleTapZoom;
return true;
}
}
return false;
},
sendViewportMetadata: function sendViewportMetadata() {
let metadata = this.metadata;
Messaging.sendRequest({
type: "Tab:ViewportMetadata",
allowZoom: metadata.allowZoom,
allowDoubleTapZoom: metadata.allowDoubleTapZoom,
defaultZoom: metadata.defaultZoom || window.devicePixelRatio,
minZoom: metadata.minZoom || 0,
maxZoom: metadata.maxZoom || 0,
isRTL: metadata.isRTL,
tabID: this.id
});
},
/** Takes a scale and restricts it based on this tab's zoom limits. */
clampZoom: function clampZoom(aZoom) {
let zoom = ViewportHandler.clamp(aZoom, kViewportMinScale, kViewportMaxScale);
let md = this.metadata;
if (!md.allowZoom)
return md.defaultZoom || zoom;
if (md && md.minZoom)
zoom = Math.max(zoom, md.minZoom);
if (md && md.maxZoom)
zoom = Math.min(zoom, md.maxZoom);
return zoom;
},
observe: function(aSubject, aTopic, aData) {
switch (aTopic) {
case "before-first-paint":
@ -4811,7 +4732,6 @@ Tab.prototype = {
}
this.contentDocumentIsDisplayed = true;
ViewportHandler.updateMetadata(this);
let zoom = this.restoredSessionZoom();
if (zoom) {
this.setResolution(zoom, true);
@ -4844,10 +4764,6 @@ Tab.prototype = {
BrowserApp.selectedTab.clearReflowOnZoomPendingActions();
}
break;
case "nsPref:changed":
if (aData == "browser.ui.zoom.force-user-scalable")
ViewportHandler.updateMetadata(this);
break;
}
},
@ -5143,8 +5059,8 @@ var BrowserEventHandler = {
},
onDoubleTap: function(aData) {
let metadata = BrowserApp.selectedTab.metadata;
if (!metadata.allowDoubleTapZoom) {
let metadata = ViewportHandler.getMetadataForDocument(BrowserApp.selectedBrowser.contentDocument);
if (metadata && !metadata.allowDoubleTapZoom) {
return;
}
@ -6311,29 +6227,26 @@ var ViewportHandler = {
_metadata: new WeakMap(),
init: function init() {
addEventListener("DOMMetaAdded", this, false);
addEventListener("DOMMetaChanged", this, false);
Services.obs.addObserver(this, "Window:Resize", false);
},
handleEvent: function handleEvent(aEvent) {
switch (aEvent.type) {
case "DOMMetaChanged":
case "DOMMetaAdded":
let target = aEvent.originalTarget;
if (target.name != "viewport")
break;
let document = target.ownerDocument;
let browser = BrowserApp.getBrowserForDocument(document);
let tab = BrowserApp.getTabForBrowser(browser);
if (tab)
this.updateMetadata(tab);
break;
}
Services.obs.addObserver(this, "zoom-constraints-updated", false);
},
observe: function(aSubject, aTopic, aData) {
switch (aTopic) {
case "zoom-constraints-updated":
// aSubject should be a document, so let's find the tab corresponding
// to that if there is one
let constraints = JSON.parse(aData);
let doc = aSubject;
constraints.isRTL = doc.documentElement.dir == "rtl";
ViewportHandler.setMetadataForDocument(doc, constraints);
let tab = BrowserApp.getTabForWindow(doc.defaultView);
if (tab) {
constraints.type = "Tab:ViewportMetadata";
constraints.tabID = tab.id;
Messaging.sendRequest(constraints);
}
return;
case "Window:Resize":
if (window.outerWidth == gScreenWidth && window.outerHeight == gScreenHeight)
break;
@ -6360,18 +6273,10 @@ var ViewportHandler = {
}
},
updateMetadata: function updateMetadata(tab) {
let contentWindow = tab.browser.contentWindow;
if (contentWindow.document.documentElement) {
let metadata = this.getViewportMetadata(contentWindow);
tab.updateViewportMetadata(metadata);
}
},
/**
* Returns the ViewportMetadata object.
* Returns true if a viewport tag was specified
*/
getViewportMetadata: function getViewportMetadata(aWindow) {
isViewportSpecified: function isViewportSpecified(aWindow) {
let tab = BrowserApp.getTabForWindow(aWindow);
let readerMode = false;
try {
@ -6379,88 +6284,16 @@ var ViewportHandler = {
} catch (e) {
}
if (tab.desktopMode && !readerMode) {
return new ViewportMetadata({
minZoom: kViewportMinScale,
maxZoom: kViewportMaxScale,
allowZoom: true,
allowDoubleTapZoom: true,
isSpecified: false
});
return false;
}
let windowUtils = aWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
// viewport details found here
// http://developer.apple.com/safari/library/documentation/AppleApplications/Reference/SafariHTMLRef/Articles/MetaTags.html
// http://developer.apple.com/safari/library/documentation/AppleApplications/Reference/SafariWebContent/UsingtheViewport/UsingtheViewport.html
// Note: These values will be NaN if parseFloat or parseInt doesn't find a number.
// Remember that NaN is contagious: Math.max(1, NaN) == Math.min(1, NaN) == NaN.
let hasMetaViewport = true;
let scale = parseFloat(windowUtils.getDocumentMetadata("viewport-initial-scale"));
let minScale = parseFloat(windowUtils.getDocumentMetadata("viewport-minimum-scale"));
let maxScale = parseFloat(windowUtils.getDocumentMetadata("viewport-maximum-scale"));
let widthStr = windowUtils.getDocumentMetadata("viewport-width");
let heightStr = windowUtils.getDocumentMetadata("viewport-height");
// Allow zoom unless explicity disabled or minScale and maxScale are equal.
// WebKit allows 0, "no", or "false" for viewport-user-scalable.
// Note: NaN != NaN. Therefore if minScale and maxScale are undefined the clause has no effect.
let allowZoomStr = windowUtils.getDocumentMetadata("viewport-user-scalable");
let allowZoom = !/^(0|no|false)$/.test(allowZoomStr) && (minScale != maxScale);
// Double-tap should always be disabled if allowZoom is disabled. So we initialize
// allowDoubleTapZoom to the same value as allowZoom and have additional conditions to
// disable it in updateViewportSize.
let allowDoubleTapZoom = allowZoom;
if (isNaN(scale) && isNaN(minScale) && isNaN(maxScale) && allowZoomStr == "" && widthStr == "" && heightStr == "") {
// Only check for HandheldFriendly if we don't have a viewport meta tag
let handheldFriendly = windowUtils.getDocumentMetadata("HandheldFriendly");
if (handheldFriendly == "true") {
return new ViewportMetadata({
defaultZoom: 1,
allowZoom: true,
allowDoubleTapZoom: false
});
}
let doctype = aWindow.document.doctype;
if (doctype && /(WAP|WML|Mobile)/.test(doctype.publicId)) {
return new ViewportMetadata({
defaultZoom: 1,
allowZoom: true,
allowDoubleTapZoom: false
});
}
hasMetaViewport = false;
let defaultZoom = Services.prefs.getIntPref("browser.viewport.defaultZoom");
if (defaultZoom >= 0) {
scale = defaultZoom / 1000;
}
}
scale = this.clamp(scale, kViewportMinScale, kViewportMaxScale);
minScale = this.clamp(minScale, kViewportMinScale, kViewportMaxScale);
maxScale = this.clamp(maxScale, (isNaN(minScale) ? kViewportMinScale : minScale), kViewportMaxScale);
let isRTL = aWindow.document.documentElement.dir == "rtl";
return new ViewportMetadata({
defaultZoom: scale,
minZoom: minScale,
maxZoom: maxScale,
allowZoom: allowZoom,
allowDoubleTapZoom: allowDoubleTapZoom,
isSpecified: hasMetaViewport,
isRTL: isRTL
});
},
clamp: function(num, min, max) {
return Math.max(min, Math.min(max, num));
return !isNaN(parseFloat(windowUtils.getDocumentMetadata("viewport-initial-scale")))
|| !isNaN(parseFloat(windowUtils.getDocumentMetadata("viewport-minimum-scale")))
|| !isNaN(parseFloat(windowUtils.getDocumentMetadata("viewport-maximum-scale")))
|| ("" != windowUtils.getDocumentMetadata("viewport-user-scalable"))
|| ("" != windowUtils.getDocumentMetadata("viewport-width"))
|| ("" != windowUtils.getDocumentMetadata("viewport-height"));
},
get displayDPI() {
@ -6470,15 +6303,11 @@ var ViewportHandler = {
},
/**
* Returns the viewport metadata for the given document, or the default metrics if no viewport
* metadata is available for that document.
* Returns the viewport metadata for the given document, or undefined if there
* isn't one.
*/
getMetadataForDocument: function getMetadataForDocument(aDocument) {
let metadata = this._metadata.get(aDocument);
if (metadata === undefined) {
metadata = new ViewportMetadata();
}
return metadata;
return this._metadata.get(aDocument);
},
/** Updates the saved viewport metadata for the given content document. */
@ -6488,50 +6317,8 @@ var ViewportHandler = {
else
this._metadata.set(aDocument, aMetadata);
}
};
/**
* An object which represents the page's preferred viewport properties:
* defaultZoom (float): The initial scale when the page is loaded.
* minZoom (float): The minimum zoom level.
* maxZoom (float): The maximum zoom level.
* allowZoom (boolean): Let the user zoom in or out.
* allowDoubleTapZoom (boolean): Allow double-tap to zoom in.
* isSpecified (boolean): Whether the page viewport is specified or not.
*/
function ViewportMetadata(aMetadata = {}) {
this.defaultZoom = ("defaultZoom" in aMetadata) ? aMetadata.defaultZoom : 0;
this.minZoom = ("minZoom" in aMetadata) ? aMetadata.minZoom : 0;
this.maxZoom = ("maxZoom" in aMetadata) ? aMetadata.maxZoom : 0;
this.allowZoom = ("allowZoom" in aMetadata) ? aMetadata.allowZoom : true;
this.allowDoubleTapZoom = ("allowDoubleTapZoom" in aMetadata) ? aMetadata.allowDoubleTapZoom : true;
this.isSpecified = ("isSpecified" in aMetadata) ? aMetadata.isSpecified : false;
this.isRTL = ("isRTL" in aMetadata) ? aMetadata.isRTL : false;
Object.seal(this);
}
ViewportMetadata.prototype = {
defaultZoom: null,
minZoom: null,
maxZoom: null,
allowZoom: null,
allowDoubleTapZoom: null,
isSpecified: null,
isRTL: null,
toString: function() {
return "; defaultZoom=" + this.defaultZoom
+ "; minZoom=" + this.minZoom
+ "; maxZoom=" + this.maxZoom
+ "; allowZoom=" + this.allowZoom
+ "; allowDoubleTapZoom=" + this.allowDoubleTapZoom
+ "; isSpecified=" + this.isSpecified
+ "; isRTL=" + this.isRTL;
}
};
/**
* Handler for blocked popups, triggered by DOMUpdatePageReport events in browser.xml
*/

View File

@ -6,14 +6,15 @@ pref("security.tls.version.min", 1);
pref("security.tls.version.max", 3);
pref("security.tls.version.fallback-limit", 3);
pref("security.tls.insecure_fallback_hosts", "");
pref("security.tls.insecure_fallback_hosts.use_static_list", true);
#ifdef RELEASE_BUILD
pref("security.tls.unrestricted_rc4_fallback", true);
pref("security.tls.insecure_fallback_hosts.use_static_list", true);
#else
pref("security.tls.unrestricted_rc4_fallback", false);
pref("security.tls.insecure_fallback_hosts.use_static_list", false);
#endif
pref("security.tls.unrestricted_rc4_fallback", false);
pref("security.ssl.treat_unsafe_negotiation_as_broken", false);
pref("security.ssl.require_safe_negotiation", false);
pref("security.ssl.enable_ocsp_stapling", true);

File diff suppressed because it is too large Load Diff

View File

@ -169,9 +169,7 @@
"StartCom Certification Authority",
"StartCom Certification Authority",
"StartCom Certification Authority G2",
"TC TrustCenter Class 2 CA II",
"TC TrustCenter Class 3 CA II",
"TC TrustCenter Universal CA I",
"TC TrustCenter Universal CA III",
// "Thawte Premium Server CA",
"thawte Primary Root CA",

View File

@ -144,8 +144,8 @@ function download(filename) {
}
function downloadAsJson(filename) {
// we have to filter out '//' comments
let result = download(filename).replace(/\/\/[^\n]*\n/g, "");
// we have to filter out '//' comments, while not mangling the json
let result = download(filename).replace(/^(\s*)?\/\/[^\n]*\n/mg, "");
let data = null;
try {
data = JSON.parse(result);

View File

@ -85,8 +85,8 @@ function download() {
throw "ERROR: could not decode data as base64 from '" + SOURCE + "': " + e;
}
// we have to filter out '//' comments
var result = resultDecoded.replace(/\/\/[^\n]*\n/g, "");
// we have to filter out '//' comments, while not mangling the json
var result = resultDecoded.replace(/^(\s*)?\/\/[^\n]*\n/mg, "");
var data = null;
try {
data = JSON.parse(result);

View File

@ -0,0 +1,26 @@
FROM centos:6
MAINTAINER Dustin J. Mitchell <dustin@mozilla.com>
### add worker user and setup its workspace
RUN useradd -d /home/worker -s /bin/bash -m worker
# Declare default working folder
WORKDIR /home/worker
# install non-build specific dependencies in a single layer
ADD system-setup.sh /tmp/system-setup.sh
RUN bash /tmp/system-setup.sh
# Builds need the share module enabled
ADD hgrc /home/worker/.hgrc
RUN chown -R worker:worker /home/worker/.hgrc
# Set variable normally configured at login, by the shells parent process, these
# are taken from GNU su manual
ENV HOME /home/worker
ENV SHELL /bin/bash
ENV USER worker
ENV LOGNAME worker
ENV HOSTNAME taskcluster-worker
# Set a default command useful for debugging
CMD ["/bin/bash", "--login"]

View File

@ -0,0 +1 @@
taskcluster

View File

@ -0,0 +1 @@
0.0.1

View File

@ -0,0 +1,2 @@
[extensions]
share =

View File

@ -0,0 +1,274 @@
#!/usr/bin/env bash
set -ve
test `whoami` == 'root'
# lots of goodies in EPEL
yum install -y epel-release
# this sometimes fails, so we repeat it
yum makecache || yum makecache
yum shell -y <<'EOF'
# This covers a bunch of requirements
groupinstall Base
install findutils
install gawk
install ppl
install cpp
install grep
install gzip
install sed
install tar
install util-linux
install autoconf213
install zlib-devel
install perl-Test-Simple
install perl-Config-General
install xorg-x11-font* # fonts required for PGO
install dbus-x11
install libstdc++
install libstdc++.i686
# lots of required -devel packages
install libnotify-devel
install alsa-lib-devel
install libcurl-devel
install wireless-tools-devel
install libX11-devel
install libXt-devel
install mesa-libGL-devel
install GConf2-devel
install pulseaudio-libs-devel
install gstreamer-devel
install gstreamer-plugins-base-devel
# Prerequisites for GNOME that are not included in tooltool
install libpng-devel
install libXrandr-devel
# required for the Python build, below
install bzip2-devel
install openssl-devel
install xz-libs
install sqlite-devel
# required for the git build, below
install autoconf
install perl-ExtUtils-MakeMaker
install gettext-devel
# build utilities
install ccache
# a basic node environment so that we can run TaskCluster tools
install nodejs
install npm
# enough X to run `make check` and do a PGO build
install Xvfb
install xvinfo
run
EOF
BUILD=/root/build
mkdir $BUILD
# for the builds below, there's no sense using ccache
export CCACHE_DISABLE=1
cd $BUILD
curl https://raw.githubusercontent.com/mozilla/build-tooltool/master/tooltool.py > tooltool.py
tooltool_fetch() {
cat >manifest.tt
python $BUILD/tooltool.py fetch
rm manifest.tt
}
# For a few packges, we want to run the very latest, which is hard to find for
# stable old CentOS 6. Custom yum repostiories are cumbersome and can cause
# unhappy failures when they contain multiple versions of the same package. So
# we either build from source or install an RPM from tooltool (the former being
# the preferred solution for transparency). Each of these source files was
# downloaded directly from the upstream project site, although the RPMs are of
# unknown origin.
cd $BUILD
tooltool_fetch <<'EOF'
[
{
"size": 383372,
"digest": "486c34aeb01d2d083fdccd043fb8e3af93efddc7c185f38b5d7e90199733424c538ac2a7dfc19999c82ff00b84de5df75aa6f891e622cf1a86d698ed0bee16e2",
"algorithm": "sha512",
"filename": "freetype-2.4.12-6.el6.1.x86_64.rpm"
},
{
"size": 397772,
"digest": "79c7ddc943394509b96593f3aeac8946acd9c9dc10a3c248a783cb282781cbc9e4e7c47b98121dd7849d39aa3bd29313234ae301ab80f769010c2bacf41e6d40",
"algorithm": "sha512",
"filename": "freetype-devel-2.4.12-6.el6.1.x86_64.rpm"
},
{
"size": 17051332,
"digest": "57c816a6df9731aa5f34678abb59ea560bbdb5abd01df3f3a001dc94a3695d3190b1121caba483f8d8c4a405f4e53fde63a628527aca73f05652efeaec9621c4",
"algorithm": "sha512",
"filename": "valgrind-3.10.0-1.x86_64.rpm"
},
{
"size": 830601,
"digest": "c04dadf29a3ac676e93cb684b619f753584f8414167135eb766602671d08c85d7bc564511310564bdf2651d72da911b017f0969b9a26d84df724aebf8733f268",
"algorithm": "sha512",
"filename": "yasm-1.1.0-1.x86_64.rpm"
}
]
EOF
yum install -y freetype-*.rpm
yum install -y valgrind-*.rpm
yum install -y yasm-*.rpm
# The source RPMs for some of those; not used here, but included for reference
: <<'EOF'
[
{
"size": 10767445,
"digest": "d435897b602f7bdf77fabf1c80bbd06ba4f7288ad0ef31d19a863546d4651172421b45f2f090bad3c3355c9fa2a00352066f18d99bf994838579b768b90553d3",
"algorithm": "sha512",
"filename": "valgrind-3.10.0-1.src.rpm"
},
{
"size": 1906249,
"digest": "c3811c74e4ca3c342e6625cdb80a62903a14c56436774149754de67f41f79ee63248c71d039dd9341d22bdf4ef8b7dc8c90fe63dd9a3df44197d38a2d3d8f4a2",
"algorithm": "sha512",
"filename": "freetype-2.4.12-6.el6.1.src.rpm"
}
]
EOF
# Git
cd $BUILD
tooltool_fetch <<'EOF'
[
{
"size": 3740620,
"digest": "ef7538c9f5ba5b2ac08962401c30e5fd51323b54b9fb5315d259adccec346e8fae9362815832dc2b5ce63a259b315c40e419bb2385dde04d84b992e62f6789b6",
"algorithm": "sha512",
"unpack": true,
"filename": "git-2.5.0.tar.xz"
}
]
EOF
cd git-2.5.0
make configure
./configure --prefix=/usr --without-tcltk
make all install
git config --global user.email "nobody@mozilla.com"
git config --global user.name "mozilla"
# Python
cd $BUILD
tooltool_fetch <<'EOF'
[
{
"size": 12250696,
"digest": "67615a6defbcda062f15a09f9dd3b9441afd01a8cc3255e5bc45b925378a0ddc38d468b7701176f6cc153ec52a4f21671b433780d9bde343aa9b9c1b2ae29feb",
"algorithm": "sha512",
"filename": "Python-2.7.10.tar.xz",
"unpack": true
}
]
EOF
cd Python-2.7.10
./configure --prefix=/usr
make
# `altinstall` means that /usr/bin/python still points to CentOS's Python 2.6 install.
# If you want Python 2.7, use `python2.7`
make altinstall
# Enough python utilities to get "peep" working
cd $BUILD
tooltool_fetch <<'EOF'
[
{
"size": 630700,
"digest": "1367f3a10c1fef2f8061e430585f1927f6bd7c416e764d65cea1f4255824d549efa77beef8ff784bbd62c307b4b1123502e7b3fd01a243c0cc5b433a841cc8b5",
"algorithm": "sha512",
"filename": "setuptools-18.1.tar.gz",
"unpack": true
},
{
"size": 1051205,
"digest": "e7d2e003ec60fce5a75a6a23711d7f9b155e898faebcf55f3abdd912ef513f4e0cf43daca8f9da7179a7a4efe6e4a625a532d051349818847df1364eb5b326de",
"algorithm": "sha512",
"filename": "pip-6.1.1.tar.gz",
"unpack": true
},
{
"size": 26912,
"digest": "9d730ed7852d4d217aaddda959cd5f871ef1b26dd6c513a3780bbb04a5a93a49d6b78e95c2274451a1311c10cc0a72755b269dc9af62640474e6e73a1abec370",
"algorithm": "sha512",
"filename": "peep-2.4.1.tar.gz",
"unpack": false
}
]
EOF
cd $BUILD
cd setuptools-18.1
python2.7 setup.py install
# NOTE: latest peep is not compatible with pip>=7.0
# https://github.com/erikrose/peep/pull/94
cd $BUILD
cd pip-6.1.1
python2.7 setup.py install
cd $BUILD
pip2.7 install peep-2.4.1.tar.gz
# Peep (latest)
cd $BUILD
pip2.7 install peep
# remaining Python utilities are installed with `peep` from upstream
# repositories; peep verifies file integrity for us
cat >requirements.txt <<'EOF'
# sha256: 90pZQ6kAXB6Je8-H9-ivfgDAb6l3e5rWkfafn6VKh9g
virtualenv==13.1.2
# sha256: tQ9peOfTn-DLKY-j-j6c5B0jVnIdFV5SiPnFfl8T6ac
mercurial==3.5
EOF
peep install -r requirements.txt
# TC-VCS
npm install -g taskcluster-vcs@2.3.8
# note that TC will replace workspace with a cache mount; there's no sense
# creating anything inside there
mkdir -p /home/worker/workspace
chown worker:worker /home/worker/workspace
# /builds is *not* replaced with a mount in the docker container. The worker
# user writes to lots of subdirectories, though, so it's owned by that user
mkdir -p /builds
chown worker:worker /builds
# remove packages installed for the builds above
yum shell -y <<'EOF'
remove bzip2-devel
remove openssl-devel
remove xz-libs
remove autoconf
remove perl-ExtUtils-MakeMaker
remove gettext-devel
remove sqlite-devel
EOF
# clean up caches from all that downloading and building
cd /
rm -rf $BUILD ~/.ccache ~/.cache ~/.npm
yum clean all
rm $0

View File

@ -1,22 +1,13 @@
FROM taskcluster/ubuntu-build:0.0.5
MAINTAINER Morgan Reece Phillips <winter2718@gmail.com>
FROM taskcluster/centos6-build:0.0.1
MAINTAINER Dustin J. Mitchell <dustin@mozilla.com>
# Add build scripts; these are the entry points from the taskcluster worker, and
# operate on environment variables
ADD bin /home/worker/bin
RUN chmod +x /home/worker/bin/*
##
# COMPILER HACKS
##
ADD hacks.sh /tmp/
RUN /tmp/hacks.sh
# So that the compilers can find necessary libraries
# gcc
ENV LIBRARY_PATH /usr/lib/x86_64-linux-gnu
# clang
ENV CPLUS_INCLUDE_PATH /usr/include/c++/4.8:/usr/include/c++/4.8/backward:/usr/include/x86_64-linux-gnu/c++/4.8
# Generate machine uuid file
RUN dbus-uuidgen --ensure=/var/lib/dbus/machine-id
# Stubbed out credentials; mozharness looks for this file an issues a WARNING
# if it's not found, which causes the build to fail. Note that this needs to
@ -29,9 +20,10 @@ ADD oauth.txt /home/worker/
# the directory where mozharness is run (not its --work-dir)
ADD buildprops.json /home/worker/
# Make sure commands from here on run as `worker`
# XXX but non-root tasks aren't yet supported - bug 1093833
# USER worker
# install tooltool directly from github where tooltool_wrapper.sh et al. expect
# to find it
RUN wget -O /builds/tooltool.py https://raw.githubusercontent.com/mozilla/build-tooltool/master/tooltool.py
RUN chmod +x /builds/tooltool.py
# Set a default command useful for debugging
CMD ["/bin/bash", "--login"]

View File

@ -1 +1 @@
taskcluster
quay.io/djmitche

View File

@ -1 +1 @@
0.0.23
0.1.1

View File

@ -1,17 +0,0 @@
#!/usr/bin/env bash
##
# Install compiler hacks, necessary for builds to work properly,
# but ultimately to be removed in favor of something cleaner
##
# On ubuntu, the compiler that pip detects (x86_64-linux-gnu-gcc) is not
# available in the tooltool compiler, so we end up using the system default;
# to get around this, we link to the tooltool compiler that we'd prefer to use.
mv /usr/bin/x86_64-linux-gnu-gcc /usr/bin/x86_64-linux-gnu-gcc.orig
ln -s /home/worker/workspace/build/src/gcc/bin/gcc /usr/bin/x86_64-linux-gnu-gcc
# a.out.h needs to exist one directory lower, or the compiler will not find it
ln -s /usr/include/linux/a.out.h /usr/include/a.out.h
# Without this, zlib.h can't find zconf.h, so hey, symlinks to the rescue, right?
ln -s /usr/include/x86_64-linux-gnu/zconf.h /usr/include/zconf.h

View File

@ -736,7 +736,7 @@ class MochitestArguments(ArgumentContainer):
options.leakThresholds = {
"default": options.defaultLeakThreshold,
"tab": 14000, # See dependencies of bug 1051230.
"tab": 10000, # See dependencies of bug 1051230.
# GMP rarely gets a log, but when it does, it leaks a little.
"geckomediaplugin": 20000,
}

View File

@ -15,7 +15,7 @@ task:
- 'index.buildbot.revisions.{{head_rev}}.{{project}}.android-api-11'
scopes:
- 'docker-worker:cache:build-android-api-11-workspace'
- 'docker-worker:cache:build-android-api-11-c6-workspace'
- 'docker-worker:cache:tooltool-cache'
- 'docker-worker:relengapi-proxy:tooltool.download.internal'
- 'docker-worker:relengapi-proxy:tooltool.download.public'
@ -23,7 +23,7 @@ task:
payload:
image: '{{#docker_image}}desktop-build{{/docker_image}}'
cache:
build-android-api-11-workspace: '/home/worker/workspace'
build-android-api-11-c6-workspace: '/home/worker/workspace'
tooltool-cache: '/home/worker/tooltool-cache'
features:

View File

@ -15,14 +15,14 @@ task:
- 'index.buildbot.revisions.{{head_rev}}.{{project}}.linux64'
scopes:
- 'docker-worker:cache:build-linux64-workspace'
- 'docker-worker:cache:build-linux64-c6-workspace'
- 'docker-worker:cache:tooltool-cache'
- 'docker-worker:relengapi-proxy:tooltool.download.public'
payload:
image: '{{#docker_image}}desktop-build{{/docker_image}}'
cache:
build-linux64-workspace: '/home/worker/workspace'
build-linux64-c6-workspace: '/home/worker/workspace'
tooltool-cache: '/home/worker/tooltool-cache'
features:

View File

@ -21,7 +21,7 @@ task:
payload:
image: '{{#docker_image}}desktop-build{{/docker_image}}'
cache:
build-macosx64-workspace: '/home/worker/workspace'
build-macosx64-c6-workspace: '/home/worker/workspace'
tooltool-cache: '/home/worker/tooltool-cache'
features:
relengAPIProxy: true

View File

@ -14,7 +14,7 @@ task:
payload:
image: '{{#docker_image}}desktop-build{{/docker_image}}'
cache:
build-spidermonkey-workspace: '/home/worker/workspace'
build-spidermonkey-c6-workspace: '/home/worker/workspace'
env:
GECKO_REPOSITORY: '{{base_repository}}'

View File

@ -27,6 +27,7 @@ using mozilla::unused;
#include "nsAppShell.h"
#include "nsIdleService.h"
#include "nsLayoutUtils.h"
#include "nsWindow.h"
#include "nsIObserverService.h"
#include "nsFocusManager.h"
@ -2541,3 +2542,34 @@ nsWindow::GetMaxTouchPoints() const
{
return GeckoAppShell::GetMaxTouchPoints();
}
void
nsWindow::UpdateZoomConstraints(const uint32_t& aPresShellId,
const FrameMetrics::ViewID& aViewId,
const mozilla::Maybe<ZoomConstraints>& aConstraints)
{
#ifdef MOZ_ANDROID_APZ
nsBaseWidget::UpdateZoomConstraints(aPresShellId, aViewId, aConstraints);
#else
if (!aConstraints) {
// This is intended to "clear" previously stored constraints but in our
// case we don't need to bother since they'll get GC'd from browser.js
return;
}
nsIContent* content = nsLayoutUtils::FindContentFor(aViewId);
nsIDocument* doc = content ? content->GetComposedDoc() : nullptr;
if (!doc) {
return;
}
nsCOMPtr<nsIObserverService> obsServ = mozilla::services::GetObserverService();
nsPrintfCString json("{ \"allowZoom\": %s,"
" \"allowDoubleTapZoom\": %s,"
" \"minZoom\": %f,"
" \"maxZoom\": %f }",
aConstraints->mAllowZoom ? "true" : "false",
aConstraints->mAllowDoubleTapZoom ? "true" : "false",
aConstraints->mMinZoom.scale, aConstraints->mMaxZoom.scale);
obsServ->NotifyObservers(doc, "zoom-constraints-updated",
NS_ConvertASCIItoUTF16(json.get()).get());
#endif
}

View File

@ -169,6 +169,10 @@ public:
virtual uint32_t GetMaxTouchPoints() const override;
void UpdateZoomConstraints(const uint32_t& aPresShellId,
const FrameMetrics::ViewID& aViewId,
const mozilla::Maybe<ZoomConstraints>& aConstraints) override;
protected:
void BringToFront();
nsWindow *FindTopLevel();

View File

@ -1870,6 +1870,7 @@ nsIWidget::LookupRegisteredPluginWindow(uintptr_t aWindowID)
struct VisEnumContext {
uintptr_t parentWidget;
const nsTArray<uintptr_t>* list;
bool widgetVisibilityFlag;
};
static PLDHashOperator
@ -1882,9 +1883,8 @@ RegisteredPluginEnumerator(const void* aWindowId, nsIWidget* aWidget, void* aUse
if (!aWidget->Destroyed()) {
VisEnumContext* pctx = static_cast<VisEnumContext*>(aUserArg);
if ((uintptr_t)aWidget->GetParent() == pctx->parentWidget &&
!pctx->list->Contains((uintptr_t)aWindowId)) {
aWidget->Show(false);
if ((uintptr_t)aWidget->GetParent() == pctx->parentWidget) {
aWidget->Show(pctx->list->Contains((uintptr_t)aWindowId));
}
}
return PLDHashOperator::PL_DHASH_NEXT;
@ -1894,7 +1894,7 @@ RegisteredPluginEnumerator(const void* aWindowId, nsIWidget* aWidget, void* aUse
// static
void
nsIWidget::UpdateRegisteredPluginWindowVisibility(uintptr_t aOwnerWidget,
nsTArray<uintptr_t>& aVisibleList)
nsTArray<uintptr_t>& aPluginIds)
{
#if !defined(XP_WIN) && !defined(MOZ_WIDGET_GTK)
NS_NOTREACHED("nsBaseWidget::UpdateRegisteredPluginWindowVisibility not implemented!");
@ -1905,7 +1905,7 @@ nsIWidget::UpdateRegisteredPluginWindowVisibility(uintptr_t aOwnerWidget,
// Our visible list is associated with a compositor which is associated with
// a specific top level window. We hand the parent widget in here so the
// enumerator can skip the plugin widgets owned by other top level windows.
VisEnumContext ctx = { aOwnerWidget, &aVisibleList };
VisEnumContext ctx = { aOwnerWidget, &aPluginIds };
sPluginWidgetList->EnumerateRead(RegisteredPluginEnumerator, static_cast<void*>(&ctx));
#endif
}

View File

@ -1024,7 +1024,7 @@ class nsIWidget : public nsISupports {
* helper to hide widgets it knows nothing about.
*/
static void UpdateRegisteredPluginWindowVisibility(uintptr_t aOwnerWidget,
nsTArray<uintptr_t>& aVisibleList);
nsTArray<uintptr_t>& aPluginIds);
/**
* Set the shadow style of the window.