merge mozilla-inbound to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2016-03-02 15:54:19 +01:00
commit 33a2ccf44e
159 changed files with 3581 additions and 420 deletions

16
.gitignore vendored
View File

@ -9,6 +9,7 @@ tags
ID
.DS_Store*
*.pdb
*.egg-info
# Allow the id locale directory for loop ('ID' matches this normally)
!browser/extensions/loop/chrome/locale/id
@ -87,6 +88,17 @@ testing/web-platform/sync/
# Android Gradle artifacts.
mobile/android/gradle/.gradle
# XCode project cruft
embedding/ios/GeckoEmbed/GeckoEmbed.xcodeproj/project.xcworkspace/xcuserdata
embedding/ios/GeckoEmbed/GeckoEmbed.xcodeproj/xcuserdata
# Ignore mozharness execution files
testing/mozharness/.tox/
testing/mozharness/build/
testing/mozharness/logs/
testing/mozharness/.coverage
testing/mozharness/nosetests.xml
# Ignore node_modules from eslint-plugin-mozilla
testing/eslint-plugin-mozilla/node_modules/
@ -100,4 +112,6 @@ testing/talos/.Python
testing/talos/bin/
testing/talos/include/
testing/talos/lib/
testing/talos/talos/page_load_test/tp5n/
testing/talos/talos/tests/tp5n.zip
testing/talos/talos/tests/tp5n
testing/talos/talos/tests/devtools/damp.manifest.develop

View File

@ -6,7 +6,8 @@
(?i)(^|/)TAGS$
(^|/)ID$
(^|/)\.DS_Store$
.*\.egg-info
\.pdb
\.egg-info
# Vim swap files.
^\.sw.$
@ -106,8 +107,11 @@ GPATH
^embedding/ios/GeckoEmbed/GeckoEmbed.xcodeproj/xcuserdata
# Ignore mozharness execution files
^testing/mozharness/logs/
^testing/mozharness/.tox/
^testing/mozharness/build/
^testing/mozharness/logs/
^testing/mozharness/.coverage
^testing/mozharness/nosetests.xml
# Ignore tox generated dir
.tox/
@ -125,4 +129,6 @@ GPATH
^testing/talos/bin/
^testing/talos/include/
^testing/talos/lib/
^testing/talos/talos/page_load_test/tp5n/
^testing/talos/talos/tests/tp5n.zip
^testing/talos/talos/tests/tp5n
^testing/talos/talos/tests/devtools/damp.manifest.develop

View File

@ -2029,6 +2029,7 @@ DocAccessible::DoARIAOwnsRelocation(Accessible* aOwner)
MoveChild(child, insertIdx);
children->InsertElementAt(arrayIdx, child);
arrayIdx++;
insertIdx = child->IndexInParent() + 1;
} else if (SeizeChild(aOwner, child, insertIdx)) {
children->InsertElementAt(arrayIdx, child);
@ -2055,6 +2056,12 @@ DocAccessible::SeizeChild(Accessible* aNewParent, Accessible* aChild,
int32_t oldIdxInParent = aChild->IndexInParent();
#ifdef A11Y_LOG
logging::TreeInfo("aria owns seize child", 0,
"old parent", oldParent, "new parent", aNewParent,
"child", aChild, nullptr);
#endif
RefPtr<AccReorderEvent> reorderEvent = new AccReorderEvent(oldParent);
RefPtr<AccMutationEvent> hideEvent = new AccHideEvent(aChild, false);
reorderEvent->AddSubMutationEvent(hideEvent);
@ -2070,6 +2077,11 @@ DocAccessible::SeizeChild(Accessible* aNewParent, Accessible* aChild,
isReinserted = aNewParent->InsertChildAt(aIdxInParent, aChild);
}
#ifdef A11Y_LOG
logging::TreeInfo("aria owns seize child: new parent tree after",
logging::eVerbose, aNewParent);
#endif
if (!isReinserted) {
AutoTreeMutation mut(oldParent);
oldParent->InsertChildAt(oldIdxInParent, aChild);
@ -2108,10 +2120,20 @@ DocAccessible::MoveChild(Accessible* aChild, int32_t aIdxInParent)
RefPtr<AccMutationEvent> hideEvent = new AccHideEvent(aChild, false);
reorderEvent->AddSubMutationEvent(hideEvent);
#ifdef A11Y_LOG
logging::TreeInfo("aria owns move child", 0,
"parent", parent, "child", aChild, nullptr);
#endif
AutoTreeMutation mut(parent);
parent->MoveChild(aIdxInParent, aChild);
aChild->SetRelocated(true);
#ifdef A11Y_LOG
logging::TreeInfo("aria owns move child: parent tree after",
logging::eVerbose, parent);
#endif
FireDelayedEvent(hideEvent);
RefPtr<AccMutationEvent> showEvent = new AccShowEvent(aChild);

View File

@ -441,12 +441,44 @@
}
}
function rearrangeARIAOwns(aContainer, aAttr, aIdList, aRoleList)
{
this.eventSeq = [];
for (var id of aIdList) {
this.eventSeq.push(new invokerChecker(EVENT_HIDE, getNode(id)));
this.eventSeq.push(new invokerChecker(EVENT_SHOW, getNode(id)));
}
this.eventSeq.push(new invokerChecker(EVENT_REORDER, getNode(aContainer)));
this.invoke = function rearrangeARIAOwns_invoke()
{
getNode(aContainer).setAttribute("aria-owns", aAttr);
}
this.finalCheck = function rearrangeARIAOwns_finalCheck()
{
var tree = { SECTION: [ ] };
for (var role of aRoleList) {
var ch = {};
ch[role] = [];
tree["SECTION"].push(ch);
}
testAccessibleTree(aContainer, tree);
}
this.getID = function rearrangeARIAOwns_getID()
{
return `Rearrange @aria-owns attribute to '${aAttr}'`;
}
}
////////////////////////////////////////////////////////////////////////////
// Test
////////////////////////////////////////////////////////////////////////////
//gA11yEventDumpToConsole = true;
//enableLogging("tree"); // debug stuff
//enableLogging("tree,verbose"); // debug stuff
var gQueue = null;
@ -474,6 +506,16 @@
// test4
gQueue.push(new showHiddenElement());
// test5
gQueue.push(new rearrangeARIAOwns(
"t5_container", "t5_checkbox t5_radio t5_button",
[ "t5_checkbox", "t5_radio", "t5_button" ],
[ "CHECKBUTTON", "RADIOBUTTON", "PUSHBUTTON" ]));
gQueue.push(new rearrangeARIAOwns(
"t5_container", "t5_radio t5_button t5_checkbox",
[ "t5_radio", "t5_button" ],
[ "RADIOBUTTON", "PUSHBUTTON", "CHECKBUTTON" ]));
gQueue.invoke(); // SimpleTest.finish() will be called in the end
}
@ -515,6 +557,12 @@
<div id="t4_child1" style="display:none" role="checkbox"></div>
<div id="t4_child2" role="radio"></div>
</div>
<div id="t5_container">
<div role="button" id="t5_button"></div>
<div role="checkbox" id="t5_checkbox"></div>
<div role="radio" id="t5_radio"></div>
</div>
</body>
</html>

View File

