mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
merge mozilla-inbound to mozilla-central a=merge
This commit is contained in:
commit
33a2ccf44e
16
.gitignore
vendored
16
.gitignore
vendored
@ -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
|
||||
|
12
.hgignore
12
.hgignore
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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>
|
||||
|
@ -61,6 +61,7 @@ SEARCH_PATHS = [
|
||||
'python/blessings',
|
||||
'python/compare-locales',
|
||||
'python/configobj',
|
||||
'python/futures',
|
||||
'python/jsmin',
|
||||
'python/psutil',
|
||||
'python/which',
|
||||
|
@ -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
|
||||
|
@ -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]
|
||||
|
@ -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]
|
||||
|
@ -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]
|
||||
|
@ -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]
|
||||
|
@ -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]
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -872,3 +872,4 @@ skip-if = buildapp == 'b2g' #no ssl support
|
||||
[test_bug1187157.html]
|
||||
[test_bug769117.html]
|
||||
[test_bug1250148.html]
|
||||
[test_bug1240471.html]
|
45
dom/base/test/test_bug1240471.html
Normal file
45
dom/base/test/test_bug1240471.html
Normal 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>
|
273
dom/bluetooth/common/BluetoothGattUUIDName.h
Normal file
273
dom/bluetooth/common/BluetoothGattUUIDName.h
Normal 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
|
234
dom/bluetooth/common/webapi/BluetoothUUID.cpp
Normal file
234
dom/bluetooth/common/webapi/BluetoothUUID.cpp
Normal 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);
|
||||
}
|
126
dom/bluetooth/common/webapi/BluetoothUUID.h
Normal file
126
dom/bluetooth/common/webapi/BluetoothUUID.h
Normal 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
|
@ -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',
|
||||
|
@ -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)
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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
|
||||
|
@ -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]
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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]
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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()
|
||||
{
|
||||
|
@ -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();
|
||||
|
@ -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,
|
||||
|
@ -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_
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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]
|
||||
|
@ -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() {
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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)) {
|
||||
|
@ -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";
|
||||
}
|
||||
|
58
dom/security/test/csp/file_fontloader.sjs
Normal file
58
dom/security/test/csp/file_fontloader.sjs
Normal 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");
|
||||
}
|
BIN
dom/security/test/csp/file_fontloader.woff
Normal file
BIN
dom/security/test/csp/file_fontloader.woff
Normal file
Binary file not shown.
@ -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]
|
||||
|
98
dom/security/test/csp/test_fontloader.html
Normal file
98
dom/security/test/csp/test_fontloader.html
Normal 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>
|
27
dom/webidl/BluetoothUUID.webidl
Normal file
27
dom/webidl/BluetoothUUID.webidl
Normal 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);
|
||||
};
|
@ -713,6 +713,7 @@ if CONFIG['MOZ_B2G_BT']:
|
||||
'BluetoothPairingListener.webidl',
|
||||
'BluetoothPbapParameters.webidl',
|
||||
'BluetoothPbapRequestHandle.webidl',
|
||||
'BluetoothUUID.webidl',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_SIMPLEPUSH']:
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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++;
|
||||
|
@ -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]
|
||||
|
@ -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]
|
||||
|
@ -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();
|
||||
};
|
||||
|
@ -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();
|
||||
};
|
||||
|
@ -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(){
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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]
|
||||
|
@ -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",
|
||||
|
@ -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,
|
||||
|
@ -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",
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -1,3 +1,6 @@
|
||||
if (!this.hasOwnProperty("TypedObject"))
|
||||
quit();
|
||||
|
||||
var T = TypedObject;
|
||||
ValueStruct = new T.StructType({
|
||||
f: T.int32,
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
182
js/src/jit-test/tests/wasm/spec.js
Normal file
182
js/src/jit-test/tests/wasm/spec.js
Normal 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);
|
||||
}
|
||||
}
|
7
js/src/jit-test/tests/wasm/spec/list.js
Normal file
7
js/src/jit-test/tests/wasm/spec/list.js
Normal file
@ -0,0 +1,7 @@
|
||||
// Included by ../spec.js.
|
||||
|
||||
var specTests = [];
|
||||
|
||||
specTests.push("names.wast");
|
||||
|
||||
// Add more tests here.
|
91
js/src/jit-test/tests/wasm/spec/names.wast
Normal file
91
js/src/jit-test/tests/wasm/spec/names.wast
Normal 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))
|
@ -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
Loading…
Reference in New Issue
Block a user