@ -61,6 +61,7 @@ SEARCH_PATHS = [
'python/blessings',
'python/compare-locales',
'python/configobj',
'python/futures',
'python/jsmin',
'python/psutil',
'python/which',

View File

@ -1,6 +1,7 @@
[DEFAULT]
tags = devtools
subsuite = devtools
skip-if = (e10s && debug && os == 'mac') # bug 1252283
support-files =
doc_body_animation.html
doc_frame_script.js

View File

@ -45,6 +45,7 @@ skip-if = e10s # scratchpad.xul is not loading in e10s window
[browser_markup_anonymous_03.js]
[browser_markup_anonymous_04.js]
[browser_markup_copy_image_data.js]
skip-if = (e10s && os == 'mac') # bug 1252345
[browser_markup_css_completion_style_attribute.js]
[browser_markup_dragdrop_autoscroll.js]
skip-if = e10s && os == 'win'
@ -79,6 +80,7 @@ skip-if = e10s && os == 'win'
[browser_markup_html_edit_02.js]
[browser_markup_html_edit_03.js]
[browser_markup_image_tooltip.js]
skip-if = (e10s && os == 'mac') # bug 1252345
[browser_markup_image_tooltip_mutations.js]
[browser_markup_keybindings_01.js]
[browser_markup_keybindings_02.js]

View File

@ -70,7 +70,7 @@ support-files =
[browser_rules_completion-popup-hidden-after-navigation.js]
[browser_rules_content_01.js]
[browser_rules_content_02.js]
skip-if = e10s && debug && os == 'win' # Bug 1250058 - Docshell leak on win debug e10s
skip-if = e10s && debug && (os == 'mac' || os == 'win') # Bug 1250058 - Docshell leak on osx/win debug e10s
[browser_rules_context-menu-show-mdn-docs-01.js]
[browser_rules_context-menu-show-mdn-docs-02.js]
[browser_rules_context-menu-show-mdn-docs-03.js]

View File

@ -79,7 +79,7 @@ support-files =
[browser_inspector_iframe-navigation.js]
[browser_inspector_infobar_01.js]
[browser_inspector_initialization.js]
skip-if = e10s && debug && os == 'win' # Bug 1250058 - Docshell leak on win debug e10s
skip-if = e10s && debug && (os == 'mac' || os == 'win') # Bug 1250058 - Docshell leak on osx/win debug e10s
[browser_inspector_inspect-object-element.js]
[browser_inspector_invalidate.js]
[browser_inspector_keyboard-shortcuts-copy-outerhtml.js]

View File

@ -42,6 +42,7 @@ support-files =
[browser_net_aaa_leaktest.js]
[browser_net_accessibility-01.js]
[browser_net_accessibility-02.js]
skip-if = (toolkit == "cocoa" && e10s) # bug 1252254
[browser_net_api-calls.js]
[browser_net_autoscroll.js]
[browser_net_cached-status.js]

View File

@ -147,7 +147,7 @@ skip-if = (e10s && debug) || (e10s && os == 'win') # Bug 1221499 enabled these o
skip-if = e10s # Bug 1042253 - webconsole e10s tests (intermittent Linux debug)
[browser_bug_638949_copy_link_location.js]
[browser_bug_862916_console_dir_and_filter_off.js]
skip-if = (e10s && os == 'win') # Bug 1221499 enabled these on windows
skip-if = (e10s && (os == 'win' || os == 'mac')) # Bug 1243976
[browser_bug_865288_repeat_different_objects.js]
[browser_bug_865871_variables_view_close_on_esc_key.js]
[browser_bug_869003_inspect_cross_domain_object.js]
@ -187,7 +187,7 @@ skip-if = e10s # Bug 1042253 - webconsole e10s tests
skip-if = e10s # Bug 1042253 - webconsole tests disabled with e10s
[browser_eval_in_debugger_stackframe2.js]
[browser_jsterm_inspect.js]
skip-if = e10s && debug && os == 'win'
skip-if = e10s && debug && (os == 'win' || os == 'mac') # Bug 1243966
[browser_longstring_hang.js]
[browser_output_breaks_after_console_dir_uninspectable.js]
[browser_output_longstring_expand.js]
@ -277,7 +277,7 @@ skip-if = true # Bug 1110500 - mouse event failure in test
skip-if = e10s # Bug 1042253 - webconsole tests disabled with e10s
[browser_webconsole_bug_766001_JS_Console_in_Debugger.js]
[browser_webconsole_bug_770099_violation.js]
skip-if = e10s && os == 'win'
skip-if = e10s && (os == 'win' || os == 'mac') # Bug 1243978
[browser_webconsole_bug_782653_CSS_links_in_Style_Editor.js]
[browser_webconsole_bug_804845_ctrl_key_nav.js]
skip-if = os != "mac"
@ -287,11 +287,11 @@ skip-if = os != "mac"
[browser_webconsole_bug_1006027_message_timestamps_incorrect.js]
skip-if = e10s # Bug 1042253 - webconsole e10s tests (Linux debug intermittent)
[browser_webconsole_bug_1010953_cspro.js]
skip-if = e10s && os == 'win'
skip-if = e10s && (os == 'win' || os == 'mac') # Bug 1243967
[browser_webconsole_certificate_messages.js]
skip-if = e10s # Bug 1042253 - webconsole tests disabled with e10s
[browser_webconsole_show_subresource_security_errors.js]
skip-if = e10s && os == 'win'
skip-if = e10s && (os == 'win' || os == 'mac') # Bug 1243987
[browser_webconsole_cached_autocomplete.js]
[browser_webconsole_change_font_size.js]
[browser_webconsole_chrome.js]

View File

@ -2881,12 +2881,15 @@ nsDocShell::PopProfileTimelineMarkers(
JSContext* aCx,
JS::MutableHandle<JS::Value> aOut)
{
RefPtr<TimelineConsumers> timelines = TimelineConsumers::Get();
if (!timelines) {
return NS_OK;
}
nsTArray<dom::ProfileTimelineMarker> store;
SequenceRooter<dom::ProfileTimelineMarker> rooter(aCx, &store);
if (mObserved) {
mObserved->PopMarkers(aCx, store);
}
timelines->PopMarkers(this, aCx, store);
if (!ToJSValue(aCx, store, aOut)) {
JS_ClearPendingException(aCx);

View File

@ -294,6 +294,8 @@ private:
nsDocShell*, const char*, const TimeStamp&, MarkerTracingType);
friend void mozilla::TimelineConsumers::AddMarkerForDocShell(
nsDocShell*, UniquePtr<AbstractTimelineMarker>&&);
friend void mozilla::TimelineConsumers::PopMarkers(nsDocShell*,
JSContext*, nsTArray<dom::ProfileTimelineMarker>&);
public:
// Tell the favicon service that aNewURI has the same favicon as aOldURI.

View File

@ -45,6 +45,7 @@ ObservedDocShell::AddOTMTMarker(UniquePtr<AbstractTimelineMarker>&& aMarker)
void
ObservedDocShell::ClearMarkers()
{
MOZ_ASSERT(NS_IsMainThread());
MutexAutoLock lock(GetLock()); // for `mOffTheMainThreadTimelineMarkers`.
mTimelineMarkers.Clear();
mOffTheMainThreadTimelineMarkers.Clear();

View File

@ -294,4 +294,19 @@ TimelineConsumers::AddMarkerForAllObservedDocShells(UniquePtr<AbstractTimelineMa
}
}
void
TimelineConsumers::PopMarkers(nsDocShell* aDocShell,
JSContext* aCx,
nsTArray<dom::ProfileTimelineMarker>& aStore)
{
MOZ_ASSERT(NS_IsMainThread());
StaticMutexAutoLock lock(sMutex); // for `mMarkersStores`.
if (!aDocShell || !aDocShell->mObserved) {
return;
}
aDocShell->mObserved->PopMarkers(aCx, aStore);
}
} // namespace mozilla

View File

@ -15,12 +15,17 @@
class nsDocShell;
class nsIDocShell;
struct JSContext;
namespace mozilla {
class TimeStamp;
class MarkersStorage;
class AbstractTimelineMarker;
namespace dom {
struct ProfileTimelineMarker;
}
class TimelineConsumers : public nsIObserver
{
public:
@ -104,6 +109,10 @@ public:
// May be called from any thread.
void AddMarkerForAllObservedDocShells(UniquePtr<AbstractTimelineMarker>& aMarker);
void PopMarkers(nsDocShell* aDocShell,
JSContext* aCx,
nsTArray<dom::ProfileTimelineMarker>& aStore);
private:
static StaticRefPtr<TimelineConsumers> sInstance;
static bool sInShutdown;

View File

@ -54,7 +54,7 @@ skip-if = true
[test_bug509055.html]
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
[test_bug511449.html]
skip-if = toolkit != "cocoa"
skip-if = toolkit != "cocoa" || e10s
support-files = file_bug511449.html
[test_bug529119-1.html]
skip-if = buildapp == 'mulet' || (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage

View File

@ -19,6 +19,7 @@ TimingParams::TimingParams(const dom::AnimationEffectTimingProperties& aRhs,
: mDuration(aRhs.mDuration)
, mDelay(TimeDuration::FromMilliseconds(aRhs.mDelay))
, mIterations(aRhs.mIterations)
, mIterationStart(aRhs.mIterationStart)
, mDirection(aRhs.mDirection)
, mFill(aRhs.mFill)
{
@ -113,6 +114,7 @@ TimingParams::operator==(const TimingParams& aOther) const
return durationEqual &&
mDelay == aOther.mDelay &&
mIterations == aOther.mIterations &&
mIterationStart == aOther.mIterationStart &&
mDirection == aOther.mDirection &&
mFill == aOther.mFill &&
mFunction == aOther.mFunction;

View File

@ -51,6 +51,7 @@ struct TimingParams
dom::OwningUnrestrictedDoubleOrString mDuration;
TimeDuration mDelay; // Initializes to zero
double mIterations = 1.0; // Can be NaN, negative, +/-Infinity
double mIterationStart = 0.0;
dom::PlaybackDirection mDirection = dom::PlaybackDirection::Normal;
dom::FillMode mFill = dom::FillMode::Auto;
Maybe<ComputedTimingFunction> mFunction;
@ -85,7 +86,7 @@ public:
double Delay() const { return mTiming.mDelay.ToMilliseconds(); }
double EndDelay() const { return 0.0; }
FillMode Fill() const { return mTiming.mFill; }
double IterationStart() const { return 0.0; }
double IterationStart() const { return mTiming.mIterationStart; }
double Iterations() const { return mTiming.mIterations; }
void GetDuration(OwningUnrestrictedDoubleOrString& aRetVal) const
{

View File

@ -36,6 +36,7 @@ GetComputedTimingDictionary(const ComputedTiming& aComputedTiming,
aRetVal.mDelay = aTiming.mDelay.ToMilliseconds();
aRetVal.mFill = aComputedTiming.mFill;
aRetVal.mIterations = aComputedTiming.mIterations;
aRetVal.mIterationStart = aComputedTiming.mIterationStart;
aRetVal.mDuration.SetAsUnrestrictedDouble() =
aComputedTiming.mDuration.ToMilliseconds();
aRetVal.mDirection = aTiming.mDirection;
@ -45,6 +46,7 @@ GetComputedTimingDictionary(const ComputedTiming& aComputedTiming,
aRetVal.mEndTime = aComputedTiming.mEndTime.ToMilliseconds();
aRetVal.mLocalTime = AnimationUtils::TimeDurationToDouble(aLocalTime);
aRetVal.mProgress = aComputedTiming.mProgress;
if (!aRetVal.mProgress.IsNull()) {
// Convert the returned currentIteration into Infinity if we set
// (uint64_t) aComputedTiming.mCurrentIteration to UINT64_MAX
@ -244,6 +246,8 @@ KeyframeEffectReadOnly::GetComputedTimingAt(
result.mIterations = IsNaN(aTiming.mIterations) || aTiming.mIterations < 0.0f ?
1.0f :
aTiming.mIterations;
result.mIterationStart = std::max(aTiming.mIterationStart, 0.0);
result.mActiveDuration = ActiveDuration(result.mDuration, result.mIterations);
// Bug 1244635: Add endDelay to the end time calculation
result.mEndTime = aTiming.mDelay + result.mActiveDuration;
@ -273,10 +277,11 @@ KeyframeEffectReadOnly::GetComputedTimingAt(
return result;
}
activeTime = result.mActiveDuration;
// Note that infinity == floor(infinity) so this will also be true when we
// have finished an infinitely repeating animation of zero duration.
double finiteProgress =
(IsInfinite(result.mIterations) ? 0.0 : result.mIterations)
+ result.mIterationStart;
isEndOfFinalIteration = result.mIterations != 0.0 &&
result.mIterations == floor(result.mIterations);
fmod(finiteProgress, 1.0) == 0;
} else if (localTime < aTiming.mDelay) {
result.mPhase = ComputedTiming::AnimationPhase::Before;
if (!result.FillsBackwards()) {
@ -292,49 +297,66 @@ KeyframeEffectReadOnly::GetComputedTimingAt(
activeTime = localTime - aTiming.mDelay;
}
// Calculate the scaled active time
// (We handle the case where the iterationStart is zero separately in case
// the duration is infinity, since 0 * Infinity is undefined.)
StickyTimeDuration startOffset =
result.mIterationStart == 0.0
? StickyTimeDuration(0)
: result.mDuration.MultDouble(result.mIterationStart);
StickyTimeDuration scaledActiveTime = activeTime + startOffset;
// Get the position within the current iteration.
StickyTimeDuration iterationTime;
if (result.mDuration != zeroDuration) {
if (result.mDuration != zeroDuration &&
scaledActiveTime != StickyTimeDuration::Forever()) {
iterationTime = isEndOfFinalIteration
? result.mDuration
: activeTime % result.mDuration;
} /* else, iterationTime is zero */
: scaledActiveTime % result.mDuration;
} /* else, either the duration is zero and iterationTime is zero,
or the scaledActiveTime is infinity in which case the iterationTime
should become infinity but we will not use the iterationTime in that
case so we just leave it as zero */
// Determine the 0-based index of the current iteration.
if (isEndOfFinalIteration) {
if (result.mPhase == ComputedTiming::AnimationPhase::Before ||
result.mIterations == 0) {
result.mCurrentIteration = static_cast<uint64_t>(result.mIterationStart);
} else if (result.mPhase == ComputedTiming::AnimationPhase::After) {
result.mCurrentIteration =
IsInfinite(result.mIterations) // Positive Infinity?
IsInfinite(result.mIterations)
? UINT64_MAX // In GetComputedTimingDictionary(), we will convert this
// into Infinity.
: static_cast<uint64_t>(result.mIterations) - 1;
} else if (activeTime == zeroDuration) {
// If the active time is zero we're either in the first iteration
// (including filling backwards) or we have finished an animation with an
// iteration duration of zero that is filling forwards (but we're not at
// the exact end of an iteration since we deal with that above).
result.mCurrentIteration =
result.mPhase == ComputedTiming::AnimationPhase::After
? static_cast<uint64_t>(result.mIterations) // floor
: 0;
: static_cast<uint64_t>(ceil(result.mIterations +
result.mIterationStart)) - 1;
} else if (result.mDuration == StickyTimeDuration::Forever()) {
result.mCurrentIteration = static_cast<uint64_t>(result.mIterationStart);
} else {
result.mCurrentIteration =
static_cast<uint64_t>(activeTime / result.mDuration); // floor
static_cast<uint64_t>(scaledActiveTime / result.mDuration); // floor
}
// Normalize the iteration time into a fraction of the iteration duration.
if (result.mPhase == ComputedTiming::AnimationPhase::Before) {
result.mProgress.SetValue(0.0);
if (result.mPhase == ComputedTiming::AnimationPhase::Before ||
result.mIterations == 0) {
double progress = fmod(result.mIterationStart, 1.0);
result.mProgress.SetValue(progress);
} else if (result.mPhase == ComputedTiming::AnimationPhase::After) {
double progress = isEndOfFinalIteration
? 1.0
: fmod(result.mIterations, 1.0);
double progress;
if (isEndOfFinalIteration) {
progress = 1.0;
} else if (IsInfinite(result.mIterations)) {
progress = fmod(result.mIterationStart, 1.0);
} else {
progress = fmod(result.mIterations + result.mIterationStart, 1.0);
}
result.mProgress.SetValue(progress);
} else {
// We are in the active phase so the iteration duration can't be zero.
MOZ_ASSERT(result.mDuration != zeroDuration,
"In the active phase of a zero-duration animation?");
double progress = result.mDuration == StickyTimeDuration::Forever()
? 0.0
? fmod(result.mIterationStart, 1.0)
: iterationTime / result.mDuration;
result.mProgress.SetValue(progress);
}

View File

@ -69,6 +69,7 @@ struct ComputedTiming
// Unlike TimingParams::mIterations, this value is
// guaranteed to be in the range [0, Infinity].
double mIterations = 1.0;
double mIterationStart = 0.0;
StickyTimeDuration mDuration;
// This is the computed fill mode so it is never auto

View File

@ -40,6 +40,7 @@
#include "nsIAsyncVerifyRedirectCallback.h"
#include "nsIAppShell.h"
#include "nsIXULRuntime.h"
#include "nsIScriptError.h"
#include "nsError.h"
@ -1482,8 +1483,8 @@ nsObjectLoadingContent::CheckJavaCodebase()
return true;
}
bool
nsObjectLoadingContent::ShouldRewriteYoutubeEmbed(nsIURI* aURI)
void
nsObjectLoadingContent::MaybeRewriteYoutubeEmbed(nsIURI* aURI, nsIURI* aBaseURI, nsIURI** aOutURI)
{
nsCOMPtr<nsIContent> thisContent =
do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
@ -1492,14 +1493,15 @@ nsObjectLoadingContent::ShouldRewriteYoutubeEmbed(nsIURI* aURI)
// We're only interested in switching out embed and object tags
if (!thisContent->NodeInfo()->Equals(nsGkAtoms::embed) &&
!thisContent->NodeInfo()->Equals(nsGkAtoms::object)) {
return false;
return;
}
nsCOMPtr<nsIEffectiveTLDService> tldService =
do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID);
// If we can't analyze the URL, just pass on through.
if(!tldService) {
NS_WARNING("Could not get TLD service!");
return false;
return;
}
nsAutoCString currentBaseDomain;
@ -1507,12 +1509,12 @@ nsObjectLoadingContent::ShouldRewriteYoutubeEmbed(nsIURI* aURI)
if (!ok) {
// Data URIs (commonly used for things like svg embeds) won't parse
// correctly, so just fail silently here.
return false;
return;
}
// See if URL is referencing youtube
if (!currentBaseDomain.EqualsLiteral("youtube.com")) {
return false;
return;
}
// We should only rewrite URLs with paths starting with "/v/", as we shouldn't
@ -1520,7 +1522,7 @@ nsObjectLoadingContent::ShouldRewriteYoutubeEmbed(nsIURI* aURI)
nsAutoCString path;
aURI->GetPath(path);
if (!StringBeginsWith(path, NS_LITERAL_CSTRING("/v/"))) {
return false;
return;
}
// See if requester is planning on using the JS API.
@ -1528,15 +1530,73 @@ nsObjectLoadingContent::ShouldRewriteYoutubeEmbed(nsIURI* aURI)
aURI->GetSpec(uri);
if (uri.Find("enablejsapi=1", true, 0, -1) != kNotFound) {
Telemetry::Accumulate(Telemetry::YOUTUBE_NONREWRITABLE_EMBED_SEEN, 1);
return false;
return;
}
// Some youtube urls have invalid query strings attached, e.g.
// http://youtube.com/embed/7LcUOEP7Brc&start=35. These URLs work with flash,
// but break iframe/object embedding. If this situation occurs with rewritten
// URLs, and the user has flash installed, just use flash. If the user does
// not have flash installed or activated, chop off the query in order to make
// the video load correctly as an iframe. In either case, warn about it in the
// developer console.
int32_t ampIndex = uri.FindChar('&', 0);
bool trimQuery = false;
if (ampIndex != -1) {
int32_t qmIndex = uri.FindChar('?', 0);
if (qmIndex == -1 ||
qmIndex > ampIndex) {
if (!nsContentUtils::IsSWFPlayerEnabled()) {
trimQuery = true;
} else {
// Flash is enabled, just use it in this case.
return;
}
}
}
// If we've made it this far, we've got a rewritable embed. Log it in
// telemetry.
Telemetry::Accumulate(Telemetry::YOUTUBE_REWRITABLE_EMBED_SEEN, 1);
// Even if node is rewritable, only rewrite if the pref tells us we should.
return Preferences::GetBool(kPrefYoutubeRewrite);
// If we're pref'd off, return after telemetry has been logged.
if (!Preferences::GetBool(kPrefYoutubeRewrite)) {
return;
}
nsAutoString utf16OldURI = NS_ConvertUTF8toUTF16(uri);
// If we need to trim the query off the URL, it means it's malformed, and an
// ampersand comes first. Use the index we found earlier.
if (trimQuery) {
uri.Truncate(ampIndex);
}
// Switch out video access url formats, which should possibly allow HTML5
// video loading.
uri.ReplaceSubstring(NS_LITERAL_CSTRING("/v/"),
NS_LITERAL_CSTRING("/embed/"));
nsAutoString utf16URI = NS_ConvertUTF8toUTF16(uri);
nsresult rv = nsContentUtils::NewURIWithDocumentCharset(aOutURI,
utf16URI,
thisContent->OwnerDoc(),
aBaseURI);
if (NS_FAILED(rv)) {
return;
}
const char16_t* params[] = { utf16OldURI.get(), utf16URI.get() };
const char* msgName;
// If there's no query to rewrite, just notify in the developer console
// that we're changing the embed.
if (!trimQuery) {
msgName = "RewriteYoutubeEmbed";
} else {
msgName = "RewriteYoutubeEmbedInvalidQuery";
}
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
NS_LITERAL_CSTRING("Plugins"),
thisContent->OwnerDoc(),
nsContentUtils::eDOM_PROPERTIES,
msgName,
params, ArrayLength(params));
}
bool
@ -1794,15 +1854,12 @@ nsObjectLoadingContent::UpdateObjectParameters(bool aJavaURI)
uriStr,
thisContent->OwnerDoc(),
newBaseURI);
if (ShouldRewriteYoutubeEmbed(newURI)) {
// Switch out video access url formats, which should possibly allow HTML5
// video loading.
uriStr.ReplaceSubstring(NS_LITERAL_STRING("/v/"),
NS_LITERAL_STRING("/embed/"));
rv = nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(newURI),
uriStr,
thisContent->OwnerDoc(),
newBaseURI);
nsCOMPtr<nsIURI> rewrittenURI;
MaybeRewriteYoutubeEmbed(newURI,
newBaseURI,
getter_AddRefs(rewrittenURI));
if (rewrittenURI) {
newURI = rewrittenURI;
newMime = NS_LITERAL_CSTRING("text/html");
}

View File

@ -538,7 +538,9 @@ class nsObjectLoadingContent : public nsImageLoadingContent
* our type to eType_Document so that we render similarly to an iframe
* embed.
*/
bool ShouldRewriteYoutubeEmbed(nsIURI* uri);
void MaybeRewriteYoutubeEmbed(nsIURI* aURI,
nsIURI* aBaseURI,
nsIURI** aRewrittenURI);
// Helper class for SetupProtoChain
class SetupProtoChainRunner final : public nsIRunnable

View File

@ -872,3 +872,4 @@ skip-if = buildapp == 'b2g' #no ssl support
[test_bug1187157.html]
[test_bug769117.html]
[test_bug1250148.html]
[test_bug1240471.html]

View File

@ -0,0 +1,45 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1240471
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 1240471</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript">
SimpleTest.waitForExplicitFinish();
"use strict";
function onLoad () {
let youtube_changed_url_noquery = "https://mochitest.youtube.com/embed/Xm5i5kbIXzc";
let youtube_changed_url_query = "https://mochitest.youtube.com/embed/Xm5i5kbIXzc?start=10&end=20";
function testEmbed(embed, expected_url) {
ok (embed, "Embed node exists");
embed = SpecialPowers.wrap(embed);
is (embed.srcURI.spec, expected_url, "Should have src uri of " + expected_url);
}
info("Running youtube rewrite query test");
testEmbed(document.getElementById("testembed-correct"), youtube_changed_url_query);
testEmbed(document.getElementById("testembed-wrong"), youtube_changed_url_noquery);
testEmbed(document.getElementById("testembed-whywouldyouevendothat"), youtube_changed_url_noquery);
SimpleTest.finish();
}
</script>
</head>
<body onload="onLoad()">
<embed id="testembed-correct"
src="https://mochitest.youtube.com/v/Xm5i5kbIXzc?start=10&end=20"
type="application/x-shockwave-flash"
allowscriptaccess="always"></embed>
<embed id="testembed-wrong"
src="https://mochitest.youtube.com/v/Xm5i5kbIXzc&start=10&end=20"
type="application/x-shockwave-flash"
allowscriptaccess="always"></embed>
<embed id="testembed-whywouldyouevendothat"
src="https://mochitest.youtube.com/v/Xm5i5kbIXzc&start=10?end=20"
type="application/x-shockwave-flash"
allowscriptaccess="always"></embed>
</body>
</html>

View File

@ -0,0 +1,273 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_BluetoothGattUUIDName_h
#define mozilla_dom_BluetoothGattUUIDName_h
namespace mozilla {
namespace dom {
struct BluetoothGattUUIDName
{
const char* name;
uint16_t uuid;
};
static BluetoothGattUUIDName ServiceTable[] = {
/**
* https://developer.bluetooth.org/gatt/services/Pages/ServicesHome.aspx
*/
{"alert_notification", 0x1811},
{"automation_io", 0x1815},
{"battery_service", 0x180F},
{"blood_pressure", 0x1810},
{"body_composition", 0x181B},
{"bond_management", 0x181E},
{"continuous_glucose_monitoring", 0x181F},
{"current_time", 0x1805},
{"cycling_power", 0x1818},
{"cycling_speed_and_cadence", 0x1816},
{"device_information", 0x180A},
{"environmental_sensing", 0x181A},
{"generic_access", 0x1800},
{"generic_attribute", 0x1801},
{"glucose", 0x1808},
{"health_thermometer", 0x1809},
{"heart_rate", 0x180D},
{"http_proxy", 0x1823},
{"human_interface_device", 0x1812},
{"immediate_alert", 0x1802},
{"indoor_positioning", 0x1821},
{"internet_protocol_support", 0x1820},
{"link_loss", 0x1803},
{"location_and_navigation", 0x1819},
{"next_dst_change", 0x1807},
{"object_transfer", 0x1825},
{"phone_alert_status", 0x180E},
{"pulse_oximeter", 0x1822},
{"reference_time_update", 0x1806},
{"running_speed_and_cadence", 0x1814},
{"scan_parameters", 0x1813},
{"transport_discovery", 0x1824},
{"tx_power", 0x1804},
{"user_data", 0x181C},
{"weight_scale", 0x181D},
};
static BluetoothGattUUIDName CharacteristicTable[] = {
/**
* https://developer.bluetooth.org/gatt/characteristics/Pages/\
* CharacteristicsHome.aspx
*/
{"aerobic_heart_rate_lower_limit", 0x2A7E},
{"aerobic_heart_rate_upper_limit", 0x2A84},
{"aerobic_threshold", 0x2A7F},
{"age", 0x2A80},
{"aggregate", 0x2A5A},
{"alert_category_id", 0x2A43},
{"alert_category_id_bit_mask", 0x2A42},
{"alert_level", 0x2A06},
{"alert_notification_control_point", 0x2A44},
{"alert_status", 0x2A3F},
{"altitude", 0x2AB3},
{"anaerobic_heart_rate_lower_limit", 0x2A81},
{"anaerobic_heart_rate_upper_limit", 0x2A82},
{"anaerobic_threshold", 0x2A83},
{"analog", 0x2A58},
{"apparent_wind_direction", 0x2A73},
{"apparent_wind_speed", 0x2A72},
{"gap.appearance", 0x2A01},
{"barometric_pressure_trend", 0x2AA3},
{"battery_level", 0x2A19},
{"blood_pressure_feature", 0x2A49},
{"blood_pressure_measurement", 0x2A35},
{"body_composition_feature", 0x2A9B},
{"body_composition_measurement", 0x2A9C},
{"body_sensor_location", 0x2A38},
{"bond_management_control_point", 0x2AA4},
{"bond_management_feature", 0x2AA5},
{"boot_keyboard_input_report", 0x2A22},
{"boot_keyboard_output_report", 0x2A32},
{"boot_mouse_input_report", 0x2A33},
{"gap.central_address_resolution_support", 0x2AA6},
{"cgm_feature", 0x2AA8},
{"cgm_measurement", 0x2AA7},
{"cgm_session_run_time", 0x2AAB},
{"cgm_session_start_time", 0x2AAA},
{"cgm_specific_ops_control_point", 0x2AAC},
{"cgm_status", 0x2AA9},
{"csc_feature", 0x2A5C},
{"csc_measurement", 0x2A5B},
{"current_time", 0x2A2B},
{"cycling_power_control_point", 0x2A66},
{"cycling_power_feature", 0x2A65},
{"cycling_power_measurement", 0x2A63},
{"cycling_power_vector", 0x2A64},
{"database_change_increment", 0x2A99},
{"date_of_birth", 0x2A85},
{"date_of_threshold_assessment", 0x2A86},
{"date_time", 0x2A08},
{"day_date_time", 0x2A0A},
{"day_of_week", 0x2A09},
{"descriptor_value_changed", 0x2A7D},
{"gap.device_name", 0x2A00},
{"dew_point", 0x2A7B},
{"digital", 0x2A56},
{"dst_offset", 0x2A0D},
{"elevation", 0x2A6C},
{"email_address", 0x2A87},
{"exact_time_256", 0x2A0C},
{"fat_burn_heart_rate_lower_limit", 0x2A88},
{"fat_burn_heart_rate_upper_limit", 0x2A89},
{"firmware_revision_string", 0x2A26},
{"first_name", 0x2A8A},
{"five_zone_heart_rate_limits", 0x2A8B},
{"floor_number", 0x2AB2},
{"gender", 0x2A8C},
{"glucose_feature", 0x2A51},
{"glucose_measurement", 0x2A18},
{"glucose_measurement_context", 0x2A34},
{"gust_factor", 0x2A74},
{"hardware_revision_string", 0x2A27},
{"heart_rate_control_point", 0x2A39},
{"heart_rate_max", 0x2A8D},
{"heart_rate_measurement", 0x2A37},
{"heat_index", 0x2A7A},
{"height", 0x2A8E},
{"hid_control_point", 0x2A4C},
{"hid_information", 0x2A4A},
{"hip_circumference", 0x2A8F},
{"http_control_point", 0x2ABA},
{"http_entity_body", 0x2AB9},
{"http_headers", 0x2AB7},
{"http_status_code", 0x2AB8},
{"http_security", 0x2ABB},
{"humidity", 0x2A6F},
{"ieee_11073-20601_regulatory_certification_data_list",
0x2A2A},
{"indoor_positioning_configuration", 0x2AAD},
{"intermediate_blood_pressure", 0x2A36},
{"intermediate_temperature", 0x2A1E},
{"irradiance", 0x2A77},
{"language", 0x2AA2},
{"last_name", 0x2A90},
{"latitude", 0x2AAE},
{"ln_control_point", 0x2A6B},
{"ln_feature", 0x2A6A},
{"local_east_coordinate.xml", 0x2AB1},
{"local_north_coordinate", 0x2AB0},
{"local_time_information", 0x2A0F},
{"location_and_speed", 0x2A67},
{"location_name", 0x2AB5},
{"longitude", 0x2AAF},
{"magnetic_declination", 0x2A2C},
{"magnetic_flux_density_2D", 0x2AA0},
{"magnetic_flux_density_3D", 0x2AA1},
{"manufacturer_name_string", 0x2A29},
{"maximum_recommended_heart_rate", 0x2A91},
{"measurement_interval", 0x2A21},
{"model_number_string", 0x2A24},
{"navigation", 0x2A68},
{"new_alert", 0x2A46},
{"object_action_control_point", 0x2AC5},
{"object_changed", 0x2AC8},
{"object_first_created", 0x2AC1},
{"object_id", 0x2AC3},
{"object_last_modified", 0x2AC2},
{"object_list_control_point", 0x2AC6},
{"object_list_filter", 0x2AC7},
{"object_name", 0x2ABE},
{"object_properties", 0x2AC4},
{"object_size", 0x2AC0},
{"object_type", 0x2ABF},
{"object_ots_feature", 0x2ABD},
{"gap.peripheral_preferred_connection_parameters",
0x2A04},
{"gap.peripheral_privacy_flag", 0x2A02},
{"plx_continuous_measurement", 0x2A5F},
{"plx_features", 0x2A60},
{"plx_spot_check_measurement", 0x2A5E},
{"pnp_id", 0x2A50},
{"pollen_concentration", 0x2A75},
{"position_quality", 0x2A69},
{"pressure", 0x2A6D},
{"protocol_mode", 0x2A4E},
{"rainfall", 0x2A78},
{"gap.reconnection_address", 0x2A03},
{"record_access_control_point", 0x2A52},
{"reference_time_information", 0x2A14},
{"report", 0x2A4D},
{"report_map", 0x2A4B},
{"resting_heart_rate", 0x2A92},
{"ringer_control_point", 0x2A40},
{"ringer_setting", 0x2A41},
{"rsc_feature", 0x2A54},
{"rsc_measurement", 0x2A53},
{"sc_control_point", 0x2A55},
{"scan_interval_window", 0x2A4F},
{"scan_refresh", 0x2A31},
{"sensor_location", 0x2A5D},
{"serial_number_string", 0x2A25},
{"gatt.service_changed", 0x2A05},
{"software_revision_string", 0x2A28},
{"sport_type_for_aerobic_and_anaerobic_thresholds",
0x2A93},
{"supported_new_alert_category", 0x2A47},
{"supported_unread_alert_category", 0x2A48},
{"system_id", 0x2A23},
{"temperature", 0x2A6E},
{"temperature_measurement", 0x2A1C},
{"temperature_type", 0x2A1D},
{"three_zone_heart_rate_limits", 0x2A94},
{"time_accuracy", 0x2A12},
{"time_source", 0x2A13},
{"time_update_control_point", 0x2A16},
{"time_update_state", 0x2A17},
{"time_with_dst", 0x2A11},
{"time_zone", 0x2A0E},
{"true_wind_direction", 0x2A71},
{"true_wind_speed", 0x2A70},
{"two_zone_heart_rate_limit", 0x2A95},
{"tx_power_level", 0x2A07},
{"uncertainty", 0x2AB4},
{"unread_alert_status", 0x2A45},
{"uri", 0x2AB6},
{"user_control_point", 0x2A9F},
{"user_index", 0x2A9A},
{"uv_index", 0x2A76},
{"vo2_max", 0x2A96},
{"waist_circumference", 0x2A97},
{"weight", 0x2A98},
{"weight_measurement", 0x2A9D},
{"weight_scale_feature", 0x2A9E},
{"wind_chill", 0x2A79},
};
static BluetoothGattUUIDName DescriptorTable[] = {
/**
* https://developer.bluetooth.org/gatt/descriptors/Pages\
* /DescriptorsHomePage.aspx
*/
{"gatt.characteristic_extended_properties", 0x2900},
{"gatt.characteristic_user_description", 0x2901},
{"gatt.client_characteristic_configuration", 0x2902},
{"gatt.server_characteristic_configuration", 0x2903},
{"gatt.characteristic_presentation_format", 0x2904},
{"gatt.characteristic_aggregate_format", 0x2905},
{"valid_range", 0x2906},
{"external_report_reference", 0x2907},
{"report_reference", 0x2908},
{"number_of_digitals", 0x2909},
{"value_trigger_setting", 0x290A},
{"es_configuration", 0x290B},
{"es_measurement", 0x290C},
{"es_trigger_setting", 0x290D},
{"time_trigger_setting", 0x290E},
};
}// dom
}// mozilla
#endif // mozilla_dom_BluetoothGattUUIDName_h

View File

@ -0,0 +1,234 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/bluetooth/BluetoothCommon.h"
#include "mozilla/dom/bluetooth/BluetoothGattUUIDName.h"
#include "mozilla/dom/BluetoothUUID.h"
#include "mozilla/dom/UnionTypes.h" /* StringOrUnsignedLong */
using namespace mozilla;
using namespace mozilla::dom;
bool BluetoothUUID::sInShutdown = false;
// static
nsDataHashtable<nsStringHashKey, uint32_t>*
BluetoothUUID::sUUIDServiceTable;
// static
nsDataHashtable<nsStringHashKey, uint32_t>*
BluetoothUUID::sUUIDCharacteristicTable;
// static
nsDataHashtable<nsStringHashKey, uint32_t>*
BluetoothUUID::sUUIDDescriptorTable;
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(BluetoothUUID, mOwner)
NS_IMPL_CYCLE_COLLECTING_ADDREF(BluetoothUUID)
NS_IMPL_CYCLE_COLLECTING_RELEASE(BluetoothUUID)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(BluetoothUUID)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
BluetoothUUID::BluetoothUUID(nsPIDOMWindowInner* aOwner)
: mOwner(aOwner)
{
MOZ_ASSERT(aOwner);
}
BluetoothUUID::~BluetoothUUID()
{
}
JSObject*
BluetoothUUID::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto)
{
return BluetoothUUIDBinding::Wrap(aCx, this, aGivenProto);
}
//static
void BluetoothUUID::HandleShutdown()
{
sInShutdown = true;
delete sUUIDServiceTable;
delete sUUIDCharacteristicTable;
delete sUUIDDescriptorTable;
sUUIDServiceTable = nullptr;
sUUIDCharacteristicTable = nullptr;
sUUIDDescriptorTable = nullptr;
}
// static
void
BluetoothUUID::InitServiceTable()
{
size_t length = sizeof(ServiceTable) / sizeof(BluetoothGattUUIDName);
for (size_t i = 0; i < length; ++i) {
sUUIDServiceTable->Put(NS_ConvertUTF8toUTF16(ServiceTable[i].name),
ServiceTable[i].uuid);
}
}
// static
void
BluetoothUUID::InitCharacteristicTable()
{
size_t length = sizeof(CharacteristicTable) / sizeof(BluetoothGattUUIDName);
for (size_t i = 0; i < length; ++i) {
sUUIDCharacteristicTable->Put(NS_ConvertUTF8toUTF16(
CharacteristicTable[i].name),
CharacteristicTable[i].uuid);
}
}
// static
void
BluetoothUUID::InitDescriptorTable()
{
size_t length = sizeof(DescriptorTable) / sizeof(BluetoothGattUUIDName);
for (size_t i = 0; i < length; ++i) {
sUUIDDescriptorTable->Put(NS_ConvertUTF8toUTF16(DescriptorTable[i].name),
DescriptorTable[i].uuid);
}
}
/**
* Check whether the UUID(aString) is valid or not
*/
bool IsValidUUID(const nsAString& aString)
{
size_t length = aString.Length();
if (length != 36) {
return false;
}
const char16_t* uuid = aString.BeginReading();
for (size_t i = 0; i < length; ++i) {
if (i == 8 || i == 13 || i == 18 || i == 23) {
if (uuid[i] != '-') {
return false;
}
} else if ((uuid[i] < '0' || uuid[i] > '9') &&
(uuid[i] < 'a' || uuid[i] > 'f')) {
return false;
}
}
return true;
}
// static
void
BluetoothUUID::ResolveUUIDName(const GlobalObject& aGlobal,
const StringOrUnsignedLong& aName,
GattAttribute aAttr, nsAString& aReturn,
ErrorResult& aRv)
{
aReturn.Truncate();
if (aName.IsUnsignedLong()) {
// aName is a 16-bit or 32-bit UUID alias.
CanonicalUUID(aGlobal, aName.GetAsUnsignedLong(), aReturn);
} else if (aName.IsString()) {
uint32_t alias = 0;
nsString aString(aName.GetAsString());
if (IsValidUUID(aString)) {
// aName is a valid UUID String.
aReturn.Assign(aString);
} else if (GetTable(aAttr, aString, alias)) {
// The UUID string can be mapped to a known UUID alias.
CanonicalUUID(aGlobal, alias, aReturn);
} else {
// Exception, Syntax error, assign aReturn the error message
aRv.ThrowDOMException(NS_ERROR_DOM_SYNTAX_ERR,
NS_LITERAL_CSTRING("Invalid name: It can be a"
" 32-bit UUID alias, 128-bit valid UUID "
"(lower-case hex characters) or known "
"Service/Characteristic/Descriptor name."));
return ;
}
} else {
MOZ_ASSERT(false, "Invalid name: It can be a 32-bit UUID alias, 128-bit "
"valid UUID (lower-case hex characters) or known "
"Service/Characteristic/Descriptor name.");
}
}
// static
bool
BluetoothUUID::GetTable(GattAttribute aAttr, const nsAString& aString,
uint32_t& aAlias)
{
// If we're in shutdown, don't create a new instance.
NS_ENSURE_FALSE(sInShutdown, false);
nsDataHashtable<nsStringHashKey, uint32_t>** tableSlot;
if (aAttr == SERVICE) {
tableSlot = &sUUIDServiceTable;
} else if (aAttr == CHARACTERISTIC) {
tableSlot = &sUUIDCharacteristicTable;
} else if (aAttr == DESCRIPTOR) {
tableSlot = &sUUIDDescriptorTable;
}
if (!*tableSlot) {
(*tableSlot) = new nsDataHashtable<nsStringHashKey, uint32_t>;
if (aAttr == SERVICE) {
InitServiceTable();
} else if (aAttr == CHARACTERISTIC) {
InitCharacteristicTable();
} else if (aAttr == DESCRIPTOR) {
InitDescriptorTable();
}
}
return (*tableSlot)->Get(aString, &aAlias);
}
// static
void
BluetoothUUID::GetService(const GlobalObject& aGlobal,
const StringOrUnsignedLong& aName,
nsAString& aReturn, ErrorResult& aRv)
{
ResolveUUIDName(aGlobal, aName, SERVICE, aReturn, aRv);
}
// static
void
BluetoothUUID::GetCharacteristic(const GlobalObject& aGlobal,
const StringOrUnsignedLong& aName,
nsAString& aReturn, ErrorResult& aRv)
{
ResolveUUIDName(aGlobal, aName, CHARACTERISTIC, aReturn, aRv);
}
// static
void
BluetoothUUID::GetDescriptor(const GlobalObject& aGlobal,
const StringOrUnsignedLong& aName,
nsAString& aReturn, ErrorResult& aRv)
{
ResolveUUIDName(aGlobal, aName, DESCRIPTOR, aReturn, aRv);
}
// static
void
BluetoothUUID::CanonicalUUID(const GlobalObject& aGlobal, uint32_t aAlias,
nsAString& aReturn)
{
char uuidStr[37];
// Convert to 128-bit UUID: alias + "-0000-1000-8000-00805f9b34fb".
snprintf(uuidStr, sizeof(uuidStr), "%.8x-0000-1000-8000-00805f9b34fb",
aAlias);
aReturn.AssignLiteral(uuidStr);
}

View File

@ -0,0 +1,126 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_BluetoothUUID_h
#define mozilla_dom_BluetoothUUID_h
#include "mozilla/dom/BluetoothUUIDBinding.h"
#include "mozilla/StaticPtr.h"
#include "nsCOMPtr.h"
#include "nsDataHashtable.h"
#include "nsHashKeys.h"
#include "nsIObserver.h"
#include "nsPIDOMWindow.h"
#include "nsWrapperCache.h"
namespace mozilla {
namespace dom {
class StringOrUnsignedLong;
class BluetoothUUID final : public nsISupports
, public nsWrapperCache
{
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(BluetoothUUID)
nsPIDOMWindowInner* GetParentObject() const
{
return mOwner;
}
virtual JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
/**
* Delete sUUIDServiceTable, sUUIDCharacteristicTable, sUUIDDescriptorTable
* used by ResolveUUIDName(). To be called from nsLayoutStatics only.
*/
static void HandleShutdown();
static void GetService(const GlobalObject& aGlobal,
const StringOrUnsignedLong& aName,
nsAString& aReturn, ErrorResult& aRv);
static void GetCharacteristic(const GlobalObject& aGlobal,
const StringOrUnsignedLong& aName,
nsAString& aReturn, ErrorResult& aRv);
static void GetDescriptor(const GlobalObject& aGlobal,
const StringOrUnsignedLong& aName,
nsAString& aReturn, ErrorResult& aRv);
static void CanonicalUUID(const GlobalObject& aGlobal, uint32_t aAlias,
nsAString& aReturn);
private:
BluetoothUUID(nsPIDOMWindowInner* aOwner);
~BluetoothUUID();
static void InitServiceTable();
static void InitCharacteristicTable();
static void InitDescriptorTable();
enum GattAttribute {
SERVICE,
CHARACTERISTIC,
DESCRIPTOR
};
/**
* Convert an UUID string or 16-bit/32-bit UUID alias to a 128-bit UUID based
* on its bluetooth attribute.
*
* @param aGlobal [in] a Global object for static attributes. We have this
* argument because it needs to call |CanonicalUUID|.
* @param aName [in] an UUID string or 16-bit/32-bit UUID alias.
* @param aAttr [in] a GATT Attribute type.
* @param aReturn [out] a 128-bit UUID.
*/
static void ResolveUUIDName(const GlobalObject& aGlobal,
const StringOrUnsignedLong& aName,
GattAttribute aAttr, nsAString& aReturn,
ErrorResult& aRv);
/**
* Get the GATT attribute table based on the GATT attribute and check whether
* the UUID string can be mapped to a known alias.
*
* @param aAttr [in] a GATT Attribute type.
* @param aString [in] an UUID string.
* @param aAlias [out] a known UUID alias if success.
* @return success if a UUID string can be mapped in table, fail if it
* cannot.
*/
static bool GetTable(GattAttribute aAttr, const nsAString& aString,
uint32_t& aAlias);
/****************************************************************************
* Variables
***************************************************************************/
nsCOMPtr<nsPIDOMWindowInner> mOwner;
static bool sInShutdown;
/**
* Hash Table of services for mapping service names to its UUID's prefix.
*/
static nsDataHashtable<nsStringHashKey, uint32_t>* sUUIDServiceTable;
/**
* Hash Table of characteristics for mapping characteristic names to its UUID's prefix.
*/
static nsDataHashtable<nsStringHashKey, uint32_t>* sUUIDCharacteristicTable;
/**
* Hash Table of descriptors for mapping descriptor names to its UUID's prefix.
*/
static nsDataHashtable<nsStringHashKey, uint32_t>* sUUIDDescriptorTable;
};
} // dom
} // mozilla
#endif // mozilla_dom_BluetoothUUID_h

View File

@ -42,6 +42,7 @@ if CONFIG['MOZ_B2G_BT']:
'common/webapi/BluetoothPairingHandle.cpp',
'common/webapi/BluetoothPairingListener.cpp',
'common/webapi/BluetoothPbapRequestHandle.cpp',
'common/webapi/BluetoothUUID.cpp',
'ipc/BluetoothChild.cpp',
'ipc/BluetoothParent.cpp',
'ipc/BluetoothServiceChildProcess.cpp'
@ -139,6 +140,7 @@ EXPORTS.mozilla.dom.bluetooth.ipc += [
]
EXPORTS.mozilla.dom.bluetooth += [
'common/BluetoothCommon.h',
'common/BluetoothGattUUIDName.h',
'common/BluetoothHashKeys.h',
'common/webapi/BluetoothAdapter.h',
'common/webapi/BluetoothClassOfDevice.h',
@ -158,6 +160,9 @@ EXPORTS.mozilla.dom.bluetooth += [
'common/webapi/BluetoothPairingListener.h',
'common/webapi/BluetoothPbapRequestHandle.h'
]
EXPORTS.mozilla.dom += [
'common/webapi/BluetoothUUID.h'
]
UNIFIED_SOURCES += [
'common/BluetoothCommon.cpp',

View File

@ -139,11 +139,8 @@ CanvasRenderingContextHelper::CreateContext(CanvasContextType aContextType)
Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_USED, 1);
ret = WebGL1Context::Create();
if (!ret) {
Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_SUCCESS, 0);
if (!ret)
return nullptr;
}
Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_SUCCESS, 1);
break;
@ -151,11 +148,8 @@ CanvasRenderingContextHelper::CreateContext(CanvasContextType aContextType)
Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_USED, 1);
ret = WebGL2Context::Create();
if (!ret) {
Telemetry::Accumulate(Telemetry::CANVAS_WEBGL2_SUCCESS, 0);
if (!ret)
return nullptr;
}
Telemetry::Accumulate(Telemetry::CANVAS_WEBGL2_SUCCESS, 1);
break;
@ -204,8 +198,16 @@ CanvasRenderingContextHelper::GetContext(JSContext* aCx,
// See bug 645792 and bug 1215072.
// We want to throw only if dictionary initialization fails,
// so only in case aRv has been set to some error value.
if (contextType == CanvasContextType::WebGL1)
Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_SUCCESS, 0);
else if (contextType == CanvasContextType::WebGL2)
Telemetry::Accumulate(Telemetry::CANVAS_WEBGL2_SUCCESS, 0);
return nullptr;
}
if (contextType == CanvasContextType::WebGL1)
Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_SUCCESS, 1);
else if (contextType == CanvasContextType::WebGL2)
Telemetry::Accumulate(Telemetry::CANVAS_WEBGL2_SUCCESS, 1);
} else {
// We already have a context of some type.
if (contextType != mCurrentContextType)

View File

@ -911,6 +911,10 @@ WebGLContext::InitAndValidateGL()
}
#endif
if (gl->IsSupported(gl::GLFeature::seamless_cube_map_opt_in)) {
gl->fEnable(LOCAL_GL_TEXTURE_CUBE_MAP_SEAMLESS);
}
// Check the shader validator pref
mBypassShaderValidation = gfxPrefs::WebGLBypassShaderValidator();

View File

@ -1,4 +1,5 @@
[DEFAULT]
skip-if = e10s && debug && os == 'win' # Bug 1252677
support-files =
android.json
file_drawImage_document_domain.html
@ -289,7 +290,6 @@ skip-if = (e10s && debug && os == 'win')
[test_offscreencanvas_toblob.html]
tags = offscreencanvas
[test_offscreencanvas_toimagebitmap.html]
skip-if = (e10s && debug && os == 'win')
tags = offscreencanvas
[test_offscreencanvas_basic_webgl.html]
tags = offscreencanvas

View File

@ -87,7 +87,7 @@ skip-if = buildapp == 'b2g' || toolkit == 'android' # b2g(1 failure out of 615,
[test_bug605242.html]
skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM
[test_bug607464.html]
skip-if = buildapp == 'b2g' || toolkit == 'android' || (e10s && os == 'win') #CRASH_DUMP, RANDOM
skip-if = buildapp == 'b2g' || toolkit == 'android' || (e10s && os == 'win') || (e10s && os == "mac") #CRASH_DUMP, RANDOM, bug 1252273
[test_bug613634.html]
skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM
[test_bug615597.html]
@ -133,7 +133,7 @@ skip-if = buildapp == 'b2g' # b2g(failing when the test gets moved around, and o
[test_bug944011.html]
[test_bug944847.html]
[test_bug946632.html]
skip-if = buildapp == 'b2g'
skip-if = buildapp == 'b2g' || (e10s && os == "mac") # bug 1252273
[test_bug967796.html]
skip-if = toolkit == "gonk" || e10s
[test_bug985988.html]

View File

@ -23,6 +23,7 @@
/** Tests for Bug 545812 **/
SimpleTest.requestFlakyTimeout("untriaged");
SimpleTest.expectAssertions(0, 1);
// Run the tests which go full-screen in new windows, as mochitests normally
// run in an iframe, which by default will not have the allowfullscreen

View File

@ -201,3 +201,7 @@ ManifestInvalidCSSColor=%1$S: %2$S is not a valid CSS color.
PatternAttributeCompileFailure=Unable to check <input pattern='%S'> because the pattern is not a valid regexp: %S
# LOCALIZATION NOTE: Do not translate "postMessage" or DOMWindow. %S values are origins, like https://domain.com:port
TargetPrincipalDoesNotMatch=Failed to execute 'postMessage' on 'DOMWindow': The target origin provided ('%S') does not match the recipient window's origin ('%S').
# LOCALIZATION NOTE: Do not translate 'youtube'. %S values are origins, like https://domain.com:port
RewriteYoutubeEmbed=Rewriting old-style Youtube Flash embed (%S) to iframe embed (%S). Please update page to use iframe instead of embed/object, if possible.
# LOCALIZATION NOTE: Do not translate 'youtube'. %S values are origins, like https://domain.com:port
RewriteYoutubeEmbedInvalidQuery=Rewriting old-style Youtube Flash embed (%S) to iframe embed (%S). Query was invalid and removed from URL. Please update page to use iframe instead of embed/object, if possible.

View File

@ -492,8 +492,7 @@ MediaDecoderStateMachine::NeedToDecodeVideo()
HaveEnoughDecodedVideo());
return IsVideoDecoding() &&
((mState == DECODER_STATE_SEEKING && mDecodeToSeekTarget) ||
(IsDecodingFirstFrame() &&
IsVideoDecoding() && VideoQueue().GetSize() == 0) ||
(IsDecodingFirstFrame() && VideoQueue().GetSize() == 0) ||
(!mMinimizePreroll && !HaveEnoughDecodedVideo()));
}
@ -564,11 +563,10 @@ MediaDecoderStateMachine::NeedToDecodeAudio()
return IsAudioDecoding() &&
((mState == DECODER_STATE_SEEKING && mDecodeToSeekTarget) ||
(IsDecodingFirstFrame() &&
IsAudioDecoding() && AudioQueue().GetSize() == 0) ||
(IsDecodingFirstFrame() && AudioQueue().GetSize() == 0) ||
(!mMinimizePreroll &&
!HaveEnoughDecodedAudio(mAmpleAudioThresholdUsecs * mPlaybackRate) &&
(mState != DECODER_STATE_SEEKING || mDecodeToSeekTarget)));
!HaveEnoughDecodedAudio(mAmpleAudioThresholdUsecs * mPlaybackRate) &&
(mState != DECODER_STATE_SEEKING || mDecodeToSeekTarget)));
}
bool

View File

@ -1103,7 +1103,7 @@ static auto& MediaManager_AnonymizeDevices = MediaManager::AnonymizeDevices;
already_AddRefed<MediaManager::PledgeChar>
MediaManager::SelectSettings(
MediaStreamConstraints& aConstraints,
RefPtr<Refcountable<ScopedDeletePtr<SourceSet>>>& aSources)
RefPtr<Refcountable<UniquePtr<SourceSet>>>& aSources)
{
MOZ_ASSERT(NS_IsMainThread());
RefPtr<PledgeChar> p = new PledgeChar();
@ -1414,7 +1414,7 @@ MediaManager::EnumerateRawDevices(uint64_t aWindowId,
realBackend = manager->GetBackend(aWindowId);
}
ScopedDeletePtr<SourceSet> result(new SourceSet);
auto result = MakeUnique<SourceSet>();
if (hasVideo) {
nsTArray<RefPtr<VideoDevice>> videos;
@ -1432,16 +1432,16 @@ MediaManager::EnumerateRawDevices(uint64_t aWindowId,
result->AppendElement(source);
}
}
SourceSet* handoff = result.forget();
SourceSet* handoff = result.release();
NS_DispatchToMainThread(do_AddRef(NewRunnableFrom([id, handoff]() mutable {
ScopedDeletePtr<SourceSet> result(handoff); // grab result
UniquePtr<SourceSet> result(handoff); // grab result
RefPtr<MediaManager> mgr = MediaManager_GetInstance();
if (!mgr) {
return NS_OK;
}
RefPtr<PledgeSourceSet> p = mgr->mOutstandingPledges.Remove(id);
if (p) {
p->Resolve(result.forget());
p->Resolve(result.release());
}
return NS_OK;
})));
@ -1609,9 +1609,9 @@ media::Parent<media::NonE10s>*
MediaManager::GetNonE10sParent()
{
if (!mNonE10sParent) {
mNonE10sParent = new media::Parent<media::NonE10s>(true);
mNonE10sParent = MakeUnique<media::Parent<media::NonE10s>>(true);
}
return mNonE10sParent;
return mNonE10sParent.get();
}
/* static */ void
@ -2115,8 +2115,8 @@ MediaManager::GetUserMedia(nsPIDOMWindowInner* aWindow,
p->Then([this, onSuccess, onFailure, windowID, c, listener, askPermission,
prefs, isHTTPS, callID, origin](SourceSet*& aDevices) mutable {
RefPtr<Refcountable<ScopedDeletePtr<SourceSet>>> devices(
new Refcountable<ScopedDeletePtr<SourceSet>>(aDevices)); // grab result
RefPtr<Refcountable<UniquePtr<SourceSet>>> devices(
new Refcountable<UniquePtr<SourceSet>>(aDevices)); // grab result
// Ensure that the captured 'this' pointer and our windowID are still good.
if (!MediaManager::Exists() ||
@ -2176,7 +2176,7 @@ MediaManager::GetUserMedia(nsPIDOMWindowInner* aWindow,
onFailure.forget(),
windowID, listener,
prefs, origin,
devices->forget()));
devices->release()));
// Store the task w/callbacks.
mActiveCallbacks.Put(callID, task.forget());
@ -2335,7 +2335,7 @@ MediaManager::EnumerateDevicesImpl(uint64_t aWindowId,
aVideoType, aAudioType,
aFake, aFakeTracks);
p->Then([id, aWindowId, aOriginKey](SourceSet*& aDevices) mutable {
ScopedDeletePtr<SourceSet> devices(aDevices); // secondary result
UniquePtr<SourceSet> devices(aDevices); // secondary result
// Only run if window is still on our active list.
RefPtr<MediaManager> mgr = MediaManager_GetInstance();
@ -2347,7 +2347,7 @@ MediaManager::EnumerateDevicesImpl(uint64_t aWindowId,
return NS_OK;
}
MediaManager_AnonymizeDevices(*devices, aOriginKey);
p->Resolve(devices.forget());
p->Resolve(devices.release());
return NS_OK;
});
});
@ -2381,7 +2381,7 @@ MediaManager::EnumerateDevices(nsPIDOMWindowInner* aWindow,
MediaSourceEnum::Microphone,
fake);
p->Then([onSuccess, windowId, listener](SourceSet*& aDevices) mutable {
ScopedDeletePtr<SourceSet> devices(aDevices); // grab result
UniquePtr<SourceSet> devices(aDevices); // grab result
RefPtr<MediaManager> mgr = MediaManager_GetInstance();
mgr->RemoveFromWindowList(windowId, listener);
nsCOMPtr<nsIWritableVariant> array = MediaManager_ToJSArray(*devices);

View File

@ -30,6 +30,7 @@
#include "mozilla/media/MediaChild.h"
#include "mozilla/media/MediaParent.h"
#include "mozilla/Logging.h"
#include "mozilla/UniquePtr.h"
#include "DOMMediaStream.h"
#ifdef MOZ_WEBRTC
@ -501,7 +502,7 @@ private:
already_AddRefed<PledgeChar>
SelectSettings(
dom::MediaStreamConstraints& aConstraints,
RefPtr<media::Refcountable<ScopedDeletePtr<SourceSet>>>& aSources);
RefPtr<media::Refcountable<UniquePtr<SourceSet>>>& aSources);
StreamListeners* AddWindowID(uint64_t aWindowId);
WindowTable *GetActiveWindows() {
@ -550,7 +551,7 @@ private:
#endif
public:
media::CoatCheck<media::Pledge<nsCString>> mGetOriginKeyPledges;
ScopedDeletePtr<media::Parent<media::NonE10s>> mNonE10sParent;
UniquePtr<media::Parent<media::NonE10s>> mNonE10sParent;
};
} // namespace mozilla

View File

@ -8,6 +8,7 @@
#include "gfx2DGlue.h"
#include "ImageContainer.h"
#include "Layers.h"
#include "mozilla/UniquePtr.h"
namespace mozilla {
@ -52,18 +53,18 @@ VideoFrame::CreateBlackImage(const gfx::IntSize& aSize)
int len = ((aSize.width * aSize.height) * 3 / 2);
// Generate a black image.
ScopedDeletePtr<uint8_t> frame(new uint8_t[len]);
auto frame = MakeUnique<uint8_t[]>(len);
int y = aSize.width * aSize.height;
// Fill Y plane.
memset(frame.rwget(), 0x10, y);
memset(frame.get(), 0x10, y);
// Fill Cb/Cr planes.
memset(frame.rwget() + y, 0x80, (len - y));
memset(frame.get() + y, 0x80, (len - y));
const uint8_t lumaBpp = 8;
const uint8_t chromaBpp = 4;
layers::PlanarYCbCrData data;
data.mYChannel = frame.rwget();
data.mYChannel = frame.get();
data.mYSize = gfx::IntSize(aSize.width, aSize.height);
data.mYStride = (int32_t) (aSize.width * lumaBpp / 8.0);
data.mCbCrStride = (int32_t) (aSize.width * chromaBpp / 8.0);

View File

@ -46,7 +46,7 @@ SanitizeOriginKeys(const uint64_t& aSinceWhen, bool aOnlyPrivateBrowsing)
if (XRE_GetProcessType() == GeckoProcessType_Default) {
// Avoid opening MediaManager in this case, since this is called by
// sanitize.js when cookies are cleared, which can happen on startup.
ScopedDeletePtr<Parent<NonE10s>> tmpParent(new Parent<NonE10s>(true));
auto tmpParent = MakeUnique<Parent<NonE10s>>(true);
tmpParent->RecvSanitizeOriginKeys(aSinceWhen, aOnlyPrivateBrowsing);
} else {
Child::Get()->SendSanitizeOriginKeys(aSinceWhen, aOnlyPrivateBrowsing);

View File

@ -10,6 +10,7 @@
#include "nsAutoPtr.h"
#include "nsThreadUtils.h"
#include "nsIAsyncShutdown.h"
#include "mozilla/UniquePtr.h"
#include "base/task.h"
namespace mozilla {
@ -96,8 +97,8 @@ public:
OnSuccessType mOnSuccess;
OnFailureType mOnFailure;
};
mFunctors = new Functors(Forward<OnSuccessType>(aOnSuccess),
Forward<OnFailureType>(aOnFailure));
mFunctors = MakeUnique<Functors>(Forward<OnSuccessType>(aOnSuccess),
Forward<OnFailureType>(aOnFailure));
if (mDone) {
if (!mRejected) {
mFunctors->Succeed(mValue);
@ -142,7 +143,7 @@ private:
bool mDone;
bool mRejected;
ErrorType mError;
ScopedDeletePtr<FunctorsBase> mFunctors;
UniquePtr<FunctorsBase> mFunctors;
};
/* media::NewRunnableFrom() - Create an nsRunnable from a lambda.
@ -337,7 +338,7 @@ private:
* (or owning smart-pointers to such objects) refcountable.
*
* Technical limitation: A template specialization is needed for types that take
* a constructor. Please add below (ScopedDeletePtr covers a lot of ground though).
* a constructor. Please add below (UniquePtr covers a lot of ground though).
*/
template<typename T>
@ -350,13 +351,13 @@ private:
};
template<typename T>
class Refcountable<ScopedDeletePtr<T>> : public ScopedDeletePtr<T>
class Refcountable<UniquePtr<T>> : public UniquePtr<T>
{
public:
explicit Refcountable<ScopedDeletePtr<T>>(T* aPtr) : ScopedDeletePtr<T>(aPtr) {}
explicit Refcountable<UniquePtr<T>>(T* aPtr) : UniquePtr<T>(aPtr) {}
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Refcountable<T>)
private:
~Refcountable<ScopedDeletePtr<T>>() {}
~Refcountable<UniquePtr<T>>() {}
};
/* media::ShutdownBlocker - Async shutdown helper.

View File

@ -856,6 +856,7 @@ skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_VideoPlaybackQuality.html]
[test_VideoPlaybackQuality_disabled.html]
[test_volume.html]
skip-if = e10s && debug && os == 'win' # bug 1245574
[test_vttparser.html]
skip-if = e10s && debug && os == 'win'
[test_webvtt_disabled.html]

View File

@ -1,6 +1,6 @@
[DEFAULT]
tags=msg
skip-if = buildapp == 'b2g' # Bug 1191270, bug 1037287, bug 967606, bug 1096400, etc
skip-if = buildapp == 'b2g' || (e10s && debug && os == 'win') # Bug 1191270, bug 1037287, bug 967606, bug 1096400, bug 1238542 etc
support-files =
head.js
hello.ogg

View File

@ -321,4 +321,17 @@ PluginPRLibrary::EndUpdateBackground(NPP instance, const nsIntRect&)
return NS_ERROR_NOT_AVAILABLE;
}
#if defined(XP_WIN)
nsresult
PluginPRLibrary::GetScrollCaptureContainer(NPP aInstance, ImageContainer** aContainer)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
nsresult
PluginPRLibrary::UpdateScrollState(NPP aInstance, bool aIsScrolling)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
#endif
} // namespace mozilla

View File

@ -125,6 +125,10 @@ public:
virtual void GetLibraryPath(nsACString& aPath) { aPath.Assign(mFilePath); }
virtual nsresult GetRunID(uint32_t* aRunID) override { return NS_ERROR_NOT_IMPLEMENTED; }
virtual void SetHasLocalInstance() override { }
#if defined(XP_WIN)
virtual nsresult GetScrollCaptureContainer(NPP aInstance, mozilla::layers::ImageContainer** aContainer) override;
virtual nsresult UpdateScrollState(NPP aInstance, bool aIsScrolling) override;
#endif
private:
NP_InitializeFunc mNP_Initialize;

View File

@ -1210,6 +1210,29 @@ nsNPAPIPluginInstance::GetImageSize(nsIntSize* aSize)
return !library ? NS_ERROR_FAILURE : library->GetImageSize(&mNPP, aSize);
}
#if defined(XP_WIN)
nsresult
nsNPAPIPluginInstance::GetScrollCaptureContainer(ImageContainer**aContainer)
{
*aContainer = nullptr;
if (RUNNING != mRunning)
return NS_OK;
AutoPluginLibraryCall library(this);
return !library ? NS_ERROR_FAILURE : library->GetScrollCaptureContainer(&mNPP, aContainer);
}
nsresult
nsNPAPIPluginInstance::UpdateScrollState(bool aIsScrolling)
{
if (RUNNING != mRunning)
return NS_OK;
AutoPluginLibraryCall library(this);
return !library ? NS_ERROR_FAILURE : library->UpdateScrollState(&mNPP, aIsScrolling);
}
#endif
void
nsNPAPIPluginInstance::DidComposite()
{

View File

@ -121,6 +121,10 @@ public:
nsresult InvalidateRegion(NPRegion invalidRegion);
nsresult GetMIMEType(const char* *result);
nsresult GetJSContext(JSContext* *outContext);
#if defined(XP_WIN)
nsresult GetScrollCaptureContainer(mozilla::layers::ImageContainer **aContainer);
nsresult UpdateScrollState(bool aIsScrolling);
#endif
nsPluginInstanceOwner* GetOwner();
void SetOwner(nsPluginInstanceOwner *aOwner);
void DidComposite();

View File

@ -212,6 +212,21 @@ AttachToContainerAsSurfaceTexture(ImageContainer* container,
}
#endif
bool
nsPluginInstanceOwner::NeedsScrollImageLayer()
{
#if defined(XP_WIN)
// If this is a windowed plugin and we're doing layout in the content
// process, force the creation of an image layer for the plugin. We'll
// paint to this when scrolling.
return XRE_IsContentProcess() &&
mPluginWindow &&
mPluginWindow->type == NPWindowTypeWindow;
#else
return false;
#endif
}
already_AddRefed<ImageContainer>
nsPluginInstanceOwner::GetImageContainer()
{
@ -247,7 +262,15 @@ nsPluginInstanceOwner::GetImageContainer()
container->SetCurrentImageInTransaction(img);
}
#else
mInstance->GetImageContainer(getter_AddRefs(container));
if (NeedsScrollImageLayer()) {
// windowed plugin under e10s
#if defined(XP_WIN)
mInstance->GetScrollCaptureContainer(getter_AddRefs(container));
#endif
} else {
// async windowless rendering
mInstance->GetImageContainer(getter_AddRefs(container));
}
#endif
return container.forget();
@ -327,6 +350,21 @@ nsPluginInstanceOwner::GetCurrentImageSize()
return size;
}
bool
nsPluginInstanceOwner::UpdateScrollState(bool aIsScrolling)
{
#if defined(XP_WIN)
if (!mInstance) {
return false;
}
mScrollState = aIsScrolling;
nsresult rv = mInstance->UpdateScrollState(aIsScrolling);
return NS_SUCCEEDED(rv);
#else
return false;
#endif
}
nsPluginInstanceOwner::nsPluginInstanceOwner()
{
// create nsPluginNativeWindow object, it is derived from NPWindow
@ -374,6 +412,7 @@ nsPluginInstanceOwner::nsPluginInstanceOwner()
mGotCompositionData = false;
mSentStartComposition = false;
mPluginDidNotHandleIMEComposition = false;
mScrollState = false;
#endif
}
@ -613,14 +652,18 @@ NS_IMETHODIMP nsPluginInstanceOwner::InvalidateRect(NPRect *invalidRect)
#endif
#ifndef XP_MACOSX
// Windowed plugins should not be calling NPN_InvalidateRect, but
// Silverlight does and expects it to "work"
// Silverlight calls invalidate for windowed plugins so this needs to work.
if (mWidget) {
mWidget->Invalidate(
LayoutDeviceIntRect(invalidRect->left, invalidRect->top,
invalidRect->right - invalidRect->left,
invalidRect->bottom - invalidRect->top));
return NS_OK;
// Plugin instances also call invalidate when plugin windows are hidden
// during scrolling. In this case fall through so we invalidate the
// underlying layer.
if (!NeedsScrollImageLayer()) {
return NS_OK;
}
}
#endif
nsIntRect rect(invalidRect->left,

View File

@ -228,6 +228,11 @@ public:
// Returns the image container that has our currently displayed image.
already_AddRefed<mozilla::layers::ImageContainer> GetImageContainer();
// Returns true if this is windowed plugin that can return static captures
// for scroll operations.
bool NeedsScrollImageLayer();
// Notification we receive from nsPluginFrame about scroll state.
bool UpdateScrollState(bool aIsScrolling);
void DidComposite();
@ -397,6 +402,9 @@ private:
#endif
bool mWaitingForPaint;
#if defined(XP_WIN)
bool mScrollState;
#endif
};
#endif // nsPluginInstanceOwner_h_

View File

@ -60,6 +60,7 @@
#include "nsIWidget.h"
#include "nsPluginNativeWindow.h"
#include "PluginQuirks.h"
#include "nsWindowsHelpers.h"
extern const wchar_t* kFlashFullscreenClass;
#elif defined(MOZ_WIDGET_GTK)
#include "mozilla/dom/ContentChild.h"
@ -72,6 +73,13 @@ using namespace mozilla::plugins;
using namespace mozilla::layers;
using namespace mozilla::gl;
#if defined(XP_WIN)
// Delays associated with attempting an e10s window capture for scrolling.
const int kScrollCaptureDelayMs = 100;
const int kInitScrollCaptureDelayMs = 1000;
const uint32_t kScrollCaptureFillColor = 0xFFa0a0a0; // gray
#endif
void
StreamNotifyParent::ActorDestroy(ActorDestroyReason aWhy)
{
@ -109,6 +117,13 @@ PluginInstanceParent::LookupPluginInstanceByID(uintptr_t aId)
}
#endif
template<>
struct RunnableMethodTraits<PluginInstanceParent>
{
static void RetainCallee(PluginInstanceParent* obj) { }
static void ReleaseCallee(PluginInstanceParent* obj) { }
};
PluginInstanceParent::PluginInstanceParent(PluginModuleParent* parent,
NPP npp,
const nsCString& aMimeType,
@ -134,6 +149,11 @@ PluginInstanceParent::PluginInstanceParent(PluginModuleParent* parent,
, mShHeight(0)
, mShColorSpace(nullptr)
#endif
#if defined(XP_WIN)
, mCaptureRefreshTask(nullptr)
, mValidFirstCapture(false)
, mIsScrolling(false)
#endif
{
#if defined(OS_WIN)
if (!sPluginInstanceList) {
@ -158,6 +178,9 @@ PluginInstanceParent::~PluginInstanceParent()
if (mShColorSpace)
::CGColorSpaceRelease(mShColorSpace);
#endif
#if defined(XP_WIN)
CancelScheduledScrollCapture();
#endif
}
bool
@ -435,6 +458,12 @@ PluginInstanceParent::AnswerNPN_SetValue_NPPVpluginWindow(
// non-pointer-sized integer.
*result = mNPNIface->setvalue(mNPP, NPPVpluginWindowBool,
(void*)(intptr_t)windowed);
#if defined(XP_WIN)
if (windowed) {
ScheduleScrollCapture(kScrollCaptureDelayMs);
}
#endif
return true;
}
@ -1182,6 +1211,203 @@ PluginInstanceParent::EndUpdateBackground(const nsIntRect& aRect)
return NS_OK;
}
#if defined(XP_WIN)
//#define CAPTURE_LOG(...) printf_stderr("CAPTURE [%X]: ", this);printf_stderr(__VA_ARGS__);printf_stderr("\n");
#define CAPTURE_LOG(...)
void
PluginInstanceParent::ScheduleScrollCapture(int aTimeout)
{
if (mCaptureRefreshTask) {
return;
}
CAPTURE_LOG("delayed scroll capture requested.");
mCaptureRefreshTask =
NewRunnableMethod(this, &PluginInstanceParent::ScheduledUpdateScrollCaptureCallback);
MessageLoop::current()->PostDelayedTask(FROM_HERE, mCaptureRefreshTask,
kScrollCaptureDelayMs);
}
void
PluginInstanceParent::ScheduledUpdateScrollCaptureCallback()
{
CAPTURE_LOG("taking delayed scrollcapture.");
mCaptureRefreshTask = nullptr;
bool retrigger = false;
UpdateScrollCapture(retrigger);
if (retrigger) {
// reset the async request
ScheduleScrollCapture(kScrollCaptureDelayMs);
}
}
void
PluginInstanceParent::CancelScheduledScrollCapture()
{
CAPTURE_LOG("delayed scroll capture cancelled.");
if (mCaptureRefreshTask) {
mCaptureRefreshTask->Cancel();
mCaptureRefreshTask = nullptr;
}
}
bool
PluginInstanceParent::UpdateScrollCapture(bool& aRequestNewCapture)
{
aRequestNewCapture = false;
if (!::IsWindow(mChildPluginHWND)) {
CAPTURE_LOG("invalid window");
aRequestNewCapture = true;
return false;
}
nsAutoHDC windowDC(::GetDC(mChildPluginHWND));
if (!windowDC) {
CAPTURE_LOG("no windowdc");
aRequestNewCapture = true;
return false;
}
RECT bounds = {0};
::GetWindowRect(mChildPluginHWND, &bounds);
if ((bounds.left == bounds.right && bounds.top == bounds.bottom) ||
(!mWindowSize.width && !mWindowSize.height)) {
CAPTURE_LOG("empty bounds");
// Lots of null window plugins in content, don't capture.
return false;
}
// If we need to init mScrollCapture do so, also reset it if the size of the
// plugin window changes.
if (!mScrollCapture || mScrollCapture->GetSize() != mWindowSize) {
mValidFirstCapture = false;
mScrollCapture =
gfxPlatform::GetPlatform()->CreateOffscreenSurface(mWindowSize,
SurfaceFormat::X8R8G8B8_UINT32);
}
// Check clipping, we don't want to capture windows that are clipped by
// the viewport.
RECT clip = {0};
int rgnType = ::GetWindowRgnBox(mPluginHWND, &clip);
bool clipCorrect = !clip.left && !clip.top &&
clip.right == mWindowSize.width &&
clip.bottom == mWindowSize.height;
bool isVisible = ::IsWindowVisible(mChildPluginHWND);
CAPTURE_LOG("validcap=%d visible=%d region=%d clip=%d:%dx%dx%dx%d",
mValidFirstCapture, isVisible, rgnType, clipCorrect
clip.left, clip.top, clip.right, clip.bottom);
// We have a good capture and can't update so keep using the existing
// capture image. Otherwise fall through so we paint the fill color to
// the layer.
if (mValidFirstCapture && (!isVisible || !clipCorrect)) {
return true;
}
// On Windows we'll need a native bitmap for BitBlt.
RefPtr<gfxWindowsSurface> nativeScrollCapture;
// Copy the plugin window if it's visible and there's no clipping, otherwise
// use a default fill color.
if (isVisible && clipCorrect) {
CAPTURE_LOG("capturing window");
nativeScrollCapture =
new gfxWindowsSurface(mWindowSize, SurfaceFormat::X8R8G8B8_UINT32);
if (!::BitBlt(nativeScrollCapture->GetDC(), 0, 0, mWindowSize.width,
mWindowSize.height, windowDC, 0, 0, SRCCOPY)) {
CAPTURE_LOG("blt failure??");
return false;
}
::GdiFlush();
mValidFirstCapture = true;
}
IntSize targetSize = mScrollCapture->GetSize();
RefPtr<gfx::DrawTarget> dt =
gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(mScrollCapture,
targetSize);
if (nativeScrollCapture) {
// Copy the native capture image over to a remotable gfx surface.
RefPtr<gfx::SourceSurface> sourceSurface =
gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(nullptr,
nativeScrollCapture);
dt->CopySurface(sourceSurface,
IntRect(0, 0, targetSize.width, targetSize.height),
IntPoint());
} else {
CAPTURE_LOG("using fill color");
dt->FillRect(gfx::Rect(0, 0, targetSize.width, targetSize.height),
gfx::ColorPattern(gfx::Color::FromABGR(kScrollCaptureFillColor)),
gfx::DrawOptions(1.f, CompositionOp::OP_SOURCE));
aRequestNewCapture = true;
}
dt->Flush();
// Get a source for mScrollCapture and load it into the image container.
RefPtr<gfx::SourceSurface> cachedSource =
gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(dt,
mScrollCapture);
RefPtr<SourceSurfaceImage> image =
new SourceSurfaceImage(cachedSource->GetSize(), cachedSource);
ImageContainer::NonOwningImage holder(image);
holder.mFrameID = ++mFrameID;
AutoTArray<ImageContainer::NonOwningImage,1> imageList;
imageList.AppendElement(holder);
// inits mImageContainer
ImageContainer *container = GetImageContainer();
container->SetCurrentImages(imageList);
// Invalidate our area in the page so the image gets flushed.
NPRect nprect = {0, 0, targetSize.width, targetSize.height};
RecvNPN_InvalidateRect(nprect);
return true;
}
nsresult
PluginInstanceParent::GetScrollCaptureContainer(ImageContainer** aContainer)
{
if (!aContainer || !::IsWindow(mPluginHWND)) {
return NS_ERROR_FAILURE;
}
if (!mImageContainer) {
ScheduleScrollCapture(kInitScrollCaptureDelayMs);
return NS_ERROR_FAILURE;
}
ImageContainer *container = GetImageContainer();
NS_IF_ADDREF(container);
*aContainer = container;
return NS_OK;
}
nsresult
PluginInstanceParent::UpdateScrollState(bool aIsScrolling)
{
bool scrollStateChanged = (mIsScrolling != aIsScrolling);
mIsScrolling = aIsScrolling;
if (scrollStateChanged && !aIsScrolling) {
// At the end of a dom scroll operation capturing now will attempt to
// capture a window that is still hidden due to the current scroll
// operation. (The browser process will update visibility after layer
// updates get pushed over.) So we delay our attempt for a bit. This
// shouldn't hurt our chances of capturing with APZ scroll since the
// delay is short.
ScheduleScrollCapture(kScrollCaptureDelayMs);
}
return NS_OK;
}
#endif // XP_WIN
PluginAsyncSurrogate*
PluginInstanceParent::GetAsyncSurrogate()
{
@ -1334,6 +1560,9 @@ PluginInstanceParent::NPP_SetWindow(const NPWindow* aWindow)
window.type = aWindow->type;
#endif
mWindowSize.width = window.width;
mWindowSize.height = window.height;
#if defined(XP_MACOSX)
double floatScaleFactor = 1.0;
mNPNIface->getvalue(mNPP, NPNVcontentsScaleFactor, &floatScaleFactor);
@ -1378,6 +1607,12 @@ PluginInstanceParent::NPP_SetWindow(const NPWindow* aWindow)
}
RecordDrawingModel();
#if defined(XP_WIN)
if (!mCaptureRefreshTask) {
ScheduleScrollCapture(kScrollCaptureDelayMs);
}
#endif
return NPERR_NO_ERROR;
}

View File

@ -330,6 +330,10 @@ public:
nsresult BeginUpdateBackground(const nsIntRect& aRect,
DrawTarget** aDrawTarget);
nsresult EndUpdateBackground(const nsIntRect& aRect);
#if defined(XP_WIN)
nsresult GetScrollCaptureContainer(mozilla::layers::ImageContainer** aContainer);
nsresult UpdateScrollState(bool aIsScrolling);
#endif
void DidComposite();
bool IsUsingDirectDrawing();
@ -388,6 +392,7 @@ private:
nsCString mSrcAttribute;
NPWindowType mWindowType;
int16_t mDrawingModel;
IntSize mWindowSize;
// Since plugins may request different drawing models to find a compatible
// one, we only record the drawing model after a SetWindow call and if the
@ -452,6 +457,18 @@ private:
RefPtr<gfxASurface> mBackground;
RefPtr<ImageContainer> mImageContainer;
#if defined(XP_WIN)
void ScheduleScrollCapture(int aTimeout);
void ScheduledUpdateScrollCaptureCallback();
bool UpdateScrollCapture(bool& aRequestNewCapture);
void CancelScheduledScrollCapture();
RefPtr<gfxASurface> mScrollCapture;
CancelableTask* mCaptureRefreshTask;
bool mValidFirstCapture;
bool mIsScrolling;
#endif
};

View File

@ -87,6 +87,10 @@ public:
virtual nsresult IsRemoteDrawingCoreAnimation(NPP instance, bool *aDrawing) = 0;
virtual nsresult ContentsScaleFactorChanged(NPP instance, double aContentsScaleFactor) = 0;
#endif
#if defined(XP_WIN)
virtual nsresult GetScrollCaptureContainer(NPP aInstance, mozilla::layers::ImageContainer** aContainer) = 0;
virtual nsresult UpdateScrollState(NPP aInstance, bool aIsScrolling) = 0;
#endif
/**
* The next three methods are the third leg in the trip to

View File

@ -1982,6 +1982,22 @@ PluginModuleParent::EndUpdateBackground(NPP instance, const nsIntRect& aRect)
return i->EndUpdateBackground(aRect);
}
#if defined(XP_WIN)
nsresult
PluginModuleParent::GetScrollCaptureContainer(NPP aInstance,
mozilla::layers::ImageContainer** aContainer)
{
PluginInstanceParent* inst = PluginInstanceParent::Cast(aInstance);
return !inst ? NS_ERROR_FAILURE : inst->GetScrollCaptureContainer(aContainer);
}
nsresult
PluginModuleParent::UpdateScrollState(NPP aInstance, bool aIsScrolling)
{
PluginInstanceParent* inst = PluginInstanceParent::Cast(aInstance);
return !inst ? NS_ERROR_FAILURE : inst->UpdateScrollState(aIsScrolling);
}
#endif
void
PluginModuleParent::OnInitFailure()
{

View File

@ -259,6 +259,11 @@ protected:
virtual nsresult EndUpdateBackground(NPP instance,
const nsIntRect& aRect) override;
#if defined(XP_WIN)
virtual nsresult GetScrollCaptureContainer(NPP aInstance, mozilla::layers::ImageContainer** aContainer) override;
virtual nsresult UpdateScrollState(NPP aInstance, bool aIsScrolling);
#endif
#if defined(XP_UNIX) && !defined(XP_MACOSX) && !defined(MOZ_WIDGET_GONK)
virtual nsresult NP_Initialize(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs, NPError* error) override;
#else

View File

@ -90,6 +90,7 @@ skip-if = release_build # Bug 1172627
[test_object.html]
skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' # b2g(needs plugin support) b2g-debug(needs plugin support) b2g-desktop(needs plugin support)
[test_painting.html]
skip-if = (toolkit == "cocoa" && e10s) # bug 1252230
[test_plugin_scroll_painting.html]
skip-if = true # Bug 596491
[test_pluginstream_asfile.html]

View File

@ -6,6 +6,7 @@
<body>
<script class="testbody" type="application/javascript">
SimpleTest.waitForExplicitFinish();
SimpleTest.expectAssertions(0, 1);
setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED);
window.frameLoaded = function frameLoaded_toCrash() {

View File

@ -10,7 +10,7 @@
<body onload="begin()">
<script type="application/javascript;version=1.8">
SimpleTest.waitForExplicitFinish();
SimpleTest.expectAssertions(0, 3);
SimpleTest.expectAssertions(0, 4);
setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED);
const MAX_CHECK_PLUGIN_STOPPED_ATTEMPTS = 50;

View File

@ -7,6 +7,7 @@
<body onload="runTests()">
<script class="testbody" type="application/javascript">
SimpleTest.waitForExplicitFinish();
SimpleTest.expectAssertions(0, 1);
setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED);
var p = null;

View File

@ -9,6 +9,7 @@
<body onload="startTest()">
<script type="application/javascript;version=1.8">
SimpleTest.waitForExplicitFinish();
SimpleTest.expectAssertions(0, 2);
setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED);
var p = null;

View File

@ -229,7 +229,8 @@ DoContentSecurityChecks(nsIURI* aURI, nsILoadInfo* aLoadInfo)
}
case nsIContentPolicy::TYPE_FONT: {
MOZ_ASSERT(false, "contentPolicyType not supported yet");
mimeTypeGuess = EmptyCString();
requestingContext = aLoadInfo->LoadingNode();
break;
}
@ -475,6 +476,13 @@ nsContentSecurityManager::CheckChannel(nsIChannel* aChannel)
return NS_OK;
}
// Allow the load if TriggeringPrincipal is the SystemPrincipal which
// is e.g. necessary to allow user user stylesheets to load XBL from
// external files.
if (nsContentUtils::IsSystemPrincipal(loadInfo->TriggeringPrincipal())) {
return NS_OK;
}
// if none of the REQUIRE_SAME_ORIGIN flags are set, then SOP does not apply
if ((securityMode == nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS) ||
(securityMode == nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED)) {

View File

@ -24,7 +24,7 @@
worker.onerror = function(error) {
var msg = error.message;
if (msg.match(/^: NetworkError/) || msg.match(/Failed to load worker script/)) {
if (msg.match(/^NetworkError/) || msg.match(/Failed to load worker script/)) {
// this means CSP blocked it
msg = "blocked";
}

View File

@ -0,0 +1,58 @@
// custom *.sjs for Bug 1195172
// CSP: 'block-all-mixed-content'
const PRE_HEAD =
"<!DOCTYPE HTML>" +
"<html><head><meta charset=\"utf-8\">" +
"<title>Bug 1195172 - CSP should block font from cache</title>";
const CSP_BLOCK =
"<meta http-equiv=\"Content-Security-Policy\" content=\"font-src 'none'\">";
const CSP_ALLOW =
"<meta http-equiv=\"Content-Security-Policy\" content=\"font-src *\">";
const CSS =
"<style>" +
" @font-face {" +
" font-family: myFontTest;" +
" src: url(file_fontloader.woff);" +
" }" +
" div {" +
" font-family: myFontTest;" +
" }" +
"</style>";
const POST_HEAD_AND_BODY =
"</head>" +
"<body>" +
"<div> Just testing the font </div>" +
"</body>" +
"</html>";
function handleRequest(request, response)
{
// avoid confusing cache behaviors
response.setHeader("Cache-Control", "no-cache", false);
var queryString = request.queryString;
if (queryString == "baseline") {
response.write(PRE_HEAD + POST_HEAD_AND_BODY);
return;
}
if (queryString == "no-csp") {
response.write(PRE_HEAD + CSS + POST_HEAD_AND_BODY);
return;
}
if (queryString == "csp-block") {
response.write(PRE_HEAD + CSP_BLOCK + CSS + POST_HEAD_AND_BODY);
return;
}
if (queryString == "csp-allow") {
response.write(PRE_HEAD + CSP_ALLOW + CSS + POST_HEAD_AND_BODY);
return;
}
// we should never get here, but just in case return something unexpected
response.write("do'h");
}

Binary file not shown.

View File

@ -154,6 +154,8 @@ support-files =
file_docwrite_meta.css
file_docwrite_meta.js
file_multipart_testserver.sjs
file_fontloader.sjs
file_fontloader.woff
[test_base-uri.html]
[test_blob_data_schemes.html]
@ -233,3 +235,4 @@ skip-if = toolkit == 'android' #investigate in bug 1250814
[test_meta_header_dual.html]
[test_docwrite_meta.html]
[test_multipartchannel.html]
[test_fontloader.html]

View File

@ -0,0 +1,98 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Bug 1122236 - CSP: Implement block-all-mixed-content</title>
<!-- Including SimpleTest.js so we can use waitForExplicitFinish !-->
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<!-- Including WindowSnapshot.js so we can take screenshots of containers !-->
<script src="/tests/SimpleTest/WindowSnapshot.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body onload="setupTests()">
<iframe style="width:100%;" id="baselineframe"></iframe>
<iframe style="width:100%;" id="testframe"></iframe>
<script class="testbody" type="text/javascript">
/* Description of the tests:
* We load a baselineFrame and compare the testFrame using
* compareSnapshots whether the font got loaded or blocked.
* Test 1: Use font-src 'none' so font gets blocked
* Test 2: Use font-src * so font gets loaded
* Test 3: Use no csp so font gets loaded
* Test 4: Use font-src 'none' so font gets blocked
* Makes sure the cache gets invalidated.
*/
SimpleTest.waitForExplicitFinish();
const BASE_URI = "https://example.com/tests/dom/security/test/csp/";
const tests = [
{ // test 1
query: "csp-block",
expected: true, // frames should be equal since font is *not* allowed to load
description: "font should be blocked by csp (csp-block)"
},
{ // test 2
query: "csp-allow",
expected: false, // frames should *not* be equal since font is loaded
description: "font should load and apply (csp-allow)"
},
{ // test 3
query: "no-csp",
expected: false, // frames should *not* be equals since font is loaded
description: "font should load and apply (no-csp)"
},
{ // test 4
query: "csp-block",
expected: true, // frames should be equal since font is *not* allowed to load
description: "font should be blocked by csp (csp-block) [apply csp to cache]"
}
];
var curTest;
var counter = -1;
var baselineframe = document.getElementById("baselineframe");
var testframe = document.getElementById("testframe");
function checkResult() {
testframe.removeEventListener('load', checkResult, false);
try {
ok(compareSnapshots(snapshotWindow(baselineframe.contentWindow),
snapshotWindow(testframe.contentWindow),
curTest.expected)[0],
curTest.description);
} catch(err) {
ok(false, "error: " + err.message);
}
loadNextTest();
}
function loadNextTest() {
counter++;
if (counter == tests.length) {
SimpleTest.finish();
return;
}
curTest = tests[counter];
testframe.addEventListener("load", checkResult, false);
testframe.src = BASE_URI + "file_fontloader.sjs?" + curTest.query;
}
// once the baselineframe is loaded we can start running tests
function startTests() {
baselineframe.removeEventListener('load', startTests, false);
loadNextTest();
}
// make sure the main page is loaded before we start the test
function setupTests() {
baselineframe.addEventListener("load", startTests, false);
baselineframe.src = BASE_URI + "file_fontloader.sjs?baseline";
}
</script>
</body>
</html>

View File

@ -0,0 +1,27 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*
* The origin of this IDL file is
* https://webbluetoothcg.github.io/web-bluetooth/#uuids
*
*/
typedef DOMString UUID;
typedef (DOMString or unsigned long) BluetoothServiceUUID;
typedef (DOMString or unsigned long) BluetoothCharacteristicUUID;
typedef (DOMString or unsigned long) BluetoothDescriptorUUID;
[Pref="dom.bluetooth.webbluetooth.enable", CheckAnyPermissions="bluetooth"]
interface BluetoothUUID
{
[Throws]
static UUID getService(BluetoothServiceUUID name);
[Throws]
static UUID getCharacteristic(BluetoothCharacteristicUUID name);
[Throws]
static UUID getDescriptor(BluetoothDescriptorUUID name);
static UUID canonicalUUID([EnforceRange] unsigned long alias);
};

View File

@ -713,6 +713,7 @@ if CONFIG['MOZ_B2G_BT']:
'BluetoothPairingListener.webidl',
'BluetoothPbapParameters.webidl',
'BluetoothPbapRequestHandle.webidl',
'BluetoothUUID.webidl',
]
if CONFIG['MOZ_SIMPLEPUSH']:

View File

@ -1752,6 +1752,11 @@ ScriptExecutorRunnable::WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
aWorkerPrivate->GetOrCreateGlobalScope(aCx);
if (NS_WARN_IF(!globalScope)) {
NS_WARNING("Failed to make global!");
// There's no way to report the exception on aCx right now, because there
// is no way to even enter a compartment on this thread anymore. Just
// clear the exception. We'll report some sort of error to our caller
// thread in ShutdownScriptLoader.
JS_ClearPendingException(aCx);
return false;
}

View File

@ -5742,7 +5742,7 @@ WorkerPrivate::ScheduleKillCloseEventRunnable()
}
void
WorkerPrivate::ReportError(JSContext* aCx, const char* aMessage,
WorkerPrivate::ReportError(JSContext* aCx, const char* aFallbackMessage,
JSErrorReport* aReport)
{
AssertIsOnWorkerThread();
@ -5763,19 +5763,9 @@ WorkerPrivate::ReportError(JSContext* aCx, const char* aMessage,
bool mutedError = aReport && aReport->isMuted;
if (aReport) {
// ErrorEvent objects don't have a |name| field the way ES |Error| objects
// do. Traditionally (and mostly by accident), the |message| field of
// ErrorEvent has corresponded to |Name: Message| of the original Error
// object. Things have been cleaned up in the JS engine, so now we need to
// format this string explicitly.
JS::Rooted<JSString*> messageStr(aCx,
js::ErrorReportToString(aCx, aReport));
if (messageStr) {
nsAutoJSString autoStr;
if (autoStr.init(aCx, messageStr)) {
message = autoStr;
}
}
// We want the same behavior here as xpc::ErrorReport::init here.
xpc::ErrorReport::ErrorReportToMessageString(aReport, message);
filename = NS_ConvertUTF8toUTF16(aReport->filename);
line = aReport->uclinebuf;
lineNumber = aReport->lineno;
@ -5791,7 +5781,7 @@ WorkerPrivate::ReportError(JSContext* aCx, const char* aMessage,
}
if (message.IsEmpty()) {
message = NS_ConvertUTF8toUTF16(aMessage);
message = NS_ConvertUTF8toUTF16(aFallbackMessage);
}
mErrorHandlerRecursionCount++;

View File

@ -213,7 +213,7 @@ skip-if = (toolkit == 'gonk' && debug) # Bug 1176223
[test_urlApi.html]
[test_urlSearchParams.html]
[test_websocket.html]
skip-if = buildapp == 'b2g' || toolkit == 'android' #bug 982828
skip-if = buildapp == 'b2g' || toolkit == 'android' || (e10s && debug && os == 'win') #bug 982828, bug 1237470
[test_websocket_basic.html]
skip-if = buildapp == 'b2g' || toolkit == 'android' #bug 982828
[test_websocket_https.html]

View File

@ -1,5 +1,5 @@
[DEFAULT]
skip-if = buildapp == 'b2g'
skip-if = buildapp == 'b2g' || (e10s && debug && os == 'win')
support-files =
worker.js
@ -199,127 +199,66 @@ support-files =
lorem_script.js
[test_bug1151916.html]
skip-if = e10s && debug && os == 'win'
[test_claim.html]
skip-if = e10s && debug && os == 'win'
[test_claim_fetch.html]
skip-if = e10s && debug && os == 'win'
[test_claim_oninstall.html]
skip-if = e10s && debug && os == 'win'
[test_close.html]
skip-if = e10s && debug && os == 'win'
[test_controller.html]
skip-if = e10s && debug && os == 'win'
[test_cross_origin_url_after_redirect.html]
skip-if = e10s && debug && os == 'win'
[test_empty_serviceworker.html]
skip-if = e10s && debug && os == 'win'
[test_eval_allowed.html]
skip-if = e10s && debug && os == 'win'
[test_fetch_event.html]
skip-if = e10s && debug && os == 'win'
[test_force_refresh.html]
skip-if = e10s && debug && os == 'win'
[test_gzip_redirect.html]
skip-if = e10s && debug && os == 'win'
[test_https_fetch.html]
skip-if = e10s && debug && os == 'win'
[test_https_fetch_cloned_response.html]
skip-if = e10s && debug && os == 'win'
[test_https_origin_after_redirect.html]
skip-if = e10s && debug && os == 'win'
[test_https_origin_after_redirect_cached.html]
skip-if = e10s && debug && os == 'win'
[test_https_synth_fetch_from_cached_sw.html]
skip-if = e10s && debug && os == 'win'
[test_importscript.html]
skip-if = e10s && debug && os == 'win'
[test_install_event.html]
skip-if = e10s && debug && os == 'win'
[test_installation_simple.html]
skip-if = e10s && debug && os == 'win'
[test_match_all.html]
skip-if = e10s && debug && os == 'win'
[test_match_all_advanced.html]
skip-if = e10s && debug && os == 'win'
[test_match_all_client_id.html]
skip-if = e10s && debug && os == 'win'
[test_match_all_client_properties.html]
skip-if = e10s && debug && os == 'win'
[test_navigator.html]
skip-if = e10s && debug && os == 'win'
[test_origin_after_redirect.html]
skip-if = e10s && debug && os == 'win'
[test_origin_after_redirect_cached.html]
skip-if = e10s && debug && os == 'win'
[test_origin_after_redirect_to_https.html]
skip-if = e10s && debug && os == 'win'
[test_origin_after_redirect_to_https_cached.html]
skip-if = e10s && debug && os == 'win'
[test_post_message.html]
skip-if = e10s && debug && os == 'win'
[test_post_message_advanced.html]
skip-if = e10s && debug && os == 'win'
[test_post_message_source.html]
skip-if = e10s && debug && os == 'win'
[test_register_base.html]
skip-if = e10s && debug && os == 'win'
[test_register_https_in_http.html]
skip-if = e10s && debug && os == 'win'
[test_request_context_audio.html]
skip-if = e10s && debug && os == 'win'
[test_request_context_beacon.html]
skip-if = e10s && debug && os == 'win'
[test_request_context_cache.html]
skip-if = e10s && debug && os == 'win'
[test_request_context_cspreport.html]
skip-if = e10s && debug && os == 'win'
[test_request_context_embed.html]
skip-if = e10s && debug && os == 'win'
[test_request_context_fetch.html]
skip-if = e10s && debug && os == 'win'
[test_request_context_font.html]
skip-if = e10s && debug && os == 'win'
[test_request_context_frame.html]
skip-if = e10s && debug && os == 'win'
[test_request_context_iframe.html]
skip-if = e10s && debug && os == 'win'
[test_request_context_image.html]
skip-if = e10s && debug && os == 'win'
[test_request_context_imagesrcset.html]
skip-if = e10s && debug && os == 'win'
[test_request_context_internal.html]
skip-if = e10s && debug && os == 'win'
[test_request_context_nestedworker.html]
skip-if = e10s && debug && os == 'win'
[test_request_context_nestedworkerinsharedworker.html]
skip-if = e10s && debug && os == 'win'
[test_request_context_object.html]
skip-if = e10s && debug && os == 'win'
[test_request_context_picture.html]
skip-if = e10s && debug && os == 'win'
[test_request_context_ping.html]
skip-if = e10s && debug && os == 'win'
[test_request_context_plugin.html]
skip-if = e10s && debug && os == 'win'
[test_request_context_script.html]
skip-if = e10s && debug && os == 'win'
[test_request_context_sharedworker.html]
skip-if = e10s && debug && os == 'win'
[test_request_context_style.html]
skip-if = e10s && debug && os == 'win'
[test_request_context_track.html]
skip-if = e10s && debug && os == 'win'
[test_request_context_video.html]
skip-if = e10s && debug && os == 'win'
[test_request_context_worker.html]
skip-if = e10s && debug && os == 'win'
[test_request_context_xhr.html]
skip-if = e10s && debug && os == 'win'
[test_request_context_xslt.html]
skip-if = e10s && debug && os == 'win'
[test_scopes.html]
skip-if = e10s && debug && os == 'win'
[test_sandbox_intercept.html]
skip-if = e10s && debug && os == 'win'
[test_notificationclick.html]

View File

@ -25,7 +25,7 @@ Tests of DOM Worker Threads
worker.onerror = function(event) {
is(event.target, worker);
is(event.message, ': NetworkError: Failed to load worker script at "nonexistent_worker.js"');
is(event.message, 'NetworkError: Failed to load worker script at "nonexistent_worker.js"');
event.preventDefault();
SimpleTest.finish();
};

View File

@ -25,7 +25,7 @@ function test(script) {
worker.onerror = function(event) {
is(event.target, worker);
ok(event.message.startsWith(": NetworkError: Failed to load worker script"))
ok(event.message.startsWith("NetworkError: Failed to load worker script"))
event.preventDefault();
runTests();
};

View File

@ -13,7 +13,7 @@
<script class="testbody" type="text/javascript">
"use strict";
var loadErrorMessage = ': SecurityError: Failed to load worker script at "about:blank"';
var loadErrorMessage = 'SecurityError: Failed to load worker script at "about:blank"';
function nextTest() {
(function(){

View File

@ -47,7 +47,7 @@ Tests of DOM Worker Threads
worker.onerror = function(event) {
event.preventDefault();
if (event.message == "InternalError: too much recursion") {
if (event.message == "too much recursion") {
ok(true, "got correct error message");
++errorCount;
}

View File

@ -47,7 +47,7 @@ Tests of DOM Worker Threads (Bug 437152)
worker.onerror = function(event) {
event.preventDefault();
is(event.target, worker);
is(event.message, "InternalError: uncaught exception: Bad message: asdf");
is(event.message, "uncaught exception: Bad message: asdf");
worker.onerror = function(otherEvent) {
otherEvent.preventDefault();

View File

@ -28,7 +28,7 @@ Tests of DOM Worker Threads
event.preventDefault();
var found = false;
for (var index in errors) {
if (event.message == "InternalError: uncaught exception: " + errors[index]) {
if (event.message == "uncaught exception: " + errors[index]) {
errors.splice(index, 1);
found = true;
break;

View File

@ -4,6 +4,7 @@ support-files =
bug293834_form.html
[test_bug293834.html]
skip-if = (toolkit == "cocoa" && e10s) # bug 1252223
[test_bug499115.html]
[test_nsFind.html]
[test_private_window_from_content.html]

View File

@ -99,6 +99,7 @@ static const char *sExtensionNames[] = {
"GL_ARB_pixel_buffer_object",
"GL_ARB_robustness",
"GL_ARB_sampler_objects",
"GL_ARB_seamless_cube_map",
"GL_ARB_sync",
"GL_ARB_texture_compression",
"GL_ARB_texture_float",

View File

@ -126,6 +126,7 @@ enum class GLFeature {
sRGB_framebuffer,
sRGB_texture,
sampler_objects,
seamless_cube_map_opt_in,
split_framebuffer,
standard_derivatives,
sync,
@ -420,6 +421,7 @@ public:
ARB_pixel_buffer_object,
ARB_robustness,
ARB_sampler_objects,
ARB_seamless_cube_map,
ARB_sync,
ARB_texture_compression,
ARB_texture_float,

View File

@ -547,6 +547,15 @@ static const FeatureInfo sFeatureInfoArr[] = {
GLContext::Extensions_End
}
},
{
"seamless_cube_map_opt_in",
GLVersion::GL3_2,
GLESVersion::NONE,
GLContext::ARB_seamless_cube_map,
{
GLContext::Extensions_End
}
},
{
// Do we have separate DRAW and READ framebuffer bind points?
"split_framebuffer",

View File

@ -589,6 +589,7 @@ SampleAnimations(Layer* aLayer, TimeStamp aPoint)
// into their start time, hence the delay is effectively zero.
timing.mDelay = TimeDuration(0);
timing.mIterations = animation.iterations();
timing.mIterationStart = animation.iterationStart();
timing.mDirection =
static_cast<dom::PlaybackDirection>(animation.direction());
// Animations typically only run on the compositor during their active

View File

@ -357,7 +357,7 @@ ImageHost::Composite(LayerComposite* aLayer,
bool isAlphaPremultiplied =
!(mCurrentTextureHost->GetFlags() & TextureFlags::NON_PREMULTIPLIED);
RefPtr<TexturedEffect> effect =
CreateTexturedEffect(mCurrentTextureHost->GetFormat(),
CreateTexturedEffect(mCurrentTextureHost->GetReadFormat(),
mCurrentTextureSource.get(), aFilter, isAlphaPremultiplied,
GetRenderState());
if (!effect) {
@ -597,7 +597,7 @@ ImageHost::GenEffect(const gfx::Filter& aFilter)
isAlphaPremultiplied = false;
}
return CreateTexturedEffect(mCurrentTextureHost->GetFormat(),
return CreateTexturedEffect(mCurrentTextureHost->GetReadFormat(),
mCurrentTextureSource,
aFilter,
isAlphaPremultiplied,

View File

@ -195,6 +195,7 @@ struct Animation {
// Values <= 0 mean the animation will not play (although events are still
// dispatched on the main thread).
float iterations;
float iterationStart;
// This uses the NS_STYLE_ANIMATION_DIRECTION_* constants.
int32_t direction;
nsCSSProperty property;

View File

@ -350,13 +350,8 @@ gfxPlatformGtk::GetDPIScale()
bool
gfxPlatformGtk::UseImageOffscreenSurfaces()
{
// We want to turn on image offscreen surfaces ONLY for GTK3 builds since
// GTK2 theme rendering still requires xlib surfaces.
#if (MOZ_WIDGET_GTK == 3)
return gfxPrefs::UseImageOffscreenSurfaces();
#else
return false;
#endif
return GetDefaultContentBackend() != mozilla::gfx::BackendType::CAIRO ||
gfxPrefs::UseImageOffscreenSurfaces();
}
gfxImageFormat

View File

@ -100,10 +100,6 @@ public:
bool UseXRender() {
#if defined(MOZ_X11)
if (GetDefaultContentBackend() != mozilla::gfx::BackendType::NONE &&
GetDefaultContentBackend() != mozilla::gfx::BackendType::CAIRO)
return false;
return sUseXRender;
#else
return false;

View File

@ -7,6 +7,7 @@
#include "gfxUserFontSet.h"
#include "gfxPlatform.h"
#include "nsContentPolicyUtils.h"
#include "nsUnicharUtils.h"
#include "nsNetUtil.h"
#include "nsIJARChannel.h"
@ -1203,6 +1204,13 @@ gfxUserFontSet::UserFontCache::GetFont(nsIURI* aSrcURI,
return nullptr;
}
// We have to perform another content policy check here to prevent
// cache poisoning. E.g. a.com loads a font into the cache but
// b.com has a CSP not allowing any fonts to be loaded.
if (!aUserFontEntry->mFontSet->IsFontLoadAllowed(aSrcURI, aPrincipal)) {
return nullptr;
}
// Ignore principal when looking up a data: URI.
nsIPrincipal* principal;
if (IgnorePrincipal(aSrcURI)) {
@ -1217,12 +1225,14 @@ gfxUserFontSet::UserFontCache::GetFont(nsIURI* aSrcURI,
return entry->GetFontEntry();
}
// The channel is never openend; to be conservative we use the most
// restrictive security flag: SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS.
nsCOMPtr<nsIChannel> chan;
if (NS_FAILED(NS_NewChannel(getter_AddRefs(chan),
aSrcURI,
aPrincipal,
nsILoadInfo::SEC_NORMAL,
nsIContentPolicy::TYPE_OTHER))) {
nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS,
nsIContentPolicy::TYPE_FONT))) {
return nullptr;
}

View File

@ -262,6 +262,10 @@ public:
nsIPrincipal** aPrincipal,
bool* aBypassCache) = 0;
// check whether content policies allow the given URI to load.
virtual bool IsFontLoadAllowed(nsIURI* aFontLocation,
nsIPrincipal* aPrincipal) = 0;
// initialize the process that loads external font data, which upon
// completion will call FontDataDownloadComplete method
virtual nsresult StartLoad(gfxUserFontEntry* aUserFontEntry,

View File

@ -537,11 +537,7 @@ gfxXlibNativeRenderer::Draw(gfxContext* ctx, IntSize size,
gfxPoint deviceTranslation = gfxPoint(dtTransform._31, dtTransform._32);
cairo_t* cairo = static_cast<cairo_t*>
(drawTarget->GetNativeSurface(NativeSurfaceType::CAIRO_CONTEXT));
if (!cairo) {
return;
}
cairo_surface_t* cairoTarget = cairo_get_group_target(cairo);
cairo_surface_t* cairoTarget = cairo ? cairo_get_group_target(cairo) : nullptr;
cairo_surface_t* tempXlibSurface =
CreateTempXlibSurface(cairoTarget, drawTarget, size,
canDrawOverBackground, flags, screen, visual,

View File

@ -83,7 +83,6 @@ FrameAnimator::AdvanceFrame(TimeStamp aTime)
uint32_t currentFrameIndex = mCurrentAnimationFrameIndex;
uint32_t nextFrameIndex = currentFrameIndex + 1;
int32_t timeout = 0;
RefreshResult ret;
RawAccessFrameRef nextFrame = GetRawFrame(nextFrameIndex);
@ -103,6 +102,23 @@ FrameAnimator::AdvanceFrame(TimeStamp aTime)
// If we're done decoding the next frame, go ahead and display it now and
// reinit with the next frame's delay time.
if (mImage->GetNumFrames() == nextFrameIndex) {
// We can only accurately determine if we are at the end of the loop if we are
// done decoding, otherwise we don't know how many frames there will be.
if (!mDoneDecoding) {
// We've already advanced to the last decoded frame, nothing more we can do.
// We're blocked by network/decoding from displaying the animation at the
// rate specified, so that means the frame we are displaying (the latest
// available) is the frame we want to be displaying at this time. So we
// update the current animation time. If we didn't update the current
// animation time then it could lag behind, which would indicate that we
// are behind in the animation and should try to catch up. When we are
// done decoding (and thus can loop around back to the start of the
// animation) we would then jump to a random point in the animation to
// try to catch up. But we were never behind in the animation.
mCurrentAnimationFrameTime = aTime;
return ret;
}
// End of an animation loop...
// If we are not looping forever, initialize the loop counter
@ -129,10 +145,8 @@ FrameAnimator::AdvanceFrame(TimeStamp aTime)
}
}
timeout = GetTimeoutForFrame(nextFrameIndex);
// Bad data
if (timeout < 0) {
if (GetTimeoutForFrame(nextFrameIndex) < 0) {
ret.animationFinished = true;
ret.error = true;
}
@ -140,13 +154,10 @@ FrameAnimator::AdvanceFrame(TimeStamp aTime)
if (nextFrameIndex == 0) {
ret.dirtyRect = mFirstFrameRefreshArea;
} else {
// Change frame
if (nextFrameIndex != currentFrameIndex + 1) {
nextFrame = GetRawFrame(nextFrameIndex);
}
MOZ_ASSERT(nextFrameIndex == currentFrameIndex + 1);
if (!DoBlend(&ret.dirtyRect, currentFrameIndex,
nextFrameIndex)) {
// Change frame
if (!DoBlend(&ret.dirtyRect, currentFrameIndex, nextFrameIndex)) {
// something went wrong, move on to next
NS_WARNING("FrameAnimator::AdvanceFrame(): Compositing of frame failed");
nextFrame->SetCompositingFailed(true);

View File

@ -95,7 +95,8 @@ RilConsumer::ConnectWorkerToRIL(JSContext* aCx)
// should ever define |postRILMessage| in a RIL worker.
Rooted<Value> val(aCx);
if (!JS_GetProperty(aCx, workerGlobal, "postRILMessage", &val)) {
JS_ReportPendingException(aCx);
// Just returning failure here will cause the exception on the JSContext to
// be reported as needed.
return NS_ERROR_FAILURE;
}
@ -108,6 +109,8 @@ RilConsumer::ConnectWorkerToRIL(JSContext* aCx)
"postRILMessage",
PostRILMessage, 2, 0);
if (NS_WARN_IF(!postRILMessage)) {
// Just returning failure here will cause the exception on the JSContext to
// be reported as needed.
return NS_ERROR_FAILURE;
}
return NS_OK;
@ -246,6 +249,9 @@ RilConsumer::Receive(JSContext* aCx,
Rooted<JSObject*> array(aCx, JS_NewUint8Array(aCx, aBuffer->GetSize()));
if (NS_WARN_IF(!array)) {
// Just suppress the exception, since our callers don't have a way to
// indicate they failed.
JS_ClearPendingException(aCx);
return NS_ERROR_FAILURE;
}
{
@ -262,6 +268,9 @@ RilConsumer::Receive(JSContext* aCx,
Rooted<Value> rval(aCx);
JS_CallFunctionName(aCx, obj, "onRILMessage", args, &rval);
// Just suppress the exception, since our callers don't have a way to
// indicate they failed.
JS_ClearPendingException(aCx);
return NS_OK;
}

View File

@ -427,11 +427,9 @@ DecodeExpr(FunctionDecoder& f, ExprType expected)
case Expr::IfElse:
return DecodeIfElse(f, /* hasElse */ true, expected);
case Expr::I32Clz:
return DecodeUnaryOperator(f, expected, ExprType::I32);
case Expr::I32Ctz:
return f.fail("NYI: ctz");
case Expr::I32Popcnt:
return f.fail("NYI: popcnt");
return DecodeUnaryOperator(f, expected, ExprType::I32);
case Expr::I64Clz:
case Expr::I64Ctz:
case Expr::I64Popcnt:

View File

@ -2821,6 +2821,10 @@ EmitExpr(FunctionCompiler& f, ExprType type, MDefinition** def, LabelVector* may
return EmitUnary<MTruncateToInt32>(f, ExprType::F64, def);
case Expr::I32Clz:
return EmitUnary<MClz>(f, ExprType::I32, def);
case Expr::I32Ctz:
return EmitUnary<MCtz>(f, ExprType::I32, def);
case Expr::I32Popcnt:
return EmitUnary<MPopcnt>(f, ExprType::I32, def);
case Expr::I32Abs:
return EmitUnaryMir<MAbs>(f, ExprType::I32, def);
case Expr::I32Neg:
@ -3057,8 +3061,6 @@ EmitExpr(FunctionCompiler& f, ExprType type, MDefinition** def, LabelVector* may
case Expr::Select:
case Expr::Br:
case Expr::BrIf:
case Expr::I32Ctz:
case Expr::I32Popcnt:
case Expr::F32CopySign:
case Expr::F32Trunc:
case Expr::F32Nearest:

View File

@ -1,3 +1,6 @@
if (!this.hasOwnProperty("TypedObject"))
quit();
var T = TypedObject;
ValueStruct = new T.StructType({
f: T.int32,

View File

@ -17,7 +17,6 @@ function evalErrorStr(global, evalString) {
assertEq(evalErrorStr(g, "let y = IDONTEXIST;"), "ReferenceError: IDONTEXIST is not defined");
assertEq(evalErrorStr(g, "y = 1;"),
"ReferenceError: can't access lexical declaration `y' before initialization");
@ -32,13 +31,22 @@ assertEq(g.evaluate("y"), 1);
assertEq(gw.forceLexicalInitializationByName("idontexist"), false);
assertEq(evalErrorStr(g, "idontexist"), "ReferenceError: idontexist is not defined");
// Ensure that ropes (non-atoms) behave properly
assertEq(gw.forceLexicalInitializationByName(("foo" + "bar" + "bop" + "zopple" + 2 + 3).slice(1)),
false);
assertEq(evalErrorStr(g, "let oobarbopzopple23 = IDONTEXIST;"), "ReferenceError: IDONTEXIST is not defined");
assertEq(gw.forceLexicalInitializationByName(("foo" + "bar" + "bop" + "zopple" + 2 + 3).slice(1)),
true);
assertEq(g.evaluate("oobarbopzopple23"), undefined);
// Ensure that only strings are accepted by forceLexicalInitializationByName
const bad_types = [
2112,
{geddy: "lee"},
() => 1,
[],
Array
Array,
"'1'", // non-identifier
]
for (var badType of bad_types) {

View File

@ -51,8 +51,13 @@ function testComparison(type, opcode, lhs, rhs, expect) {
}
testUnary('i32', 'clz', 40, 26);
//testUnary('i32', 'ctz', 40, 0); // TODO: NYI
//testUnary('i32', 'popcnt', 40, 0); // TODO: NYI
testUnary('i32', 'ctz', 40, 3);
testUnary('i32', 'ctz', 0, 32);
testUnary('i32', 'ctz', -2147483648, 31);
testUnary('i32', 'popcnt', 40, 2);
testUnary('i32', 'popcnt', 0, 0);
testUnary('i32', 'popcnt', 0xFFFFFFFF, 32);
testBinary('i32', 'add', 40, 2, 42);
testBinary('i32', 'sub', 40, 2, 38);

View File

@ -0,0 +1,182 @@
load(libdir + "wasm.js");
load(scriptdir + "spec/list.js");
if (typeof assert === 'undefined') {
var assert = function assert(c, msg) {
if (!c) {
throw new Error("Assertion failed: " + msg);
}
};
}
// Element list or string.
function Element(str, dollared, quoted) {
this.list = [];
this.str = str === undefined ? null : str;
this.dollared = !!dollared;
this.quoted = !!quoted;
}
Element.prototype.toString = function() {
if (this.str !== null) {
if (this.dollared) {
return "$" + this.str;
} else if (this.quoted) {
return `"${this.str}"`;
}
return this.str;
}
return `(${this.list.map(x => x.toString()).join(" ")})`;
};
// Creates a tree of s-expressions. Ported from Binaryen's SExpressionParser.
function parseSExpression(text) {
var input = 0;
function parseInnerList() {
if (text[input] === ';') {
// Parse comment.
input++;
if (text[input] === ';') {
while (text[input] != '\n') input++;
return null;
}
input = text.substring(";)", input);
assert(input >= 0);
return null;
}
var ret = new Element();
while (true) {
var curr = parse();
if (!curr) return ret;
ret.list.push(curr);
}
}
function isSpace(c) {
switch (c) {
case ' ':
case '\n':
case '\r':
case '\t':
case '\v':
case '\f':
return true;
default:
return false;
}
}
function skipWhitespace() {
while (true) {
while (isSpace(text[input])) input++;
if (text[input] === ';' && text[input + 1] === ';') {
while (text.length > input && text[input] != '\n') input++;
} else if (text[input] === '(' && text[input + 1] === ';') {
input = text.substring(";)", input) + 2;
} else {
return;
}
}
}
function parseString() {
var dollared = false;
var quoted = false;
if (text[input] === '$') {
input++;
dollared = true;
}
var start = input;
if (text[input] === '"') {
quoted = true;
// Parse escaping \", but leave code escaped - we'll handle escaping in memory segments specifically.
input++;
var str = "";
while (true) {
if (text[input] === '"') break;
if (text[input] === '\\') {
str += text[input];
str += text[input + 1];
input += 2;
continue;
}
str += text[input];
input++;
}
input++;
return new Element(str, dollared, quoted);
}
while (text.length > input && !isSpace(text[input]) && text[input] != ')' && text[input] != '(') input++;
return new Element(text.substring(start, input), dollared);
}
function parse() {
skipWhitespace();
if (text.length === input || text[input] === ')') return null;
if (text[input] === '(') {
input++;
var ret = parseInnerList();
skipWhitespace();
assert(text[input] === ')');
input++;
return ret;
}
return parseString();
}
var root = null;
while (!root) { // Keep parsing until we pass an initial comment.
root = parseInnerList();
}
return root;
}
var imports = {
spectest: {
print: function (x) {
print(x);
}
}
};
var module;
var moduleText;
// Recursively execute the expression.
function exec(e) {
var exprName = e.list[0].str;
if (exprName === "module") {
moduleText = e.toString();
try {
module = wasmEvalText(moduleText, imports);
} catch (x) {
assert(false, x.toString());
}
} else if (exprName === "invoke") {
var name = e.list[1].str;
var args = e.list.slice(2).map(exec);
var fn = null;
assert(module !== null);
if (typeof module[name] === "function") {
fn = module[name];
} else if (name === "") {
fn = module;
assert(typeof fn === "function", "Default exported function not found: " + e);
} else {
assert(false, "Exported function not found: " + e);
}
return fn.apply(null, args);
} else if (exprName.indexOf(".const") > 0) {
// Eval the expression using a wasm module.
var type = exprName.substring(0, exprName.indexOf(".const"));
return wasmEvalText('(module (func (result ' + type + ') ' + e + ') (export "" 0))')()
} else if (exprName === "assert_return") {
assertEq(exec(e.list[1]), exec(e.list[2]));
} else if (exprName === "assert_return_nan") {
assertEq(exec(e.list[1]), NaN);
} else {
assert(false, "NYI: " + e);
}
}
for (var test of specTests) {
module = null;
moduleText = null;
var root = new parseSExpression(read(scriptdir + "spec/" + test));
for (var e of root.list) {
exec(e);
}
}

View File

@ -0,0 +1,7 @@
// Included by ../spec.js.
var specTests = [];
specTests.push("names.wast");
// Add more tests here.

View File

@ -0,0 +1,91 @@
;; Test files can define multiple modules. Test that implementations treat
;; each module independently from the other.
(module
(func $foo (result i32) (i32.const 0))
(export "foo" $foo)
)
(assert_return (invoke "foo") (i32.const 0))
;; Another module, same function name, different contents.
(module
(func $foo (result i32) (i32.const 1))
(export "foo" $foo)
)
(assert_return (invoke "foo") (i32.const 1))
(module
;; Test that we can use the empty string as a symbol.
(func (result f32) (f32.const 0x1.91p+2))
(export "" 0)
;; Test that we can use common libc names without conflict.
(func $malloc (result f32) (f32.const 0x1.92p+2))
(export "malloc" $malloc)
;; Test that we can use some libc hidden names without conflict.
(func $_malloc (result f32) (f32.const 0x1.93p+2))
(func $__malloc (result f32) (f32.const 0x1.94p+2))
(func (result f32) (f32.const 0x1.95p+2))
(export "_malloc" $_malloc)
(export "__malloc" $__malloc)
;; Test that we can use non-alphanumeric names.
(func (result f32) (f32.const 0x1.96p+2))
(export "~!@#$%^&*()_+`-={}|[]\\:\";'<>?,./ " 5)
;; Test that we can use names beginning with a digit.
(func (result f32) (f32.const 0x1.97p+2))
(export "0" 6)
;; Test that we can use names beginning with an underscore.
(func $_ (result f32) (f32.const 0x1.98p+2))
(export "_" $_)
;; Test that we can use names beginning with a dollar sign.
(func (result f32) (f32.const 0x1.99p+2))
(export "$" 8)
;; Test that we can use names beginning with an at sign.
(func (result f32) (f32.const 0x2.00p+2))
(export "@" 9)
;; Test that we can use names that have special meaning in JS.
(func $NaN (result f32) (f32.const 0x2.01p+2))
(func $Infinity (result f32) (f32.const 0x2.02p+2))
(func $if (result f32) (f32.const 0x2.03p+2))
(export "NaN" $NaN)
(export "Infinity" $Infinity)
(export "if" $if)
)
(assert_return (invoke "") (f32.const 0x1.91p+2))
(assert_return (invoke "malloc") (f32.const 0x1.92p+2))
(assert_return (invoke "_malloc") (f32.const 0x1.93p+2))
(assert_return (invoke "__malloc") (f32.const 0x1.94p+2))
(assert_return (invoke "~!@#$%^&*()_+`-={}|[]\\:\";'<>?,./ ") (f32.const 0x1.96p+2))
(assert_return (invoke "0") (f32.const 0x1.97p+2))
(assert_return (invoke "_") (f32.const 0x1.98p+2))
(assert_return (invoke "$") (f32.const 0x1.99p+2))
(assert_return (invoke "@") (f32.const 0x2.00p+2))
(assert_return (invoke "NaN") (f32.const 0x2.01p+2))
(assert_return (invoke "Infinity") (f32.const 0x2.02p+2))
(assert_return (invoke "if") (f32.const 0x2.03p+2))
(module
;; Test that we can use indices instead of names to reference imports,
;; functions and parameters.
(import "spectest" "print" (param i32))
(import "spectest" "print" (param i32))
(func (param i32) (param i32)
(call_import 0 (get_local 0))
(call_import 1 (get_local 1))
)
(export "print32" 0)
)
(invoke "print32" (i32.const 42) (i32.const 123))

View File

@ -1393,6 +1393,24 @@ LIRGenerator::visitClz(MClz* ins)
define(lir, ins);
}
void
LIRGenerator::visitCtz(MCtz* ins)
{
MDefinition* num = ins->num();
LCtzI* lir = new(alloc()) LCtzI(useRegisterAtStart(num));
define(lir, ins);
}
void
LIRGenerator::visitPopcnt(MPopcnt* ins)
{
MDefinition* num = ins->num();
LPopcntI* lir = new(alloc()) LPopcntI(useRegisterAtStart(num), temp());
define(lir, ins);
}
void
LIRGenerator::visitSqrt(MSqrt* ins)
{

Some files were not shown because too many files have changed in this diff Show More