mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 05:11:03 +00:00
import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1247982 - Lock request headers. r=mcmanus (8a5940a109) - Bug 1251332 - add PAC support for reversed ranges; r=bagder (7ac8fd97cb) - Bug 1178337 - Part 1: Supports all referrer policies for element atrributes. r=sicking, r=Gijs, r=mcmanus (85b7421b02) - Bug 1187357 - rename referrer attribute to referrerpolicy in tests. r=hsivonen (da334bf712) - Bug 1178337 - Part 2: Update/add test cases. r=sicking. (acec860fd8) - Bug 1260766 - the comparison of OriginAttributes in nsFrameLoader::Swap* methods should consider the usercontextid attribute of the owning element, r=smaug (82f8895bec) - bits of Bug 1110485 P1 (f8908eb35f) - Bug 1195968 - Check how CanvasFilterChainObserver accesses the CanvasRenderingContext2D. r=mstange (eecc12329b) - Bug 1260960 - Check skiaGL is enabled before calling skiaGLTex(), r=snorp (82c069fcc9) - align test stuff (c0ccc11ed9) - Bug 1245256 - GMP Plugins now installed in flat manner to accomodate widevine. r=spohl (ae0eb69979) - Bug 1245649: Turn on use-isnan, no-unexpected-multiline (0633b3470f) - Bug 1079665 - [e10s] Findbar focusContent doesn't work when a link was found. r=enndeakin (b349e62d5a) - Bug 1174291 - Fix ctrl-return for e10s findbar. r=evilpie (6f0bf0b149) - Bug 1174289 - Remove fake focus-ring after e10s findbar is closed. r=evilpie (302ffe7559) - Bug 1079665 - follow up, remove accidental line included from different patch. r=me (0904fe927c) - Bug 1260208 - part 1 - use C I/O facilities in TestWebGLElementArrayCache instead of C++ ones; r=BenWa The libc++ included with the Android NDK does not seem to work correctly with std::cerr; writing to it (or to std::cout, as confirmed by tests) causes the process to hang indefinitely, causing test failures. Using fprintf and stderr, however, seems to work correctly. (4279c2d09d) - Bug 1260208 - part 5 - add libc++ license to about:license when using it on Android; r=gerv,nalexander (4bcf23794a) - Bug 1260208 - part 0 - correctly compare EHTable when sorting; r=froydnj operator< for EHTable compares the LHS start PC with the RHS *end* PC. Because the ranges are non-overlapping, this works fine for two distinct EHTables. However, the comparison doesn't work if LHS and RHS refer to the same EHTable; in that case operator< returns true, even though it should return false because the two operands are identical. (dc2af36cec) - Bug 1254908 - ./mach bootstrap doesn't work on CentOS/Fedora when it attempts to upgrade Mercurial. r=gps (d288b314ec) - Bug 1239413. Clarify comment about the context flags. (c2b01ef6d1) - Bug 1146875 - Fix the leak-gauge.html broken and add a encoding declaration. r=dbaron (8df2510774) - Bug 1132499 - part 1 - convert nsTextEditorState::mValue to use Maybe instead of heap allocation; r=ehsan (2644faebbb) - Bug 1132499 - part 2 - convert nsTextEditorState::mValue to be an nsString; r=ehsan (6e0df4d1dc) - Bug 409885 - Use SetHostPort in nsHTMLDocument::SetDomain. r=bz (2d289a79c5) - Bug 1269475 - Fix uninitialized variable warning. r=jdm (881fa29803) - Bug 1263935 - Expose native version of mapURIToAddonId via amIAddonPathService. r=mossop (04da9fe703) - Bug 1234974 - Handle null GetOwner() in |BluetoothAdapter::IsBluetoothCertifiedApp|, r=shuang (e4dde47d7f) - Bug 1241117 - Fix mAppUuid access before assign in BluetoothGatt::Connect. r=joliu (3920535f2a) - Bug 1238424 - Fix a missing header in Bluetooth module. r=brsun (438fd74375) - Bug 1267958: Only complain for negative size, not merely zero. r=jrmuizel (194bd2a754) - Bug 1320621 - Make sure --enable-system-hunspell picks up system headers. r=glandium (125c4ea215) - Bug 1266430: Support offsets in DrawTargetD2D1::CopySurface when using PartialUploading. r=jrmuizel (de8630b117) - Bug 1267363. Disable hinting on osx fonts only if we have expclity grayscale AA. r=mstange (c4c32fd7cc) - Bug 1134549 - Switch FlattenBezier from floats to doubles. r=bas (5753ab16a3) - Bug 1240437 part 2: Follow-up to fix implicit constrcutor static analysis failure. r=me (525d9d9a9f) - Bug 1256678 - Backout diagnostic patch rev 39c895b67af2 - r=me (f63698de77) - Bug 1256678 - Account for truncated font names in ScaledFontWin::GetFontFileData() - r=jfkthame (a6930e0a33) - Bug 1256678 - Re-add nightly-only crash if ScaledFontWin::GetFontFileData fails to find a matching TrueType collection font - r=jfkthame (8bec2d43a2) - Bug 1260350 - GFX: 2D: Use ConvolveHorizontally_LS3. r=jrmuizel (9d2f372593) - Bug 1260112 - GFX: 2D: Fix unaligned access in ConvolveVertically/Horizontally_LS3. r=huangwenjun06 (43ba8f7b05) - Bug 1260885 - Make SurfaceFormat::R5G6B5_UINT16 properly round-trip through SourceSurfaceCairo. r=lsalzman (bc8f0c0876) - Bug 1262415 - make Accessible to keep weak pointers to parent and children, r=yzen (c0b987fe10) - Bug 1267271 - skip empty surfaces in DrawTargetSkia::DrawSurfaceWithShadow. r=mchang (fd488c918a) - Bug 1249600. Lookup font and font family from font face when requesting SkTypeface. r=bas (0281313c33) - Bug 1268096. Sync the D3D11 rasterizer state if pointDrawMode or multisample changes. (25b2af8b26) - Bug 1203132 - Add an SVG for the B2G flow of touch events. r=botond (2ce3b0ddc4) - Bug 1180322. Add a document describing the history of layers (b3351dbba3) - Bug 1235223. Update history document. (212d356bd0) - Bug 1235223 - Fix typos in layers history document. (f19a5802d8) - Bug 1235223 - Fix another typo in the layers history document. (9663fe5447) - Bug 1265112 - Add support for NV_texture_barrier to GLContext. r=jrmuizel (f1f5fb1a3a) - Bug 1240730 - Initialize all GLLibraryEGL symbols in the ctor. r=mattwoodrow (dae8955458) - Bug 1240730 - Initialize all GLXLibrary members in the ctor. r=mattwoodrow (8218ed6fd9) - bug 1250485 - make the ctor for GLXLibrary constexpr r=jrmuizel (a571491f0a) - mitor spacing (0083550ab2) - Bug 1256492 - Cast to proper width to avoid C4312 on VS2015; r=jrmuizel (1bb2ed20d3) - Bug 1266878 - Fix off-by-one error in ParamTraits<StereoMode> - r=nical (f467d496b8) - Bug 1258758 - rename GetEffectiveClipRect to GetLocalClipRect. r=kats (897798948f) - Bug 1249936 - add a LayerComposite::GetShadowTransform method & simplify Layer::GetLocalTransform. r=botond (fe492a1327) - Bug 1269032 - Add support for user multipliers to pan gesture inputs. r=mstange (ea7698dca2) - Bug 1265510 - Add some scroll-snapping logging to APZC. r=botond (6f2369163a) - Bug 1268523 - Avoid leaking tasks when they are posted to a destroyed APZC instance. r=botond (70e1e63b7b) - Bug 1265510 - Ensure that new input blocks still allow APZCs with interrupted animations to scroll-snap. r=botond (01341b554b) - Bug 1269068 - Zero out the axis velocity once the wheel scroll animation is terminating. r=botond (9a9f384485) - Bug 1246056 - Ensure that the MockContentController's timestamp is always >= GetStartupTime(). r=botond (4fe53e1f24) - Bug 1256341 - Add a gtest to catch scenarios where a tap timeout is interrupted by a non-touch block. r=botond (21a15f5a5a) - Bug 1266833 - When the scroll position is clamped during a frame reconstruction, send a scroll offset update to APZ. r=tnikkel (c0acd70a3d) - Bug 1268517 - Remove unused function. r=botond (534e4d9bae) - Bug 1213095 - Fix APZEventState build with logging enabled. r=botond (ac7c1e9401) - Bug 1250954 - Correct the SharedSurfaceTextureClient when forwarder changed. r=jgilbert (0a389bc0fa) - Bug 1265873 - Use gfxSharedReadLock in TextureClientPool r=nical (e3ed936a8a) - Bug 1265468 - Update the compositor pointer on all TextureSources in the list when recycling in ImageHost. r=nical (78f29244bb) - Bug 1252237 - Remove the TextureHost shmem mapping failed assert. r=milan (d0b7230dff) - Bug 1265112 - When rendering blend modes with CompositorOGL, use NV_texture_barrier (if available) to sample directly from the framebuffer. r=jrmuizel (6f3ae237a5) - Bug 1268878 - Include various of gfxFontEntry's sub-objects in memory reporting. r=njn (b960415fa8) - Bug 1268951 - Reallocate sanitized user font data into an appropriately-sized block, to reduce ongoing RAM footprint. r=jrmuizel (a26e9dd632) - Bug 1123416 - Part 1: Make topsrcdir a valid Gradle project root. r=sebastian (77b0b35fc1) - Bug 1260672: Remove 'nsAutoPtr.h' and clean up includes of Gonk diskspace watcher, r=gsvelto (99c4c35e3d) - Bug 1167535 - Fix fanotify 4g size limit. r=fabrice (c62015e454) - Bug 1167817 - Switch back to printf_stderr in GonkDiskSpaceWatcher.cpp r=dhylands (110445f628) - Bug 1260672: Use |UniquePtr| for Gonk alarms, r=gsvelto (03678b9015) - Bug 1260672: Use |UniquePtr| for Gonk sensors, r=gsvelto (545ec3fc70) - Bug 1263845. When a parent changes from auto height to non-auto height or vice versa, a percentage height non-block child needs to realize it's doing a vertical resize. r=dbaron (05db492bc8) - Bug 1268009 - If APZ is force-disabled, disable paint skipping even for apz-originated scrolls. r=kats (c02f8755cd) - Bug 1267555 part 1 - [css-grid] Make grid-aligned abs.pos. descendants that span from 'auto' to the first/last line stretch to the outer edge of the first/last track respectively. r=dholbert (88f6261043) - Bug 1267555 part 2 - [css-grid] Adjust reftests for abs.pos. "auto/first-line" and "last-line/auto" change. (43d03ab15b)
This commit is contained in:
@@ -94,8 +94,7 @@ using namespace mozilla::a11y;
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Accessible: nsISupports and cycle collection
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION(Accessible,
|
||||
mContent, mParent, mChildren)
|
||||
NS_IMPL_CYCLE_COLLECTION(Accessible, mContent)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Accessible)
|
||||
if (aIID.Equals(NS_GET_IID(Accessible)))
|
||||
@@ -1979,7 +1978,7 @@ Accessible::BindToParent(Accessible* aParent, uint32_t aIndexInParent)
|
||||
#ifdef A11Y_LOG
|
||||
if (mParent) {
|
||||
logging::TreeInfo("BindToParent: stealing accessible", 0,
|
||||
"old parent", mParent.get(),
|
||||
"old parent", mParent,
|
||||
"new parent", aParent,
|
||||
"child", this, nullptr);
|
||||
}
|
||||
|
||||
@@ -1094,8 +1094,8 @@ protected:
|
||||
nsCOMPtr<nsIContent> mContent;
|
||||
DocAccessible* mDoc;
|
||||
|
||||
RefPtr<Accessible> mParent;
|
||||
nsTArray<RefPtr<Accessible> > mChildren;
|
||||
Accessible* mParent;
|
||||
nsTArray<Accessible*> mChildren;
|
||||
int32_t mIndexInParent;
|
||||
|
||||
static const uint8_t kStateFlagsBits = 13;
|
||||
|
||||
@@ -99,7 +99,7 @@ private:
|
||||
|
||||
if (parent && parent->IsListControl()) {
|
||||
Accessible* combobox = parent->Parent();
|
||||
return combobox && combobox->IsCombobox() ? combobox : mParent.get();
|
||||
return combobox && combobox->IsCombobox() ? combobox : mParent;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
|
||||
@@ -911,8 +911,25 @@ nsFrameLoader::SwapWithOtherRemoteLoader(nsFrameLoader* aOther,
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
if (mRemoteBrowser->OriginAttributesRef() !=
|
||||
aOther->mRemoteBrowser->OriginAttributesRef()) {
|
||||
// When we swap docShells, maybe we have to deal with a new page created just
|
||||
// for this operation. In this case, the browser code should already have set
|
||||
// the correct userContextId attribute value in the owning XULElement, but our
|
||||
// docShell, that has been created way before) doesn't know that that
|
||||
// happened.
|
||||
// This is the reason why now we must retrieve the correct value from the
|
||||
// usercontextid attribute before comparing our originAttributes with the
|
||||
// other one.
|
||||
OriginAttributes ourOriginAttributes =
|
||||
mRemoteBrowser->OriginAttributesRef();
|
||||
rv = PopulateUserContextIdFromAttribute(ourOriginAttributes);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
OriginAttributes otherOriginAttributes =
|
||||
aOther->mRemoteBrowser->OriginAttributesRef();
|
||||
rv = aOther->PopulateUserContextIdFromAttribute(otherOriginAttributes);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
if (ourOriginAttributes != otherOriginAttributes) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
@@ -1293,8 +1310,25 @@ nsFrameLoader::SwapWithOtherLoader(nsFrameLoader* aOther,
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
if (ourDocshell->GetOriginAttributes() !=
|
||||
otherDocshell->GetOriginAttributes()) {
|
||||
// When we swap docShells, maybe we have to deal with a new page created just
|
||||
// for this operation. In this case, the browser code should already have set
|
||||
// the correct userContextId attribute value in the owning XULElement, but our
|
||||
// docShell, that has been created way before) doesn't know that that
|
||||
// happened.
|
||||
// This is the reason why now we must retrieve the correct value from the
|
||||
// usercontextid attribute before comparing our originAttributes with the
|
||||
// other one.
|
||||
OriginAttributes ourOriginAttributes =
|
||||
ourDocshell->GetOriginAttributes();
|
||||
rv = PopulateUserContextIdFromAttribute(ourOriginAttributes);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
OriginAttributes otherOriginAttributes =
|
||||
otherDocshell->GetOriginAttributes();
|
||||
rv = aOther->PopulateUserContextIdFromAttribute(otherOriginAttributes);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
if (ourOriginAttributes != otherOriginAttributes) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
@@ -3174,3 +3208,24 @@ nsFrameLoader::GetNewTabContext(MutableTabContext* aTabContext,
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsFrameLoader::PopulateUserContextIdFromAttribute(OriginAttributes& aAttr)
|
||||
{
|
||||
if (aAttr.mUserContextId ==
|
||||
nsIScriptSecurityManager::DEFAULT_USER_CONTEXT_ID) {
|
||||
// Grab the userContextId from owner if XUL
|
||||
nsAutoString userContextIdStr;
|
||||
int32_t namespaceID = mOwnerContent->GetNameSpaceID();
|
||||
if ((namespaceID == kNameSpaceID_XUL) &&
|
||||
mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::usercontextid,
|
||||
userContextIdStr) &&
|
||||
!userContextIdStr.IsEmpty()) {
|
||||
nsresult rv;
|
||||
aAttr.mUserContextId = userContextIdStr.ToInteger(&rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@@ -326,6 +326,9 @@ private:
|
||||
};
|
||||
void MaybeUpdatePrimaryTabParent(TabParentChange aChange);
|
||||
|
||||
nsresult
|
||||
PopulateUserContextIdFromAttribute(mozilla::OriginAttributes& aAttr);
|
||||
|
||||
nsCOMPtr<nsIDocShell> mDocShell;
|
||||
nsCOMPtr<nsIURI> mURIToLoad;
|
||||
mozilla::dom::Element* mOwnerContent; // WEAK
|
||||
|
||||
@@ -14,7 +14,7 @@ function createTestPage(aHead, aImgPolicy, aName) {
|
||||
<html>'+
|
||||
aHead +
|
||||
'<body>\n\
|
||||
<img src="' + _createTestUrl('img') + '" referrer="' + aImgPolicy + '" id="image"></img>\n\
|
||||
<img src="' + _createTestUrl('img') + '" referrerpolicy="' + aImgPolicy + '" id="image"></img>\n\
|
||||
<script>' +
|
||||
|
||||
// LOAD EVENT (of the test)
|
||||
@@ -52,9 +52,9 @@ function createTest3(aImgPolicy1, aImgPolicy2, aImgPolicy3, aName) {
|
||||
return '<!DOCTYPE HTML>\n\
|
||||
<html>\n\
|
||||
<body>\n\
|
||||
<img src="' + createTestUrl(aImgPolicy1, 'test', aName + aImgPolicy1) + '" referrer="' + aImgPolicy1 + '" id="image"></img>\n\
|
||||
<img src="' + createTestUrl(aImgPolicy2, 'test', aName + aImgPolicy2) + '" referrer="' + aImgPolicy2 + '" id="image"></img>\n\
|
||||
<img src="' + createTestUrl(aImgPolicy3, 'test', aName + aImgPolicy3) + '" referrer="' + aImgPolicy3 + '" id="image"></img>\n\
|
||||
<img src="' + createTestUrl(aImgPolicy1, 'test', aName + aImgPolicy1) + '" referrerpolicy="' + aImgPolicy1 + '" id="image"></img>\n\
|
||||
<img src="' + createTestUrl(aImgPolicy2, 'test', aName + aImgPolicy2) + '" referrerpolicy="' + aImgPolicy2 + '" id="image"></img>\n\
|
||||
<img src="' + createTestUrl(aImgPolicy3, 'test', aName + aImgPolicy3) + '" referrerpolicy="' + aImgPolicy3 + '" id="image"></img>\n\
|
||||
<script>\n\
|
||||
var _numLoads = 0;' +
|
||||
|
||||
|
||||
@@ -23,7 +23,8 @@ window.addEventListener("message", function(event) {
|
||||
* to do checkIndividualResults and resetState
|
||||
*/
|
||||
function doXHR(aUrl, onSuccess, onFail) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
// The server is at http[s]://example.com so we need cross-origin XHR.
|
||||
var xhr = new XMLHttpRequest({mozSystem: true});
|
||||
xhr.responseType = "json";
|
||||
xhr.onload = function () {
|
||||
onSuccess(xhr);
|
||||
@@ -31,7 +32,7 @@ function doXHR(aUrl, onSuccess, onFail) {
|
||||
xhr.onerror = function () {
|
||||
onFail(xhr);
|
||||
};
|
||||
xhr.open('GET', aUrl, true);
|
||||
xhr.open('GET', "http" + aUrl, true);
|
||||
xhr.send(null);
|
||||
}
|
||||
|
||||
@@ -69,6 +70,8 @@ var tests = (function() {
|
||||
|
||||
// enable referrer attribute
|
||||
yield SpecialPowers.pushPrefEnv({"set": [['network.http.enablePerElementReferrer', true]]}, advance);
|
||||
yield SpecialPowers.pushPrefEnv({"set": [['security.mixed_content.block_active_content', false]]}, advance);
|
||||
yield SpecialPowers.pushPermissions([{'type': 'systemXHR', 'allow': true, 'context': document}], advance);
|
||||
|
||||
var iframe = document.getElementById("testframe");
|
||||
|
||||
@@ -87,7 +90,8 @@ var tests = (function() {
|
||||
searchParams.append(l, tests[i][l]);
|
||||
}
|
||||
}
|
||||
yield iframe.src = SJS + searchParams.toString();
|
||||
var schemeFrom = tests[i].SCHEME_FROM || "http";
|
||||
yield iframe.src = schemeFrom + SJS + searchParams.toString();
|
||||
yield checkIndividualResults(tests[i].DESC, tests[i].RESULT, tests[i].NAME);
|
||||
};
|
||||
};
|
||||
|
||||
@@ -16,35 +16,39 @@ const IMG_BYTES = atob(
|
||||
"iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12" +
|
||||
"P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==");
|
||||
|
||||
function createTestUrl(aPolicy, aAction, aName, aType) {
|
||||
return "http://" + BASE_URL +
|
||||
function createTestUrl(aPolicy, aAction, aName, aType, aSchemeFrom, aSchemeTo) {
|
||||
var schemeTo = aSchemeTo || "http";
|
||||
var schemeFrom = aSchemeFrom || "http";
|
||||
return schemeTo + "://" + BASE_URL +
|
||||
"ACTION=" + aAction + "&" +
|
||||
"policy=" + aPolicy + "&" +
|
||||
"NAME=" + aName + "&" +
|
||||
"type=" + aType;
|
||||
"type=" + aType + "&" +
|
||||
"SCHEME_FROM=" + schemeFrom;
|
||||
}
|
||||
|
||||
// test page using iframe referrer attribute
|
||||
// if aParams are set this creates a test where the iframe url is a redirect
|
||||
function createIframeTestPageUsingRefferer(aMetaPolicy, aAttributePolicy, aNewAttributePolicy, aName, aParams, aChangingMethod) {
|
||||
function createIframeTestPageUsingRefferer(aMetaPolicy, aAttributePolicy, aNewAttributePolicy, aName, aParams,
|
||||
aSchemeFrom, aSchemeTo, aChangingMethod) {
|
||||
var metaString = "";
|
||||
if (aMetaPolicy) {
|
||||
metaString = `<meta name="referrer" content="${aMetaPolicy}">`;
|
||||
}
|
||||
var changeString = "";
|
||||
if (aChangingMethod === "setAttribute") {
|
||||
changeString = `document.getElementById("myframe").setAttribute("referrer", "${aNewAttributePolicy}")`;
|
||||
changeString = `document.getElementById("myframe").setAttribute("referrerpolicy", "${aNewAttributePolicy}")`;
|
||||
} else if (aChangingMethod === "property") {
|
||||
changeString = `document.getElementById("myframe").referrer = "${aNewAttributePolicy}"`;
|
||||
changeString = `document.getElementById("myframe").referrerPolicy = "${aNewAttributePolicy}"`;
|
||||
}
|
||||
var iFrameString = `<iframe src="" id="myframe" ${aAttributePolicy ? ` referrer="${aAttributePolicy}"` : ""}>iframe</iframe>`;
|
||||
var iFrameString = `<iframe src="" id="myframe" ${aAttributePolicy ? ` referrerpolicy="${aAttributePolicy}"` : ""}>iframe</iframe>`;
|
||||
var iframeUrl = "";
|
||||
if (aParams) {
|
||||
aParams.delete("ACTION");
|
||||
aParams.append("ACTION", "redirectIframe");
|
||||
iframeUrl = "http://" + CROSS_ORIGIN + aParams.toString();
|
||||
} else {
|
||||
iframeUrl = createTestUrl(aAttributePolicy, "test", aName, "iframe");
|
||||
iframeUrl = createTestUrl(aAttributePolicy, "test", aName, "iframe", aSchemeFrom, aSchemeTo);
|
||||
}
|
||||
|
||||
return `<!DOCTYPE HTML>
|
||||
@@ -67,20 +71,20 @@ function createIframeTestPageUsingRefferer(aMetaPolicy, aAttributePolicy, aNewAt
|
||||
</html>`;
|
||||
}
|
||||
|
||||
function buildAnchorString(aMetaPolicy, aReferrerPolicy, aName, aRelString){
|
||||
function buildAnchorString(aMetaPolicy, aReferrerPolicy, aName, aRelString, aSchemeFrom, aSchemeTo){
|
||||
if (aReferrerPolicy) {
|
||||
return `<a href="${createTestUrl(aReferrerPolicy, 'test', aName, 'link')}" referrer="${aReferrerPolicy}" id="link" ${aRelString}>${aReferrerPolicy}</a>`;
|
||||
return `<a href="${createTestUrl(aReferrerPolicy, 'test', aName, 'link', aSchemeFrom, aSchemeTo)}" referrerpolicy="${aReferrerPolicy}" id="link" ${aRelString}>${aReferrerPolicy}</a>`;
|
||||
}
|
||||
return `<a href="${createTestUrl(aMetaPolicy, 'test', aName, 'link')}" id="link" ${aRelString}>link</a>`;
|
||||
return `<a href="${createTestUrl(aMetaPolicy, 'test', aName, 'link', aSchemeFrom, aSchemeTo)}" id="link" ${aRelString}>link</a>`;
|
||||
}
|
||||
|
||||
function buildAreaString(aMetaPolicy, aReferrerPolicy, aName, aRelString){
|
||||
function buildAreaString(aMetaPolicy, aReferrerPolicy, aName, aRelString, aSchemeFrom, aSchemeTo){
|
||||
var result = `<img src="file_mozfiledataurl_img.jpg" alt="image" usemap="#imageMap">`;
|
||||
result += `<map name="imageMap">`;
|
||||
if (aReferrerPolicy) {
|
||||
result += `<area shape="circle" coords="1,1,1" href="${createTestUrl(aReferrerPolicy, 'test', aName, 'link')}" alt="theArea" referrer="${aReferrerPolicy}" id="link" ${aRelString}>`;
|
||||
result += `<area shape="circle" coords="1,1,1" href="${createTestUrl(aReferrerPolicy, 'test', aName, 'link', aSchemeFrom, aSchemeTo)}" alt="theArea" referrerpolicy="${aReferrerPolicy}" id="link" ${aRelString}>`;
|
||||
} else {
|
||||
result += `<area shape="circle" coords="1,1,1" href="${createTestUrl(aMetaPolicy, 'test', aName, 'link')}" alt="theArea" id="link" ${aRelString}>`;
|
||||
result += `<area shape="circle" coords="1,1,1" href="${createTestUrl(aMetaPolicy, 'test', aName, 'link', aSchemeFrom, aSchemeTo)}" alt="theArea" id="link" ${aRelString}>`;
|
||||
}
|
||||
result += `</map>`;
|
||||
|
||||
@@ -88,22 +92,22 @@ function buildAreaString(aMetaPolicy, aReferrerPolicy, aName, aRelString){
|
||||
}
|
||||
|
||||
// test page using anchor or area referrer attribute
|
||||
function createAETestPageUsingRefferer(aMetaPolicy, aAttributePolicy, aNewAttributePolicy, aName, aRel, aStringBuilder, aChangingMethod) {
|
||||
function createAETestPageUsingRefferer(aMetaPolicy, aAttributePolicy, aNewAttributePolicy, aName, aRel, aStringBuilder, aSchemeFrom, aSchemeTo, aChangingMethod) {
|
||||
var metaString = "";
|
||||
if (aMetaPolicy) {
|
||||
metaString = `<head><meta name="referrer" content="${aMetaPolicy}"></head>`;
|
||||
}
|
||||
var changeString = "";
|
||||
if (aChangingMethod === "setAttribute") {
|
||||
changeString = `document.getElementById("link").setAttribute("referrer", "${aNewAttributePolicy}")`;
|
||||
changeString = `document.getElementById("link").setAttribute("referrerpolicy", "${aNewAttributePolicy}")`;
|
||||
} else if (aChangingMethod === "property") {
|
||||
changeString = `document.getElementById("link").referrer = "${aNewAttributePolicy}"`;
|
||||
changeString = `document.getElementById("link").referrerPolicy = "${aNewAttributePolicy}"`;
|
||||
}
|
||||
var relString = "";
|
||||
if (aRel) {
|
||||
relString = `rel="noreferrer"`;
|
||||
}
|
||||
var elementString = aStringBuilder(aMetaPolicy, aAttributePolicy, aName, relString);
|
||||
var elementString = aStringBuilder(aMetaPolicy, aAttributePolicy, aName, relString, aSchemeFrom, aSchemeTo);
|
||||
|
||||
return `<!DOCTYPE HTML>
|
||||
<html>
|
||||
@@ -138,7 +142,7 @@ function createRedirectImgTestCase(aParams, aAttributePolicy) {
|
||||
<title>Test referrer policies on redirect (img)</title>
|
||||
</head>
|
||||
<body>
|
||||
<img id="testImg" src="${imgUrl}" ${aAttributePolicy ? ` referrer="${aAttributePolicy}"` : ""}>
|
||||
<img id="testImg" src="${imgUrl}" ${aAttributePolicy ? ` referrerpolicy="${aAttributePolicy}"` : ""}>
|
||||
<script>
|
||||
window.addEventListener("load", function() {
|
||||
parent.postMessage("childLoadComplete", "http://mochi.test:8888");
|
||||
@@ -151,6 +155,8 @@ function createRedirectImgTestCase(aParams, aAttributePolicy) {
|
||||
function handleRequest(request, response) {
|
||||
var params = new URLSearchParams(request.queryString);
|
||||
var action = params.get("ACTION");
|
||||
var schemeFrom = params.get("SCHEME_FROM") || "http";
|
||||
var schemeTo = params.get("SCHEME_TO") || "http";
|
||||
|
||||
if (action === "resetState") {
|
||||
setSharedState(SHARED_KEY, "{}");
|
||||
@@ -201,7 +207,7 @@ function handleRequest(request, response) {
|
||||
var referrer = request.getHeader("Referer");
|
||||
if (referrer.indexOf("referrer_testserver") > 0) {
|
||||
referrerLevel = "full";
|
||||
} else if (referrer.indexOf("http://mochi.test:8888") == 0) {
|
||||
} else if (referrer.indexOf(schemeFrom + "://example.com") == 0) {
|
||||
referrerLevel = "origin";
|
||||
} else {
|
||||
// this is never supposed to happen
|
||||
@@ -250,8 +256,8 @@ function handleRequest(request, response) {
|
||||
|
||||
// anchor & area
|
||||
var _getPage = createAETestPageUsingRefferer.bind(null, metaPolicy, attributePolicy, newAttributePolicy, name, rel);
|
||||
var _getAnchorPage = _getPage.bind(null, buildAnchorString);
|
||||
var _getAreaPage = _getPage.bind(null, buildAreaString);
|
||||
var _getAnchorPage = _getPage.bind(null, buildAnchorString, schemeFrom, schemeTo);
|
||||
var _getAreaPage = _getPage.bind(null, buildAreaString, schemeFrom, schemeTo);
|
||||
|
||||
// aMetaPolicy, aAttributePolicy, aNewAttributePolicy, aName, aChangingMethod, aStringBuilder
|
||||
if (action === "generate-anchor-policy-test") {
|
||||
@@ -280,7 +286,8 @@ function handleRequest(request, response) {
|
||||
}
|
||||
|
||||
// iframe
|
||||
_getPage = createIframeTestPageUsingRefferer.bind(null, metaPolicy, attributePolicy, newAttributePolicy, name, "");
|
||||
_getPage = createIframeTestPageUsingRefferer.bind(null, metaPolicy, attributePolicy, newAttributePolicy, name, "",
|
||||
schemeFrom, schemeTo);
|
||||
|
||||
// aMetaPolicy, aAttributePolicy, aNewAttributePolicy, aName, aChangingMethod
|
||||
if (action === "generate-iframe-policy-test") {
|
||||
@@ -302,7 +309,8 @@ function handleRequest(request, response) {
|
||||
return;
|
||||
}
|
||||
if (action === "generate-iframe-redirect-policy-test") {
|
||||
response.write(createIframeTestPageUsingRefferer(metaPolicy, attributePolicy, newAttributePolicy, name, params));
|
||||
response.write(createIframeTestPageUsingRefferer(metaPolicy, attributePolicy, newAttributePolicy, name, params,
|
||||
schemeFrom, schemeTo));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
|
||||
<script type="application/javascript;version=1.8">
|
||||
|
||||
const SJS = "/tests/dom/base/test/referrer_testserver.sjs?";
|
||||
const PARAMS = ["ATTRIBUTE_POLICY", "NEW_ATTRIBUTE_POLICY", "META_POLICY", "REL"];
|
||||
const SJS = "://example.com/tests/dom/base/test/referrer_testserver.sjs?";
|
||||
const PARAMS = ["ATTRIBUTE_POLICY", "NEW_ATTRIBUTE_POLICY", "META_POLICY", "REL", "SCHEME_FROM", "SCHEME_TO"];
|
||||
|
||||
const testCases = [
|
||||
{ACTION: ["generate-anchor-policy-test", "generate-area-policy-test"],
|
||||
@@ -39,6 +39,28 @@
|
||||
META_POLICY: 'no-referrer',
|
||||
DESC: "no-referrer in meta",
|
||||
RESULT: 'none'},
|
||||
|
||||
// Test if element attr would override meta referr policy.
|
||||
|
||||
// 1. Downgrade.
|
||||
{ATTRIBUTE_POLICY: 'no-referrer-when-downgrade',
|
||||
NAME: 'origin-in-meta-downgrade-in-attr',
|
||||
META_POLICY: 'origin',
|
||||
DESC: 'origin in meta downgrade in attr',
|
||||
SCHEME_FROM: 'https',
|
||||
SCHEME_TO: 'http',
|
||||
RESULT: 'none'},
|
||||
|
||||
// 2. No downgrade.
|
||||
{ATTRIBUTE_POLICY: 'no-referrer-when-downgrade',
|
||||
NAME: 'origin-in-meta-downgrade-in-attr',
|
||||
META_POLICY: 'origin',
|
||||
DESC: 'origin in meta downgrade in attr',
|
||||
SCHEME_FROM: 'https',
|
||||
SCHEME_TO: 'https',
|
||||
RESULT: 'full'},
|
||||
// End of element attr overriding test..
|
||||
|
||||
{ATTRIBUTE_POLICY: 'origin',
|
||||
NAME: 'origin-with-no-meta',
|
||||
META_POLICY: '',
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
<script type="application/javascript;version=1.8">
|
||||
|
||||
const SJS = "/tests/dom/base/test/referrer_testserver.sjs?";
|
||||
const SJS = "://example.com/tests/dom/base/test/referrer_testserver.sjs?";
|
||||
const PARAMS = ["ATTRIBUTE_POLICY", "NEW_ATTRIBUTE_POLICY", "META_POLICY", "REL"];
|
||||
|
||||
const testCases = [
|
||||
|
||||
@@ -14,19 +14,24 @@
|
||||
|
||||
<script type="application/javascript;version=1.8">
|
||||
|
||||
const SJS = "/tests/dom/base/test/referrer_testserver.sjs?";
|
||||
const PARAMS = ["ATTRIBUTE_POLICY", "NEW_ATTRIBUTE_POLICY", "META_POLICY", "REL"];
|
||||
const SJS = "://example.com/tests/dom/base/test/referrer_testserver.sjs?";
|
||||
const PARAMS = ["ATTRIBUTE_POLICY", "NEW_ATTRIBUTE_POLICY", "META_POLICY", "REL", , "SCHEME_FROM", "SCHEME_TO"];
|
||||
|
||||
const testCases = [
|
||||
{ACTION: ["generate-anchor-policy-test", "generate-area-policy-test"],
|
||||
TESTS: [
|
||||
// setting invalid refer values -> we expect either full referrer (default)
|
||||
// or whatever is specified in the meta referrer policy
|
||||
|
||||
// Note that for those test cases which require cross-origin test, we use different
|
||||
// scheme to result in cross-origin request.
|
||||
{ATTRIBUTE_POLICY: 'origin-when-cross-origin',
|
||||
NAME: 'origin-when-cross-origin-with-no-meta',
|
||||
META_POLICY: '',
|
||||
SCHEME_FROM: 'https',
|
||||
SCHEME_TO: 'http',
|
||||
DESC: "origin-when-cross-origin (anchor) with no meta",
|
||||
RESULT: 'full'},
|
||||
RESULT: 'origin'},
|
||||
{ATTRIBUTE_POLICY: 'default',
|
||||
NAME: 'default-with-no-meta',
|
||||
META_POLICY: '',
|
||||
@@ -40,16 +45,22 @@
|
||||
{ATTRIBUTE_POLICY: 'origin-when-cross-origin',
|
||||
NAME: 'origin-when-cross-origin-with-no-referrer-in-meta',
|
||||
META_POLICY: 'no-referrer',
|
||||
SCHEME_FROM: 'https',
|
||||
SCHEME_TO: 'http',
|
||||
DESC: "origin-when-cross-origin (anchor) with no-referrer in meta",
|
||||
RESULT: 'none'},
|
||||
RESULT: 'origin'},
|
||||
{ATTRIBUTE_POLICY: 'origin-when-cross-origin',
|
||||
NAME: 'origin-when-cross-origin-with-unsafe-url-in-meta',
|
||||
META_POLICY: 'unsafe-url',
|
||||
SCHEME_FROM: 'https',
|
||||
SCHEME_TO: 'http',
|
||||
DESC: "origin-when-cross-origin (anchor) with unsafe-url in meta",
|
||||
RESULT: 'full'},
|
||||
RESULT: 'origin'},
|
||||
{ATTRIBUTE_POLICY: 'origin-when-cross-origin',
|
||||
NAME: 'origin-when-cross-origin-with-origin-in-meta',
|
||||
META_POLICY: 'origin',
|
||||
SCHEME_FROM: 'https',
|
||||
SCHEME_TO: 'http',
|
||||
DESC: "origin-when-cross-origin (anchor) with origin in meta",
|
||||
RESULT: 'origin'}]}
|
||||
];
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
<script type="application/javascript;version=1.8">
|
||||
|
||||
const SJS = "/tests/dom/base/test/referrer_testserver.sjs?";
|
||||
const SJS = "://example.com/tests/dom/base/test/referrer_testserver.sjs?";
|
||||
const PARAMS = ["ATTRIBUTE_POLICY", "NEW_ATTRIBUTE_POLICY", "META_POLICY", "REL"];
|
||||
|
||||
const testCases = [
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
const SJS = "/tests/dom/base/test/referrer_testserver.sjs?";
|
||||
const SJS = "://example.com/tests/dom/base/test/referrer_testserver.sjs?";
|
||||
const PARAMS = ["ATTRIBUTE_POLICY", "NEW_ATTRIBUTE_POLICY", "META_POLICY"];
|
||||
|
||||
const testCases = [
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
const SJS = "/tests/dom/base/test/referrer_testserver.sjs?";
|
||||
const SJS = "://example.com/tests/dom/base/test/referrer_testserver.sjs?";
|
||||
const PARAMS = ["ATTRIBUTE_POLICY", "NEW_ATTRIBUTE_POLICY", "META_POLICY"];
|
||||
|
||||
const testCases = [
|
||||
|
||||
@@ -14,19 +14,24 @@
|
||||
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
const SJS = "/tests/dom/base/test/referrer_testserver.sjs?";
|
||||
const PARAMS = ["ATTRIBUTE_POLICY", "NEW_ATTRIBUTE_POLICY", "META_POLICY"];
|
||||
const SJS = "://example.com/tests/dom/base/test/referrer_testserver.sjs?";
|
||||
const PARAMS = ["ATTRIBUTE_POLICY", "NEW_ATTRIBUTE_POLICY", "META_POLICY", "SCHEME_FROM", "SCHEME_TO"];
|
||||
|
||||
const testCases = [
|
||||
{ACTION: ["generate-iframe-policy-test"],
|
||||
TESTS: [
|
||||
// setting invalid refer values -> we expect either full referrer (default)
|
||||
// or whatever is specified in the meta referrer policy
|
||||
|
||||
// Note that for those test cases which require cross-origin test, we use different
|
||||
// scheme to result in cross-origin request.
|
||||
{ATTRIBUTE_POLICY: 'origin-when-cross-origin',
|
||||
NAME: 'origin-when-cross-origin-with-no-meta',
|
||||
META_POLICY: '',
|
||||
DESC: "origin-when-cross-origin (iframe) with no meta",
|
||||
RESULT: 'full'},
|
||||
SCHEME_FROM: 'https',
|
||||
SCHEME_TO: 'http',
|
||||
RESULT: 'origin'},
|
||||
{ATTRIBUTE_POLICY: 'default',
|
||||
NAME: 'default-with-no-meta',
|
||||
META_POLICY: '',
|
||||
@@ -41,16 +46,22 @@
|
||||
NAME: 'origin-when-cross-origin-with-no-referrer-in-meta',
|
||||
META_POLICY: 'no-referrer',
|
||||
DESC: "origin-when-cross-origin (iframe) with no-referrer in meta",
|
||||
RESULT: 'none'},
|
||||
SCHEME_FROM: 'https',
|
||||
SCHEME_TO: 'http',
|
||||
RESULT: 'origin'},
|
||||
{ATTRIBUTE_POLICY: 'origin-when-cross-origin',
|
||||
NAME: 'origin-when-cross-origin-with-unsafe-url-in-meta',
|
||||
META_POLICY: 'unsafe-url',
|
||||
DESC: "origin-when-cross-origin (iframe) with unsafe-url in meta",
|
||||
RESULT: 'full'},
|
||||
SCHEME_FROM: 'https',
|
||||
SCHEME_TO: 'http',
|
||||
RESULT: 'origin'},
|
||||
{ATTRIBUTE_POLICY: 'origin-when-cross-origin',
|
||||
NAME: 'origin-when-cross-origin-with-origin-in-meta',
|
||||
META_POLICY: 'origin',
|
||||
DESC: "origin-when-cross-origin (iframe) with origin in meta",
|
||||
SCHEME_FROM: 'https',
|
||||
SCHEME_TO: 'http',
|
||||
RESULT: 'origin'},
|
||||
{NAME: 'origin-in-meta',
|
||||
META_POLICY: 'origin',
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
<script type="application/javascript;version=1.8">
|
||||
|
||||
const SJS = "/tests/dom/base/test/referrer_testserver.sjs?";
|
||||
const SJS = "://example.com/tests/dom/base/test/referrer_testserver.sjs?";
|
||||
const PARAMS = ["ATTRIBUTE_POLICY", "NEW_ATTRIBUTE_POLICY", "META_POLICY"];
|
||||
|
||||
const testCases = [
|
||||
|
||||
@@ -1059,6 +1059,8 @@ BluetoothAdapter::IsAdapterAttributeChanged(BluetoothAdapterAttribute aType,
|
||||
bool
|
||||
BluetoothAdapter::IsBluetoothCertifiedApp()
|
||||
{
|
||||
NS_ENSURE_TRUE(GetOwner(), false);
|
||||
|
||||
// Retrieve the app status and origin for permission checking
|
||||
nsCOMPtr<nsIDocument> doc = GetOwner()->GetExtantDoc();
|
||||
NS_ENSURE_TRUE(doc, false);
|
||||
|
||||
@@ -112,11 +112,6 @@ BluetoothGatt::Connect(ErrorResult& aRv)
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
BT_ENSURE_TRUE_REJECT(bs, promise, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
BluetoothUuid appUuid;
|
||||
BT_ENSURE_TRUE_REJECT(NS_SUCCEEDED(StringToUuid(mAppUuid, appUuid)),
|
||||
promise,
|
||||
NS_ERROR_DOM_OPERATION_ERR);
|
||||
|
||||
BluetoothAddress deviceAddr;
|
||||
BT_ENSURE_TRUE_REJECT(
|
||||
NS_SUCCEEDED(StringToAddress(mDeviceAddr, deviceAddr)),
|
||||
@@ -131,6 +126,11 @@ BluetoothGatt::Connect(ErrorResult& aRv)
|
||||
RegisterBluetoothSignalHandler(mAppUuid, this);
|
||||
}
|
||||
|
||||
BluetoothUuid appUuid;
|
||||
BT_ENSURE_TRUE_REJECT(NS_SUCCEEDED(StringToUuid(mAppUuid, appUuid)),
|
||||
promise,
|
||||
NS_ERROR_DOM_OPERATION_ERR);
|
||||
|
||||
UpdateConnectionState(BluetoothConnectionState::Connecting);
|
||||
bs->ConnectGattClientInternal(
|
||||
appUuid, deviceAddr, new BluetoothVoidReplyRunnable(nullptr, promise));
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#define mozilla_dom_bluetooth_bluetoothpbaprequesthandle_h
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "mozilla/dom/bluetooth/BluetoothCommon.h"
|
||||
#include "mozilla/dom/DOMRequest.h"
|
||||
#include "mozilla/dom/BlobSet.h"
|
||||
|
||||
|
||||
Vendored
@@ -1,73 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=965421
|
||||
-->
|
||||
<head>
|
||||
<title>Bug 965421 - Test camera hardware API for Auto focus moving Callback</title>
|
||||
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="camera_common.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=965421">Mozilla Bug 965421</a>
|
||||
<video id="viewfinder" width = "200" height = "200" autoplay></video>
|
||||
<img src="#" alt="This image is going to load" id="testimage"/>
|
||||
|
||||
<script class="testbody" type="text/javascript;version=1.7">
|
||||
|
||||
var suite = new CameraTestSuite();
|
||||
|
||||
suite.test('auto-focus-moving', function() {
|
||||
function triggerAutoFocusMoving(p) {
|
||||
var sync = new Promise(function(resolve, reject) {
|
||||
function onEvent(e) {
|
||||
suite.camera.removeEventListener('focus', onEvent);
|
||||
ok(e.newState === 'focusing', 'autofocus event state focusing == ' + e.newState);
|
||||
resolve();
|
||||
}
|
||||
suite.camera.addEventListener('focus', onEvent);
|
||||
});
|
||||
|
||||
suite.hw.fireAutoFocusMoving(true);
|
||||
return sync;
|
||||
}
|
||||
|
||||
function waitAutoFocusComplete(p) {
|
||||
var sync = new Promise(function(resolve, reject) {
|
||||
function onEvent(e) {
|
||||
suite.camera.removeEventListener('focus', onEvent);
|
||||
ok(e.newState === 'focused', 'autofocus event state focused == ' + e.newState);
|
||||
resolve();
|
||||
}
|
||||
suite.camera.addEventListener('focus', onEvent);
|
||||
});
|
||||
|
||||
// Missing the fireAutoFocusComplete but it should timeout on its own
|
||||
suite.hw.fireAutoFocusMoving(false);
|
||||
return sync;
|
||||
}
|
||||
|
||||
function runAutoFocusCycle(p) {
|
||||
return triggerAutoFocusMoving(p)
|
||||
.then(waitAutoFocusComplete);
|
||||
}
|
||||
|
||||
/* If the driver doesn't supply an onAutoFocusComplete notification,
|
||||
gecko will timeout and provide it. After three times, it will no
|
||||
longer rely upon a timeout and fire it immediately. */
|
||||
return suite.getCamera()
|
||||
.then(runAutoFocusCycle)
|
||||
.then(runAutoFocusCycle)
|
||||
.then(runAutoFocusCycle)
|
||||
.then(runAutoFocusCycle);
|
||||
});
|
||||
|
||||
suite.setup()
|
||||
.then(suite.run);
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -872,6 +872,35 @@ private:
|
||||
CanvasRenderingContext2D *mContext;
|
||||
};
|
||||
|
||||
class CanvasFilterChainObserver : public nsSVGFilterChainObserver
|
||||
{
|
||||
public:
|
||||
CanvasFilterChainObserver(nsTArray<nsStyleFilter>& aFilters,
|
||||
Element* aCanvasElement,
|
||||
CanvasRenderingContext2D* aContext)
|
||||
: nsSVGFilterChainObserver(aFilters, aCanvasElement)
|
||||
, mContext(aContext)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void DoUpdate() override
|
||||
{
|
||||
if (!mContext) {
|
||||
MOZ_CRASH("This should never be called without a context");
|
||||
}
|
||||
// Refresh the cached FilterDescription in mContext->CurrentState().filter.
|
||||
// If this filter is not at the top of the state stack, we'll refresh the
|
||||
// wrong filter, but that's ok, because we'll refresh the right filter
|
||||
// when we pop the state stack in CanvasRenderingContext2D::Restore().
|
||||
mContext->UpdateFilter();
|
||||
}
|
||||
|
||||
void DetachFromContext() { mContext = nullptr; }
|
||||
|
||||
private:
|
||||
CanvasRenderingContext2D *mContext;
|
||||
};
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(CanvasRenderingContext2D)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(CanvasRenderingContext2D)
|
||||
|
||||
@@ -887,6 +916,12 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(CanvasRenderingContext2D)
|
||||
ImplCycleCollectionUnlink(tmp->mStyleStack[i].patternStyles[Style::FILL]);
|
||||
ImplCycleCollectionUnlink(tmp->mStyleStack[i].gradientStyles[Style::STROKE]);
|
||||
ImplCycleCollectionUnlink(tmp->mStyleStack[i].gradientStyles[Style::FILL]);
|
||||
CanvasFilterChainObserver *filterChainObserver =
|
||||
static_cast<CanvasFilterChainObserver*>(tmp->mStyleStack[i].filterChainObserver.get());
|
||||
if (filterChainObserver) {
|
||||
filterChainObserver->DetachFromContext();
|
||||
}
|
||||
ImplCycleCollectionUnlink(tmp->mStyleStack[i].filterChainObserver);
|
||||
}
|
||||
for (size_t x = 0 ; x < tmp->mHitRegionsOptions.Length(); x++) {
|
||||
RegionInfo& info = tmp->mHitRegionsOptions[x];
|
||||
@@ -904,6 +939,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(CanvasRenderingContext2D)
|
||||
ImplCycleCollectionTraverse(cb, tmp->mStyleStack[i].patternStyles[Style::FILL], "Fill CanvasPattern");
|
||||
ImplCycleCollectionTraverse(cb, tmp->mStyleStack[i].gradientStyles[Style::STROKE], "Stroke CanvasGradient");
|
||||
ImplCycleCollectionTraverse(cb, tmp->mStyleStack[i].gradientStyles[Style::FILL], "Fill CanvasGradient");
|
||||
ImplCycleCollectionTraverse(cb, tmp->mStyleStack[i].filterChainObserver, "Filter Chain Observer");
|
||||
}
|
||||
for (size_t x = 0 ; x < tmp->mHitRegionsOptions.Length(); x++) {
|
||||
RegionInfo& info = tmp->mHitRegionsOptions[x];
|
||||
@@ -1182,7 +1218,7 @@ CanvasRenderingContext2D::Redraw(const gfx::Rect& aR)
|
||||
void
|
||||
CanvasRenderingContext2D::DidRefresh()
|
||||
{
|
||||
if (IsTargetValid() && SkiaGLTex()) {
|
||||
if (IsTargetValid() && mIsSkiaGL) {
|
||||
SkiaGLGlue* glue = gfxPlatform::GetPlatform()->GetSkiaGLGlue();
|
||||
MOZ_ASSERT(glue);
|
||||
|
||||
@@ -2425,30 +2461,6 @@ CanvasRenderingContext2D::ParseFilter(const nsAString& aString,
|
||||
return true;
|
||||
}
|
||||
|
||||
class CanvasFilterChainObserver : public nsSVGFilterChainObserver
|
||||
{
|
||||
public:
|
||||
CanvasFilterChainObserver(nsTArray<nsStyleFilter>& aFilters,
|
||||
Element* aCanvasElement,
|
||||
CanvasRenderingContext2D* aContext)
|
||||
: nsSVGFilterChainObserver(aFilters, aCanvasElement)
|
||||
, mContext(aContext)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void DoUpdate() override
|
||||
{
|
||||
// Refresh the cached FilterDescription in mContext->CurrentState().filter.
|
||||
// If this filter is not at the top of the state stack, we'll refresh the
|
||||
// wrong filter, but that's ok, because we'll refresh the right filter
|
||||
// when we pop the state stack in CanvasRenderingContext2D::Restore().
|
||||
mContext->UpdateFilter();
|
||||
}
|
||||
|
||||
private:
|
||||
CanvasRenderingContext2D *mContext;
|
||||
};
|
||||
|
||||
void
|
||||
CanvasRenderingContext2D::SetFilter(const nsAString& aFilter, ErrorResult& aError)
|
||||
{
|
||||
@@ -5639,20 +5651,19 @@ CanvasRenderingContext2D::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
|
||||
|
||||
CanvasLayer::Data data;
|
||||
|
||||
GLuint skiaGLTex = SkiaGLTex();
|
||||
if (mIsSkiaGL && skiaGLTex) {
|
||||
SkiaGLGlue* glue = gfxPlatform::GetPlatform()->GetSkiaGLGlue();
|
||||
MOZ_ASSERT(glue);
|
||||
|
||||
data.mGLContext = glue->GetGLContext();
|
||||
data.mFrontbufferGLTex = skiaGLTex;
|
||||
PersistentBufferProvider *provider = GetBufferProvider(aManager);
|
||||
data.mBufferProvider = provider;
|
||||
} else {
|
||||
PersistentBufferProvider *provider = GetBufferProvider(aManager);
|
||||
data.mBufferProvider = provider;
|
||||
if (mIsSkiaGL) {
|
||||
GLuint skiaGLTex = SkiaGLTex();
|
||||
if (skiaGLTex) {
|
||||
SkiaGLGlue* glue = gfxPlatform::GetPlatform()->GetSkiaGLGlue();
|
||||
MOZ_ASSERT(glue);
|
||||
data.mGLContext = glue->GetGLContext();
|
||||
data.mFrontbufferGLTex = skiaGLTex;
|
||||
}
|
||||
}
|
||||
|
||||
PersistentBufferProvider *provider = GetBufferProvider(aManager);
|
||||
data.mBufferProvider = provider;
|
||||
|
||||
if (userData &&
|
||||
userData->IsForContext(this) &&
|
||||
static_cast<CanvasLayer*>(aOldLayer)->IsDataValid(data)) {
|
||||
@@ -5693,20 +5704,20 @@ CanvasRenderingContext2D::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
|
||||
canvasLayer->SetPreTransactionCallback(
|
||||
CanvasRenderingContext2DUserData::PreTransactionCallback, userData);
|
||||
|
||||
GLuint skiaGLTex = SkiaGLTex();
|
||||
if (mIsSkiaGL && skiaGLTex) {
|
||||
SkiaGLGlue* glue = gfxPlatform::GetPlatform()->GetSkiaGLGlue();
|
||||
MOZ_ASSERT(glue);
|
||||
|
||||
data.mGLContext = glue->GetGLContext();
|
||||
data.mFrontbufferGLTex = skiaGLTex;
|
||||
PersistentBufferProvider *provider = GetBufferProvider(aManager);
|
||||
data.mBufferProvider = provider;
|
||||
} else {
|
||||
PersistentBufferProvider *provider = GetBufferProvider(aManager);
|
||||
data.mBufferProvider = provider;
|
||||
if (mIsSkiaGL) {
|
||||
GLuint skiaGLTex = SkiaGLTex();
|
||||
if (skiaGLTex) {
|
||||
SkiaGLGlue* glue = gfxPlatform::GetPlatform()->GetSkiaGLGlue();
|
||||
MOZ_ASSERT(glue);
|
||||
data.mGLContext = glue->GetGLContext();
|
||||
data.mFrontbufferGLTex = skiaGLTex;
|
||||
}
|
||||
}
|
||||
|
||||
PersistentBufferProvider *provider = GetBufferProvider(aManager);
|
||||
data.mBufferProvider = provider;
|
||||
|
||||
canvasLayer->Initialize(data);
|
||||
uint32_t flags = mOpaque ? Layer::CONTENT_OPAQUE : 0;
|
||||
canvasLayer->SetContentFlags(flags);
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
|
||||
#include "WebGLElementArrayCache.cpp"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include "nscore.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
@@ -21,7 +21,7 @@ VerifyImplFunction(bool condition, const char* file, int line)
|
||||
if (condition) {
|
||||
gTestsPassed++;
|
||||
} else {
|
||||
std::cerr << "Test failed at " << file << ":" << line << std::endl;
|
||||
std::fprintf(stderr, "Test failed at %s:%d\n", file, line);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
@@ -226,7 +226,7 @@ main(int argc, char* argv[])
|
||||
} // i
|
||||
} // maxBufferSize
|
||||
|
||||
std::cerr << argv[0] << ": all " << gTestsPassed << " tests passed" << std::endl;
|
||||
std::fprintf(stderr, "%s: all %d tests passed\n", argv[0], gTestsPassed);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,9 @@ GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_USER_2] = "user-2";
|
||||
const CB_MESSAGE_SIZE_GSM = 88;
|
||||
const CB_MESSAGE_SIZE_ETWS = 56;
|
||||
|
||||
const CB_UMTS_MESSAGE_TYPE_CBS = 1;
|
||||
const CB_UMTS_MESSAGE_PAGE_SIZE = 82;
|
||||
|
||||
const CB_GSM_MESSAGEID_ETWS_BEGIN = 0x1100;
|
||||
const CB_GSM_MESSAGEID_ETWS_END = 0x1107;
|
||||
|
||||
@@ -189,7 +192,7 @@ function decodeGsmDataCodingScheme(aDcs) {
|
||||
*
|
||||
* @return A deferred promise.
|
||||
*/
|
||||
let cbManager;
|
||||
var cbManager;
|
||||
function ensureCellBroadcast() {
|
||||
let deferred = Promise.defer();
|
||||
|
||||
@@ -201,18 +204,28 @@ function ensureCellBroadcast() {
|
||||
SpecialPowers.pushPermissions(permissions, function() {
|
||||
ok(true, "permissions pushed: " + JSON.stringify(permissions));
|
||||
|
||||
cbManager = window.navigator.mozCellBroadcast;
|
||||
if (cbManager) {
|
||||
log("navigator.mozCellBroadcast is instance of " + cbManager.constructor);
|
||||
} else {
|
||||
log("navigator.mozCellBroadcast is undefined.");
|
||||
}
|
||||
// Permission changes can't change existing Navigator.prototype
|
||||
// objects, so grab our objects from a new Navigator.
|
||||
let workingFrame = document.createElement("iframe");
|
||||
workingFrame.addEventListener("load", function load() {
|
||||
workingFrame.removeEventListener("load", load);
|
||||
|
||||
if (cbManager instanceof window.MozCellBroadcast) {
|
||||
deferred.resolve(cbManager);
|
||||
} else {
|
||||
deferred.reject();
|
||||
}
|
||||
cbManager = workingFrame.contentWindow.navigator.mozCellBroadcast;
|
||||
|
||||
if (cbManager) {
|
||||
log("navigator.mozCellBroadcast is instance of " + cbManager.constructor);
|
||||
} else {
|
||||
log("navigator.mozCellBroadcast is undefined.");
|
||||
}
|
||||
|
||||
if (cbManager instanceof window.MozCellBroadcast) {
|
||||
deferred.resolve(cbManager);
|
||||
} else {
|
||||
deferred.reject();
|
||||
}
|
||||
});
|
||||
|
||||
document.body.appendChild(workingFrame);
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
@@ -233,7 +246,7 @@ function ensureCellBroadcast() {
|
||||
*
|
||||
* @return A deferred promise.
|
||||
*/
|
||||
let pendingEmulatorCmdCount = 0;
|
||||
var pendingEmulatorCmdCount = 0;
|
||||
function runEmulatorCmdSafe(aCommand) {
|
||||
let deferred = Promise.defer();
|
||||
|
||||
|
||||
@@ -5,5 +5,9 @@ qemu = true
|
||||
|
||||
[test_cellbroadcast_etws.js]
|
||||
[test_cellbroadcast_gsm.js]
|
||||
[test_cellbroadcast_gsm_language_and_body.js]
|
||||
disabled = Bug 1231462
|
||||
[test_cellbroadcast_multi_sim.js]
|
||||
[test_cellbroadcast_umts.js]
|
||||
[test_cellbroadcast_umts.js]
|
||||
[test_cellbroadcast_umts_language_and_body.js]
|
||||
disabled = Bug 1224992
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
MARIONETTE_TIMEOUT = 20000;
|
||||
MARIONETTE_TIMEOUT = 60000;
|
||||
MARIONETTE_HEAD_JS = 'head.js';
|
||||
|
||||
function testReceiving_ETWS_MessageAttributes() {
|
||||
@@ -91,7 +91,7 @@ function testReceiving_ETWS_MessageId() {
|
||||
// Message Identifier has 16 bits, but no bitwise operation is needed.
|
||||
// Test some selected values only.
|
||||
let messageIds = [
|
||||
0x0000, 0x0001, 0x0010, 0x0100, 0x1000, 0x1111, 0x8888, 0x8811,
|
||||
0x0000, 0x0001, 0x0010, 0x0100, 0x1111, 0x8888, 0x8811,
|
||||
];
|
||||
|
||||
let verifyCBMessage = (aMessage, aMessageId) => {
|
||||
|
||||
@@ -90,7 +90,7 @@ function testReceiving_GSM_MessageId() {
|
||||
// Message Identifier has 16 bits, but no bitwise operation is needed.
|
||||
// Test some selected values only.
|
||||
let messageIds = [
|
||||
0x0000, 0x0001, 0x0010, 0x0100, 0x1000, 0x1111, 0x8888, 0x8811,
|
||||
0x0000, 0x0001, 0x0010, 0x0100, 0x1111, 0x8888, 0x8811,
|
||||
];
|
||||
|
||||
let verifyCBMessage = (aMessage, aMessageId) => {
|
||||
@@ -110,62 +110,6 @@ function testReceiving_GSM_MessageId() {
|
||||
return promise;
|
||||
}
|
||||
|
||||
function testReceiving_GSM_Language_and_Body() {
|
||||
log("Test receiving GSM Cell Broadcast - Language & Body");
|
||||
|
||||
let promise = Promise.resolve();
|
||||
|
||||
let testDcs = [];
|
||||
let dcs = 0;
|
||||
while (dcs <= 0xFF) {
|
||||
try {
|
||||
let dcsInfo = { dcs: dcs };
|
||||
[ dcsInfo.encoding, dcsInfo.language,
|
||||
dcsInfo.indicator, dcsInfo.messageClass ] = decodeGsmDataCodingScheme(dcs);
|
||||
testDcs.push(dcsInfo);
|
||||
} catch (e) {
|
||||
// Unsupported coding group, skip.
|
||||
dcs = (dcs & PDU_DCS_CODING_GROUP_BITS) + 0x10;
|
||||
}
|
||||
dcs++;
|
||||
}
|
||||
|
||||
let verifyCBMessage = (aMessage, aDcsInfo) => {
|
||||
if (aDcsInfo.language) {
|
||||
is(aMessage.language, aDcsInfo.language, "aMessage.language");
|
||||
} else if (aDcsInfo.indicator) {
|
||||
is(aMessage.language, "@@", "aMessage.language");
|
||||
} else {
|
||||
ok(aMessage.language == null, "aMessage.language");
|
||||
}
|
||||
|
||||
switch (aDcsInfo.encoding) {
|
||||
case PDU_DCS_MSG_CODING_7BITS_ALPHABET:
|
||||
is(aMessage.body, aDcsInfo.indicator ? DUMMY_BODY_7BITS_IND : DUMMY_BODY_7BITS, "aMessage.body");
|
||||
break;
|
||||
case PDU_DCS_MSG_CODING_8BITS_ALPHABET:
|
||||
ok(aMessage.body == null, "aMessage.body");
|
||||
break;
|
||||
case PDU_DCS_MSG_CODING_16BITS_ALPHABET:
|
||||
is(aMessage.body, aDcsInfo.indicator ? DUMMY_BODY_UCS2_IND : DUMMY_BODY_UCS2, "aMessage.body");
|
||||
break;
|
||||
}
|
||||
|
||||
is(aMessage.messageClass, aDcsInfo.messageClass, "aMessage.messageClass");
|
||||
};
|
||||
|
||||
testDcs.forEach(function(aDcsInfo) {
|
||||
let pdu = buildHexStr(0, 8)
|
||||
+ buildHexStr(aDcsInfo.dcs, 2)
|
||||
+ buildHexStr(0, (CB_MESSAGE_SIZE_GSM - 5) * 2);
|
||||
promise = promise
|
||||
.then(() => sendMultipleRawCbsToEmulatorAndWait([pdu]))
|
||||
.then((aMessage) => verifyCBMessage(aMessage, aDcsInfo));
|
||||
});
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
function testReceiving_GSM_Timestamp() {
|
||||
log("Test receiving GSM Cell Broadcast - Timestamp");
|
||||
|
||||
@@ -351,7 +295,6 @@ startTestCommon(function testCaseMain() {
|
||||
.then(() => testReceiving_GSM_GeographicalScope())
|
||||
.then(() => testReceiving_GSM_MessageCode())
|
||||
.then(() => testReceiving_GSM_MessageId())
|
||||
.then(() => testReceiving_GSM_Language_and_Body())
|
||||
.then(() => testReceiving_GSM_Timestamp())
|
||||
.then(() => testReceiving_GSM_WarningType())
|
||||
.then(() => testReceiving_GSM_EmergencyUserAlert())
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
MARIONETTE_TIMEOUT = 90000;
|
||||
MARIONETTE_HEAD_JS = 'head.js';
|
||||
|
||||
function testReceiving_GSM_Language_and_Body() {
|
||||
log("Test receiving GSM Cell Broadcast - Language & Body");
|
||||
|
||||
let promise = Promise.resolve();
|
||||
|
||||
let testDcs = [];
|
||||
let dcs = 0;
|
||||
while (dcs <= 0xFF) {
|
||||
try {
|
||||
let dcsInfo = { dcs: dcs };
|
||||
[ dcsInfo.encoding, dcsInfo.language,
|
||||
dcsInfo.indicator, dcsInfo.messageClass ] = decodeGsmDataCodingScheme(dcs);
|
||||
testDcs.push(dcsInfo);
|
||||
} catch (e) {
|
||||
// Unsupported coding group, skip.
|
||||
dcs = (dcs & PDU_DCS_CODING_GROUP_BITS) + 0x10;
|
||||
}
|
||||
dcs++;
|
||||
}
|
||||
|
||||
let verifyCBMessage = (aMessage, aDcsInfo) => {
|
||||
if (aDcsInfo.language) {
|
||||
is(aMessage.language, aDcsInfo.language, "aMessage.language");
|
||||
} else if (aDcsInfo.indicator) {
|
||||
is(aMessage.language, "@@", "aMessage.language");
|
||||
} else {
|
||||
ok(aMessage.language == null, "aMessage.language");
|
||||
}
|
||||
|
||||
switch (aDcsInfo.encoding) {
|
||||
case PDU_DCS_MSG_CODING_7BITS_ALPHABET:
|
||||
is(aMessage.body, aDcsInfo.indicator ? DUMMY_BODY_7BITS_IND : DUMMY_BODY_7BITS, "aMessage.body");
|
||||
break;
|
||||
case PDU_DCS_MSG_CODING_8BITS_ALPHABET:
|
||||
ok(aMessage.body == null, "aMessage.body");
|
||||
break;
|
||||
case PDU_DCS_MSG_CODING_16BITS_ALPHABET:
|
||||
is(aMessage.body, aDcsInfo.indicator ? DUMMY_BODY_UCS2_IND : DUMMY_BODY_UCS2, "aMessage.body");
|
||||
break;
|
||||
}
|
||||
|
||||
is(aMessage.messageClass, aDcsInfo.messageClass, "aMessage.messageClass");
|
||||
};
|
||||
|
||||
ok(testDcs.length, "testDcs.length");
|
||||
testDcs.forEach(function(aDcsInfo) {
|
||||
let pdu = buildHexStr(0, 8)
|
||||
+ buildHexStr(aDcsInfo.dcs, 2)
|
||||
+ buildHexStr(0, (CB_MESSAGE_SIZE_GSM - 5) * 2);
|
||||
promise = promise
|
||||
.then(() => sendMultipleRawCbsToEmulatorAndWait([pdu]))
|
||||
.then((aMessage) => verifyCBMessage(aMessage, aDcsInfo));
|
||||
});
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
startTestCommon(() => testReceiving_GSM_Language_and_Body());
|
||||
@@ -1,7 +1,7 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
MARIONETTE_TIMEOUT = 10000;
|
||||
MARIONETTE_TIMEOUT = 60000;
|
||||
MARIONETTE_HEAD_JS = 'head.js';
|
||||
|
||||
function testReceiving_MultiSIM() {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
MARIONETTE_TIMEOUT = 90000;
|
||||
MARIONETTE_HEAD_JS = 'head.js';
|
||||
|
||||
const CB_UMTS_MESSAGE_TYPE_CBS = 1;
|
||||
const CB_UMTS_MESSAGE_PAGE_SIZE = 82;
|
||||
|
||||
function testReceiving_UMTS_MessageAttributes() {
|
||||
log("Test receiving UMTS Cell Broadcast - Message Attributes");
|
||||
|
||||
@@ -102,7 +102,7 @@ function testReceiving_UMTS_MessageId() {
|
||||
// Message Identifier has 16 bits, but no bitwise operation is needed.
|
||||
// Test some selected values only.
|
||||
let messageIds = [
|
||||
0x0000, 0x0001, 0x0010, 0x0100, 0x1000, 0x1111, 0x8888, 0x8811,
|
||||
0x0000, 0x0001, 0x0010, 0x0100, 0x1111, 0x8888, 0x8811,
|
||||
];
|
||||
|
||||
let verifyCBMessage = (aMessage, aMessageId) => {
|
||||
@@ -126,70 +126,6 @@ function testReceiving_UMTS_MessageId() {
|
||||
return promise;
|
||||
}
|
||||
|
||||
function testReceiving_UMTS_Language_and_Body() {
|
||||
log("Test receiving UMTS Cell Broadcast - Language & Body");
|
||||
|
||||
let promise = Promise.resolve();
|
||||
|
||||
let testDcs = [];
|
||||
let dcs = 0;
|
||||
while (dcs <= 0xFF) {
|
||||
try {
|
||||
let dcsInfo = { dcs: dcs };
|
||||
[ dcsInfo.encoding, dcsInfo.language,
|
||||
dcsInfo.indicator, dcsInfo.messageClass ] = decodeGsmDataCodingScheme(dcs);
|
||||
testDcs.push(dcsInfo);
|
||||
} catch (e) {
|
||||
// Unsupported coding group, skip.
|
||||
dcs = (dcs & PDU_DCS_CODING_GROUP_BITS) + 0x10;
|
||||
}
|
||||
dcs++;
|
||||
}
|
||||
|
||||
let verifyCBMessage = (aMessage, aDcsInfo) => {
|
||||
if (aDcsInfo.language) {
|
||||
is(aMessage.language, aDcsInfo.language, "aMessage.language");
|
||||
} else if (aDcsInfo.indicator) {
|
||||
is(aMessage.language, "@@", "aMessage.language");
|
||||
} else {
|
||||
ok(aMessage.language == null, "aMessage.language");
|
||||
}
|
||||
|
||||
switch (aDcsInfo.encoding) {
|
||||
case PDU_DCS_MSG_CODING_7BITS_ALPHABET:
|
||||
is(aMessage.body,
|
||||
aDcsInfo.indicator ? DUMMY_BODY_7BITS_IND : DUMMY_BODY_7BITS,
|
||||
"aMessage.body");
|
||||
break;
|
||||
case PDU_DCS_MSG_CODING_8BITS_ALPHABET:
|
||||
ok(aMessage.body == null, "aMessage.body");
|
||||
break;
|
||||
case PDU_DCS_MSG_CODING_16BITS_ALPHABET:
|
||||
is(aMessage.body,
|
||||
aDcsInfo.indicator ? DUMMY_BODY_UCS2_IND : DUMMY_BODY_UCS2,
|
||||
"aMessage.body");
|
||||
break;
|
||||
}
|
||||
|
||||
is(aMessage.messageClass, aDcsInfo.messageClass, "aMessage.messageClass");
|
||||
};
|
||||
|
||||
testDcs.forEach(function(aDcsInfo) {
|
||||
let pdu = buildHexStr(CB_UMTS_MESSAGE_TYPE_CBS, 2) // msg_type
|
||||
+ buildHexStr(0, 4) // skip msg_id
|
||||
+ buildHexStr(0, 4) // skip SN
|
||||
+ buildHexStr(aDcsInfo.dcs, 2) // set dcs
|
||||
+ buildHexStr(1, 2) // set num_of_pages to 1
|
||||
+ buildHexStr(0, CB_UMTS_MESSAGE_PAGE_SIZE * 2)
|
||||
+ buildHexStr(CB_UMTS_MESSAGE_PAGE_SIZE, 2); // msg_info_length
|
||||
promise = promise
|
||||
.then(() => sendMultipleRawCbsToEmulatorAndWait([pdu]))
|
||||
.then((aMessage) => verifyCBMessage(aMessage, aDcsInfo));
|
||||
});
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
function testReceiving_UMTS_Timestamp() {
|
||||
log("Test receiving UMTS Cell Broadcast - Timestamp");
|
||||
|
||||
@@ -441,7 +377,6 @@ startTestCommon(function testCaseMain() {
|
||||
.then(() => testReceiving_UMTS_GeographicalScope())
|
||||
.then(() => testReceiving_UMTS_MessageCode())
|
||||
.then(() => testReceiving_UMTS_MessageId())
|
||||
.then(() => testReceiving_UMTS_Language_and_Body())
|
||||
.then(() => testReceiving_UMTS_Timestamp())
|
||||
.then(() => testReceiving_UMTS_WarningType())
|
||||
.then(() => testReceiving_UMTS_EmergencyUserAlert())
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
MARIONETTE_TIMEOUT = 90000;
|
||||
MARIONETTE_HEAD_JS = 'head.js';
|
||||
|
||||
function testReceiving_UMTS_Language_and_Body() {
|
||||
log("Test receiving UMTS Cell Broadcast - Language & Body");
|
||||
|
||||
let promise = Promise.resolve();
|
||||
|
||||
let testDcs = [];
|
||||
let dcs = 0;
|
||||
while (dcs <= 0xFF) {
|
||||
try {
|
||||
let dcsInfo = { dcs: dcs };
|
||||
[ dcsInfo.encoding, dcsInfo.language,
|
||||
dcsInfo.indicator, dcsInfo.messageClass ] = decodeGsmDataCodingScheme(dcs);
|
||||
testDcs.push(dcsInfo);
|
||||
} catch (e) {
|
||||
// Unsupported coding group, skip.
|
||||
dcs = (dcs & PDU_DCS_CODING_GROUP_BITS) + 0x10;
|
||||
}
|
||||
dcs++;
|
||||
}
|
||||
|
||||
let verifyCBMessage = (aMessage, aDcsInfo) => {
|
||||
if (aDcsInfo.language) {
|
||||
is(aMessage.language, aDcsInfo.language, "aMessage.language");
|
||||
} else if (aDcsInfo.indicator) {
|
||||
is(aMessage.language, "@@", "aMessage.language");
|
||||
} else {
|
||||
ok(aMessage.language == null, "aMessage.language");
|
||||
}
|
||||
|
||||
switch (aDcsInfo.encoding) {
|
||||
case PDU_DCS_MSG_CODING_7BITS_ALPHABET:
|
||||
is(aMessage.body,
|
||||
aDcsInfo.indicator ? DUMMY_BODY_7BITS_IND : DUMMY_BODY_7BITS,
|
||||
"aMessage.body");
|
||||
break;
|
||||
case PDU_DCS_MSG_CODING_8BITS_ALPHABET:
|
||||
ok(aMessage.body == null, "aMessage.body");
|
||||
break;
|
||||
case PDU_DCS_MSG_CODING_16BITS_ALPHABET:
|
||||
is(aMessage.body,
|
||||
aDcsInfo.indicator ? DUMMY_BODY_UCS2_IND : DUMMY_BODY_UCS2,
|
||||
"aMessage.body");
|
||||
break;
|
||||
}
|
||||
|
||||
is(aMessage.messageClass, aDcsInfo.messageClass, "aMessage.messageClass");
|
||||
};
|
||||
|
||||
testDcs.forEach(function(aDcsInfo) {
|
||||
let pdu = buildHexStr(CB_UMTS_MESSAGE_TYPE_CBS, 2) // msg_type
|
||||
+ buildHexStr(0, 4) // skip msg_id
|
||||
+ buildHexStr(0, 4) // skip SN
|
||||
+ buildHexStr(aDcsInfo.dcs, 2) // set dcs
|
||||
+ buildHexStr(1, 2) // set num_of_pages to 1
|
||||
+ buildHexStr(0, CB_UMTS_MESSAGE_PAGE_SIZE * 2)
|
||||
+ buildHexStr(CB_UMTS_MESSAGE_PAGE_SIZE, 2); // msg_info_length
|
||||
promise = promise
|
||||
.then(() => sendMultipleRawCbsToEmulatorAndWait([pdu]))
|
||||
.then((aMessage) => verifyCBMessage(aMessage, aDcsInfo));
|
||||
});
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
startTestCommon(() => testReceiving_UMTS_Language_and_Body());
|
||||
@@ -1,209 +1,28 @@
|
||||
<!DOCTYPE html>
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Migration tests</title>
|
||||
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<h1>migration tests</h1>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<iframe></iframe>
|
||||
<pre id="test">
|
||||
<script type="text/javascript;version=1.8" src="shared.js"></script>
|
||||
<script class="testbody" type="text/javascript">
|
||||
"use strict";
|
||||
<script type="application/javascript">
|
||||
|
||||
var backend, contactsCount, allContacts;
|
||||
function loadChromeScript() {
|
||||
var url = SimpleTest.getTestFileURL("test_migration_chrome.js");
|
||||
backend = SpecialPowers.loadChromeScript(url);
|
||||
function run_tests() {
|
||||
var iframe = document.querySelector("iframe");
|
||||
iframe.src = "file_migration.html";
|
||||
}
|
||||
|
||||
function addBackendEvents() {
|
||||
backend.addMessageListener("createDB.success", function(count) {
|
||||
contactsCount = count;
|
||||
ok(true, "Created the database");
|
||||
next();
|
||||
});
|
||||
backend.addMessageListener("createDB.error", function(err) {
|
||||
ok(false, err);
|
||||
next();
|
||||
});
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
onload = function() {
|
||||
SpecialPowers.pushPermissions([
|
||||
{type: "contacts-read", allow: true, context: document},
|
||||
{type: "contacts-write", allow: true, context: document},
|
||||
{type: "contacts-create", allow: true, context: document},
|
||||
], run_tests);
|
||||
};
|
||||
|
||||
backend.addMessageListener("deleteDB.success", function() {
|
||||
ok(true, "Deleted the database");
|
||||
next();
|
||||
});
|
||||
backend.addMessageListener("deleteDB.error", function(err) {
|
||||
ok(false, err);
|
||||
next();
|
||||
});
|
||||
}
|
||||
|
||||
function createDB(version) {
|
||||
info("Will create the DB at version " + version);
|
||||
backend.sendAsyncMessage("createDB", version);
|
||||
}
|
||||
|
||||
function deleteDB() {
|
||||
info("Will delete the DB.");
|
||||
backend.sendAsyncMessage("deleteDB");
|
||||
}
|
||||
|
||||
function setSubstringMatching(value) {
|
||||
info("Setting substring matching to " + value);
|
||||
|
||||
if (value) {
|
||||
SpecialPowers.setIntPref("dom.phonenumber.substringmatching.BR", value);
|
||||
|
||||
// this is the Mcc for Brazil, so that we trigger the previous pref
|
||||
SpecialPowers.setCharPref("ril.lastKnownSimMcc", "724");
|
||||
} else {
|
||||
SpecialPowers.clearUserPref("dom.phonenumber.substringmatching.BR");
|
||||
SpecialPowers.clearUserPref("ril.lastKnownSimMcc");
|
||||
}
|
||||
|
||||
next();
|
||||
}
|
||||
|
||||
var steps = [
|
||||
function setupChromeScript() {
|
||||
loadChromeScript();
|
||||
addBackendEvents();
|
||||
next();
|
||||
},
|
||||
|
||||
deleteDB, // let's be sure the DB does not exist yet
|
||||
createDB.bind(null, 12),
|
||||
setSubstringMatching.bind(null, 7),
|
||||
|
||||
function testAccessMozContacts() {
|
||||
info("Checking we have the right number of contacts: " + contactsCount);
|
||||
var req = mozContacts.getCount();
|
||||
req.onsuccess = function onsuccess() {
|
||||
ok(true, "Could access the mozContacts API");
|
||||
is(this.result, contactsCount, "Contacts count is correct");
|
||||
next();
|
||||
};
|
||||
|
||||
req.onerror = function onerror() {
|
||||
ok(false, "Couldn't access the mozContacts API");
|
||||
next();
|
||||
};
|
||||
},
|
||||
|
||||
function testRetrieveAllContacts() {
|
||||
/* if the migration does not work right, either we'll have an error, or the
|
||||
contacts won't be migrated properly and thus will fail WebIDL conversion,
|
||||
which will manifest as a timeout */
|
||||
info("Checking the contacts are corrected to obey WebIDL constraints. (upgrades 14 to 17)");
|
||||
var req = mozContacts.find();
|
||||
req.onsuccess = function onsuccess() {
|
||||
if (this.result) {
|
||||
is(this.result.length, contactsCount, "Contacts array length is correct");
|
||||
allContacts = this.result;
|
||||
next();
|
||||
} else {
|
||||
ok(false, "Could access the mozContacts API but got no contacts!");
|
||||
next();
|
||||
}
|
||||
};
|
||||
|
||||
req.onerror = function onerror() {
|
||||
ok(false, "Couldn't access the mozContacts API");
|
||||
next();
|
||||
};
|
||||
},
|
||||
|
||||
function checkNameIndex() {
|
||||
info("Checking name index migration (upgrades 17 to 19).");
|
||||
if (!allContacts) {
|
||||
next();
|
||||
}
|
||||
|
||||
var count = allContacts.length;
|
||||
|
||||
function finishRequest() {
|
||||
count--;
|
||||
if (!count) {
|
||||
next();
|
||||
}
|
||||
}
|
||||
|
||||
allContacts.forEach(function(contact) {
|
||||
var name = contact.name && contact.name[0];
|
||||
if (!name) {
|
||||
count--;
|
||||
return;
|
||||
}
|
||||
|
||||
var req = mozContacts.find({
|
||||
filterBy: ["name"],
|
||||
filterValue: name,
|
||||
filterOp: "equals"
|
||||
});
|
||||
|
||||
req.onsuccess = function onsuccess() {
|
||||
if (this.result) {
|
||||
info("Found contact '" + name + "', checking it's the correct one.");
|
||||
checkContacts(this.result[0], contact);
|
||||
} else {
|
||||
ok(false, "Could not find contact with name '" + name + "'");
|
||||
}
|
||||
|
||||
finishRequest();
|
||||
};
|
||||
|
||||
req.onerror = function onerror() {
|
||||
ok(false, "Error while finding contact with name '" + name + "'!");
|
||||
finishRequest();
|
||||
}
|
||||
});
|
||||
|
||||
if (!count) {
|
||||
ok(false, "No contact had a name, this is unexpected.");
|
||||
next();
|
||||
}
|
||||
},
|
||||
|
||||
function checkSubstringMatching() {
|
||||
var subject = "0004567890"; // the last 7 digits are the same that at least one contact
|
||||
info("Looking for a contact matching " + subject);
|
||||
var req = mozContacts.find({
|
||||
filterValue: subject,
|
||||
filterOp: "match",
|
||||
filterBy: ["tel"],
|
||||
filterLimit: 1
|
||||
});
|
||||
|
||||
req.onsuccess = function onsuccess() {
|
||||
if (this.result && this.result[0]) {
|
||||
ok(true, "Found a contact with number " + this.result[0].tel[0].value);
|
||||
}
|
||||
next();
|
||||
};
|
||||
|
||||
req.onerror = function onerror() {
|
||||
ok(false, "Error while finding contact for substring matching check!");
|
||||
next();
|
||||
};
|
||||
},
|
||||
|
||||
deleteDB,
|
||||
setSubstringMatching.bind(null, null),
|
||||
|
||||
function finish() {
|
||||
backend.destroy();
|
||||
info("all done!\n");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
];
|
||||
|
||||
start_tests();
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
|
||||
@@ -109,6 +109,7 @@
|
||||
#include "nsComputedDOMStyle.h"
|
||||
#include "mozilla/StyleSetHandle.h"
|
||||
#include "mozilla/StyleSetHandleInlines.h"
|
||||
#include "ReferrerPolicy.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
@@ -1281,9 +1282,11 @@ nsGenericHTMLElement::ParseReferrerAttribute(const nsAString& aString,
|
||||
nsAttrValue& aResult)
|
||||
{
|
||||
static const nsAttrValue::EnumTable kReferrerTable[] = {
|
||||
{ "no-referrer", net::RP_No_Referrer },
|
||||
{ "origin", net::RP_Origin },
|
||||
{ "unsafe-url", net::RP_Unsafe_URL },
|
||||
{ net::kRPS_No_Referrer, net::RP_No_Referrer },
|
||||
{ net::kRPS_Origin, net::RP_Origin },
|
||||
{ net::kRPS_Origin_When_Cross_Origin, net::RP_Origin_When_Crossorigin },
|
||||
{ net::kRPS_No_Referrer_When_Downgrade, net::RP_No_Referrer_When_Downgrade },
|
||||
{ net::kRPS_Unsafe_URL, net::RP_Unsafe_URL },
|
||||
{ 0 }
|
||||
};
|
||||
return aResult.ParseEnumValue(aString, kReferrerTable, false);
|
||||
|
||||
@@ -320,7 +320,7 @@ nsHTMLDNSPrefetch::nsDeferrals::SubmitQueue()
|
||||
if (link && link->HasDeferredDNSPrefetchRequest()) {
|
||||
nsCOMPtr<nsIURI> hrefURI(link ? link->GetURI() : nullptr);
|
||||
bool isLocalResource = false;
|
||||
nsresult rv;
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
hostName.Truncate();
|
||||
if (hrefURI) {
|
||||
|
||||
+16
-16
@@ -934,23 +934,22 @@ nsHTMLDocument::SetDomain(const nsAString& aDomain, ErrorResult& rv)
|
||||
return;
|
||||
}
|
||||
|
||||
nsAutoCString newURIString;
|
||||
if (NS_FAILED(uri->GetScheme(newURIString))) {
|
||||
rv.Throw(NS_ERROR_FAILURE);
|
||||
return;
|
||||
}
|
||||
nsAutoCString path;
|
||||
if (NS_FAILED(uri->GetPath(path))) {
|
||||
rv.Throw(NS_ERROR_FAILURE);
|
||||
return;
|
||||
}
|
||||
newURIString.AppendLiteral("://");
|
||||
AppendUTF16toUTF8(aDomain, newURIString);
|
||||
newURIString.Append(path);
|
||||
|
||||
nsCOMPtr<nsIURI> newURI;
|
||||
if (NS_FAILED(NS_NewURI(getter_AddRefs(newURI), newURIString))) {
|
||||
rv.Throw(NS_ERROR_FAILURE);
|
||||
nsresult rv2 = uri->Clone(getter_AddRefs(newURI));
|
||||
if (NS_FAILED(rv2)) {
|
||||
rv.Throw(rv2);
|
||||
return;
|
||||
}
|
||||
|
||||
rv2 = newURI->SetUserPass(EmptyCString());
|
||||
if (NS_FAILED(rv2)) {
|
||||
rv.Throw(rv2);
|
||||
return;
|
||||
}
|
||||
|
||||
rv2 = newURI->SetHostPort(NS_ConvertUTF16toUTF8(aDomain));
|
||||
if (NS_FAILED(rv2)) {
|
||||
rv.Throw(rv2);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -989,6 +988,7 @@ nsHTMLDocument::SetDomain(const nsAString& aDomain, ErrorResult& rv)
|
||||
return;
|
||||
}
|
||||
|
||||
NS_TryToSetImmutable(newURI);
|
||||
rv = NodePrincipal()->SetDomain(newURI);
|
||||
}
|
||||
|
||||
|
||||
@@ -1918,7 +1918,7 @@ nsTextEditorState::GetValue(nsAString& aValue, bool aIgnoreWrap) const
|
||||
if (!mTextCtrlElement->ValueChanged() || !mValue) {
|
||||
mTextCtrlElement->GetDefaultValueFromContent(aValue);
|
||||
} else {
|
||||
aValue = NS_ConvertUTF8toUTF16(*mValue);
|
||||
aValue = *mValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2139,7 +2139,7 @@ nsTextEditorState::SetValue(const nsAString& aValue, uint32_t aFlags)
|
||||
}
|
||||
} else {
|
||||
if (!mValue) {
|
||||
mValue = new nsCString;
|
||||
mValue.emplace();
|
||||
}
|
||||
nsString value;
|
||||
if (!value.Assign(newValue, fallible)) {
|
||||
@@ -2148,7 +2148,7 @@ nsTextEditorState::SetValue(const nsAString& aValue, uint32_t aFlags)
|
||||
if (!nsContentUtils::PlatformToDOMLineBreaks(value, fallible)) {
|
||||
return false;
|
||||
}
|
||||
if (!CopyUTF16toUTF8(value, *mValue, fallible)) {
|
||||
if (!mValue->Assign(value, fallible)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/WeakPtr.h"
|
||||
|
||||
class nsTextInputListener;
|
||||
@@ -292,7 +293,7 @@ private:
|
||||
nsCOMPtr<mozilla::dom::Element> mPlaceholderDiv;
|
||||
nsTextControlFrame* mBoundFrame;
|
||||
RefPtr<nsTextInputListener> mTextListener;
|
||||
nsAutoPtr<nsCString> mValue;
|
||||
mozilla::Maybe<nsString> mValue;
|
||||
RefPtr<nsAnonDivObserver> mMutationObserver;
|
||||
mutable nsString mCachedValue; // Caches non-hard-wrapped value on a multiline control.
|
||||
// mValueBeingSet is available only while SetValue() is requesting to commit
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
MARIONETTE_CONTEXT = "chrome";
|
||||
|
||||
var XPCOMUtils = Cu.import("resource://gre/modules/XPCOMUtils.jsm").XPCOMUtils;
|
||||
var Promise = Cu.import("resource://gre/modules/Promise.jsm").Promise;
|
||||
|
||||
var mobileConnectionService =
|
||||
Cc["@mozilla.org/mobileconnection/gonkmobileconnectionservice;1"]
|
||||
.getService(Ci.nsIMobileConnectionService);
|
||||
ok(mobileConnectionService,
|
||||
"mobileConnectionService.constructor is " + mobileConnectionService.constructor);
|
||||
|
||||
var _pendingEmulatorShellCmdCount = 0;
|
||||
|
||||
/**
|
||||
* Send emulator shell command with safe guard.
|
||||
*
|
||||
* We should only call |finish()| after all emulator shell command transactions
|
||||
* end, so here comes with the pending counter. Resolve when the emulator
|
||||
* shell gives response. Never reject.
|
||||
*
|
||||
* Fulfill params:
|
||||
* result -- an array of emulator shell response lines.
|
||||
*
|
||||
* @param aCommands
|
||||
* A string array commands to be passed to emulator through adb shell.
|
||||
*
|
||||
* @return A deferred promise.
|
||||
*/
|
||||
function runEmulatorShellCmdSafe(aCommands) {
|
||||
return new Promise(function(aResolve, aReject) {
|
||||
++_pendingEmulatorShellCmdCount;
|
||||
runEmulatorShell(aCommands, function(aResult) {
|
||||
--_pendingEmulatorShellCmdCount;
|
||||
|
||||
ok(true, "Emulator shell response: " + JSON.stringify(aResult));
|
||||
aResolve(aResult);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get nsIMobileConnection by clientId
|
||||
*
|
||||
* @param aClient [optional]
|
||||
* A numeric DSDS client id. Default: 0.
|
||||
*
|
||||
* @return A nsIMobileConnection.
|
||||
*/
|
||||
function getMobileConnection(aClientId = 0) {
|
||||
let mobileConnection = mobileConnectionService.getItemByServiceId(0);
|
||||
ok(mobileConnection,
|
||||
"mobileConnection.constructor is " + mobileConnection.constructor);
|
||||
return mobileConnection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Neighboring Cell Ids.
|
||||
*
|
||||
* Fulfill params:
|
||||
* An array of nsINeighboringCellInfo.
|
||||
* Reject params:
|
||||
* 'RadioNotAvailable', 'RequestNotSupported', or 'GenericFailure'
|
||||
*
|
||||
* @param aClient [optional]
|
||||
* A numeric DSDS client id. Default: 0.
|
||||
*
|
||||
* @return A deferred promise.
|
||||
*/
|
||||
function getNeighboringCellIds(aClientId = 0) {
|
||||
let mobileConnection = getMobileConnection(aClientId);
|
||||
return new Promise(function(aResolve, aReject) {
|
||||
ok(true, "getNeighboringCellIds");
|
||||
mobileConnection.getNeighboringCellIds({
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsINeighboringCellIdsCallback]),
|
||||
notifyGetNeighboringCellIds: function(aCount, aResults) {
|
||||
aResolve(aResults);
|
||||
},
|
||||
notifyGetNeighboringCellIdsFailed: function(aErrorMsg) {
|
||||
aReject(aErrorMsg);
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Cell Info List.
|
||||
*
|
||||
* Fulfill params:
|
||||
* An array of nsICellInfo.
|
||||
* Reject params:
|
||||
* 'RadioNotAvailable', 'RequestNotSupported', or 'GenericFailure'
|
||||
*
|
||||
* @param aClient [optional]
|
||||
* A numeric DSDS client id. Default: 0.
|
||||
*
|
||||
* @return A deferred promise.
|
||||
*/
|
||||
function getCellInfoList(aClientId = 0) {
|
||||
let mobileConnection = getMobileConnection(aClientId);
|
||||
return new Promise(function(aResolve, aReject) {
|
||||
ok(true, "getCellInfoList");
|
||||
mobileConnection.getCellInfoList({
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsICellInfoListCallback]),
|
||||
notifyGetCellInfoList: function(aCount, aResults) {
|
||||
aResolve(aResults);
|
||||
},
|
||||
notifyGetCellInfoListFailed: function(aErrorMsg) {
|
||||
aReject(aErrorMsg);
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for pending emulator transactions and call |finish()|.
|
||||
*/
|
||||
function cleanUp() {
|
||||
// Use ok here so that we have at least one test run.
|
||||
ok(true, ":: CLEANING UP ::");
|
||||
|
||||
waitFor(finish, function() {
|
||||
return _pendingEmulatorShellCmdCount === 0;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic test routine helper.
|
||||
*
|
||||
* This helper does nothing but clean-ups.
|
||||
*
|
||||
* @param aTestCaseMain
|
||||
* A function that takes no parameter.
|
||||
*/
|
||||
function startTestBase(aTestCaseMain) {
|
||||
return Promise.resolve()
|
||||
.then(aTestCaseMain)
|
||||
.catch((aException) => {
|
||||
ok(false, "promise rejects during test: " + aException);
|
||||
})
|
||||
.then(cleanUp);
|
||||
}
|
||||
@@ -8,6 +8,7 @@ qemu = true
|
||||
[test_mobile_voice_location.js]
|
||||
[test_mobile_operator_names.js]
|
||||
[test_mobile_operator_names_plmnlist.js]
|
||||
disabled = Bug 1234746
|
||||
[test_mobile_operator_names_roaming.js]
|
||||
[test_mobile_preferred_network_type.js]
|
||||
[test_mobile_preferred_network_type_radio_off.js]
|
||||
@@ -15,6 +16,7 @@ qemu = true
|
||||
[test_mobile_data_location.js]
|
||||
[test_mobile_data_state.js]
|
||||
[test_mobile_roaming_preference.js]
|
||||
[test_call_barring_basic_operations.js]
|
||||
[test_call_barring_get_error.js]
|
||||
[test_call_barring_set_error.js]
|
||||
[test_call_barring_change_password.js]
|
||||
@@ -25,7 +27,6 @@ qemu = true
|
||||
[test_mobile_connections_array_uninitialized.js]
|
||||
[test_mobile_signal_strength.js]
|
||||
[test_mobile_data_ipv6.js]
|
||||
disabled = Bug 979137
|
||||
[test_mobile_supported_network_types.js]
|
||||
[test_mobile_call_forwarding.js]
|
||||
[test_mobile_call_forwarding_set_error.js]
|
||||
@@ -35,3 +36,5 @@ disabled = Bug 979137
|
||||
[test_mobile_clir.js]
|
||||
[test_mobile_clir_radio_off.js]
|
||||
[test_mobile_neighboring_cell_ids.js]
|
||||
[test_mobile_cell_Info_list.js]
|
||||
skip-if = android_version < '19'
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
MARIONETTE_TIMEOUT = 60000;
|
||||
MARIONETTE_HEAD_JS = "head.js";
|
||||
|
||||
const AO = MozMobileConnection.CALL_BARRING_PROGRAM_ALL_OUTGOING;
|
||||
const OI = MozMobileConnection.CALL_BARRING_PROGRAM_OUTGOING_INTERNATIONAL;
|
||||
const OX = MozMobileConnection.CALL_BARRING_PROGRAM_OUTGOING_INTERNATIONAL_EXCEPT_HOME;
|
||||
var outgoingPrograms = [null, AO, OI, OX];
|
||||
|
||||
const AI = MozMobileConnection.CALL_BARRING_PROGRAM_ALL_INCOMING;
|
||||
const IR = MozMobileConnection.CALL_BARRING_PROGRAM_INCOMING_ROAMING;
|
||||
var incomingPrograms = [null, AI, IR];
|
||||
|
||||
const SERVICE_CLASS_VOICE = MozMobileConnection.ICC_SERVICE_CLASS_VOICE;
|
||||
|
||||
function getProgram(aProgram, aEnabled) {
|
||||
if (aProgram === null) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
return Promise.resolve()
|
||||
.then(() => getCallBarringOption({
|
||||
program: aProgram,
|
||||
serviceClass: SERVICE_CLASS_VOICE
|
||||
}))
|
||||
|
||||
.then(result => {
|
||||
is(result.program, aProgram, "Program");
|
||||
is(result.enabled, aEnabled, "Enabled");
|
||||
is(result.serviceClass, SERVICE_CLASS_VOICE, "ServiceClass");
|
||||
});
|
||||
}
|
||||
|
||||
function setProgram(aProgram, aEnabled) {
|
||||
if (aProgram === null) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
return Promise.resolve()
|
||||
.then(() => setCallBarringOption({
|
||||
program: aProgram,
|
||||
serviceClass: SERVICE_CLASS_VOICE,
|
||||
enabled: aEnabled,
|
||||
password: "0000" // The dafault call barring password of the emulator
|
||||
}));
|
||||
}
|
||||
|
||||
function setAndCheckProgram(aActiveProgram, aAllPrograms) {
|
||||
let promise = Promise.resolve();
|
||||
|
||||
if (aActiveProgram !== null) {
|
||||
promise = promise.then(() => setProgram(aActiveProgram, true));
|
||||
} else {
|
||||
// Deactive all barring programs in |aAllPrograms|.
|
||||
promise = aAllPrograms.reduce((previousPromise, program) => {
|
||||
return previousPromise.then(() => setProgram(program, false));
|
||||
}, promise);
|
||||
}
|
||||
|
||||
// Make sure |aActiveProgram| is the only active program in |aAllPrograms|.
|
||||
promise = aAllPrograms.reduce((previousPromise, program) => {
|
||||
return previousPromise.then(() => getProgram(program, program === aActiveProgram));
|
||||
}, promise);
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
function testSingleProgram(aOriginProgram, aTargetPrograms, aOriginPrograms) {
|
||||
let promise = setAndCheckProgram(aOriginProgram, aOriginPrograms);
|
||||
|
||||
return aTargetPrograms.reduce((previousPromise, targetProgram) => {
|
||||
return previousPromise
|
||||
.then(() => log(aOriginProgram + " <-> " + targetProgram))
|
||||
.then(() => setAndCheckProgram(targetProgram, aOriginPrograms))
|
||||
.then(() => setAndCheckProgram(aOriginProgram, aOriginPrograms));
|
||||
}, promise);
|
||||
}
|
||||
|
||||
function testAllPrograms(aPrograms) {
|
||||
let targetPrograms = aPrograms.slice();
|
||||
|
||||
return aPrograms.reduce((previousPromise, program) => {
|
||||
return previousPromise
|
||||
.then(() => {
|
||||
targetPrograms.shift();
|
||||
return testSingleProgram(program, targetPrograms, aPrograms);
|
||||
});
|
||||
}, Promise.resolve());
|
||||
}
|
||||
|
||||
function testUnsupportedPrograms() {
|
||||
// Emulator now doesn't support these three programs.
|
||||
let unsupportedPrograms =
|
||||
[MozMobileConnection.CALL_BARRING_PROGRAM_ALL_SERVICE,
|
||||
MozMobileConnection.CALL_BARRING_PROGRAM_OUTGOING_SERVICE,
|
||||
MozMobileConnection.CALL_BARRING_PROGRAM_INCOMING_SERVICE];
|
||||
|
||||
return unsupportedPrograms.reduce((previousPromise, program) => {
|
||||
return previousPromise
|
||||
.then(() => log("Test " + program))
|
||||
.then(() => setProgram(program, false))
|
||||
.then(() => {
|
||||
ok(false, "Should be rejected");
|
||||
}, error => {
|
||||
is(error.name, "RequestNotSupported",
|
||||
"Failed to setProgram: "+ error.name);
|
||||
});
|
||||
}, Promise.resolve());
|
||||
}
|
||||
|
||||
// Start tests
|
||||
startTestCommon(function() {
|
||||
return Promise.resolve()
|
||||
.then(() => setAndCheckProgram(null, outgoingPrograms))
|
||||
.then(() => setAndCheckProgram(null, incomingPrograms))
|
||||
|
||||
.then(() => log("=== Test outgoing call barring programs ==="))
|
||||
.then(() => testAllPrograms(outgoingPrograms))
|
||||
.then(() => log("=== Test incoming call barring programs ==="))
|
||||
.then(() => testAllPrograms(incomingPrograms))
|
||||
|
||||
.then(() => log("=== Test unsupported call barring programs ==="))
|
||||
.then(() => testUnsupportedPrograms())
|
||||
|
||||
.catch(aError => ok(false, "promise rejects during test: " + aError))
|
||||
.then(() => setAndCheckProgram(null, outgoingPrograms))
|
||||
.then(() => setAndCheckProgram(null, incomingPrograms));
|
||||
});
|
||||
@@ -4,33 +4,11 @@
|
||||
MARIONETTE_TIMEOUT = 60000;
|
||||
MARIONETTE_HEAD_JS = "head.js";
|
||||
|
||||
const TEST_DATA = [
|
||||
// [<pin>, <new pin>, <expected error>]
|
||||
function testChangeCallBarringPassword(aExpectedError, aOptions) {
|
||||
log("Test changing call barring password from " +
|
||||
aOptions.pin + " to " + aOptions.newPin);
|
||||
|
||||
// Test passing an invalid pin or newPin.
|
||||
[null, "0000", "InvalidPassword"],
|
||||
["0000", null, "InvalidPassword"],
|
||||
[null, null, "InvalidPassword"],
|
||||
|
||||
// Test passing mismatched newPin.
|
||||
["000", "0000", "InvalidPassword"],
|
||||
["00000", "1111", "InvalidPassword"],
|
||||
["abcd", "efgh", "InvalidPassword"],
|
||||
|
||||
// TODO: Bug 906603 - B2G RIL: Support Change Call Barring Password on Emulator.
|
||||
// Currently emulator doesn't support REQUEST_CHANGE_BARRING_PASSWORD, so we
|
||||
// expect to get a 'RequestNotSupported' error here.
|
||||
["1234", "1234", "RequestNotSupported"]
|
||||
];
|
||||
|
||||
function testChangeCallBarringPassword(aPin, aNewPin, aExpectedError) {
|
||||
log("Test changing call barring password to " + aPin + "/" + aNewPin);
|
||||
|
||||
let options = {
|
||||
pin: aPin,
|
||||
newPin: aNewPin
|
||||
};
|
||||
return changeCallBarringPassword(options)
|
||||
return changeCallBarringPassword(aOptions)
|
||||
.then(function resolve() {
|
||||
ok(!aExpectedError, "changeCallBarringPassword success");
|
||||
}, function reject(aError) {
|
||||
@@ -40,11 +18,67 @@ function testChangeCallBarringPassword(aPin, aNewPin, aExpectedError) {
|
||||
|
||||
// Start tests
|
||||
startTestCommon(function() {
|
||||
let promise = Promise.resolve();
|
||||
for (let i = 0; i < TEST_DATA.length; i++) {
|
||||
let data = TEST_DATA[i];
|
||||
promise =
|
||||
promise.then(() => testChangeCallBarringPassword(data[0], data[1], data[2]));
|
||||
}
|
||||
return promise;
|
||||
return Promise.resolve()
|
||||
|
||||
// According to TS.22.004 clause 5.2, the password should consist of four
|
||||
// digits in the range 0000 to 9999.
|
||||
|
||||
// Test passing an invalid pin.
|
||||
.then(() => testChangeCallBarringPassword("InvalidPassword", {
|
||||
pin: null,
|
||||
newPin: "0000"
|
||||
}))
|
||||
|
||||
.then(() => testChangeCallBarringPassword("InvalidPassword", {
|
||||
pin: "000",
|
||||
newPin: "0000"
|
||||
}))
|
||||
|
||||
.then(() => testChangeCallBarringPassword("InvalidPassword", {
|
||||
pin: "00000",
|
||||
newPin: "0000"
|
||||
}))
|
||||
|
||||
.then(() => testChangeCallBarringPassword("InvalidPassword", {
|
||||
pin: "abcd",
|
||||
newPin: "0000"
|
||||
}))
|
||||
|
||||
// Test passing an invalid newPin
|
||||
.then(() => testChangeCallBarringPassword("InvalidPassword", {
|
||||
pin: "0000",
|
||||
newPin: null
|
||||
}))
|
||||
|
||||
.then(() => testChangeCallBarringPassword("InvalidPassword", {
|
||||
pin: "0000",
|
||||
newPin: "000"
|
||||
}))
|
||||
|
||||
.then(() => testChangeCallBarringPassword("InvalidPassword", {
|
||||
pin: "0000",
|
||||
newPin: "00000"
|
||||
}))
|
||||
|
||||
.then(() => testChangeCallBarringPassword("InvalidPassword", {
|
||||
pin: "0000",
|
||||
newPin: "abcd"
|
||||
}))
|
||||
|
||||
// Test passing an incorrect password, where the default password is "0000".
|
||||
.then(() => testChangeCallBarringPassword("IncorrectPassword", {
|
||||
pin: "1111",
|
||||
newPin: "2222"
|
||||
}))
|
||||
|
||||
// Sucessful
|
||||
.then(() => testChangeCallBarringPassword(null, {
|
||||
pin: "0000",
|
||||
newPin: "2222"
|
||||
}))
|
||||
|
||||
.then(() => testChangeCallBarringPassword(null, {
|
||||
pin: "2222",
|
||||
newPin: "0000"
|
||||
}));
|
||||
});
|
||||
|
||||
@@ -4,59 +4,12 @@
|
||||
MARIONETTE_TIMEOUT = 60000;
|
||||
MARIONETTE_HEAD_JS = "head.js";
|
||||
|
||||
const TEST_DATA = [
|
||||
// Test passing invalid program.
|
||||
{
|
||||
options: {
|
||||
program: 5, /* Invalid program */
|
||||
serviceClass: 0
|
||||
},
|
||||
expectedError: "InvalidParameter"
|
||||
}, {
|
||||
options: {
|
||||
program: null,
|
||||
serviceClass: 0
|
||||
},
|
||||
expectedError: "InvalidParameter"
|
||||
}, {
|
||||
options: {
|
||||
/* Undefined program */
|
||||
serviceClass: 0
|
||||
},
|
||||
expectedError: "InvalidParameter"
|
||||
},
|
||||
// Test passing invalid serviceClass.
|
||||
{
|
||||
options: {
|
||||
program: MozMobileConnection.CALL_BARRING_PROGRAM_ALL_OUTGOING,
|
||||
serviceClass: null
|
||||
},
|
||||
expectedError: "InvalidParameter"
|
||||
}, {
|
||||
options: {
|
||||
program: MozMobileConnection.CALL_BARRING_PROGRAM_ALL_OUTGOING,
|
||||
/* Undefined serviceClass */
|
||||
},
|
||||
expectedError: "InvalidParameter"
|
||||
},
|
||||
// TODO: Bug 1027546 - [B2G][Emulator] Support call barring
|
||||
// Currently emulator doesn't support call barring, so we expect to get a
|
||||
// 'RequestNotSupported' error here.
|
||||
{
|
||||
options: {
|
||||
program: MozMobileConnection.CALL_BARRING_PROGRAM_ALL_OUTGOING,
|
||||
serviceClass: 0
|
||||
},
|
||||
expectedError: "RequestNotSupported"
|
||||
}
|
||||
];
|
||||
|
||||
function testGetCallBarringOption(aOptions, aExpectedError) {
|
||||
log("Test getting call barring to " + JSON.stringify(aOptions));
|
||||
function testGetCallBarringOption(aExpectedError, aOptions) {
|
||||
log("Test getCallBarringOption with " + JSON.stringify(aOptions));
|
||||
|
||||
return getCallBarringOption(aOptions)
|
||||
.then(function resolve(aResult) {
|
||||
ok(false, "should not success");
|
||||
ok(false, "should be rejected");
|
||||
}, function reject(aError) {
|
||||
is(aError.name, aExpectedError, "failed to getCallBarringOption");
|
||||
});
|
||||
@@ -64,11 +17,32 @@ function testGetCallBarringOption(aOptions, aExpectedError) {
|
||||
|
||||
// Start tests
|
||||
startTestCommon(function() {
|
||||
let promise = Promise.resolve();
|
||||
for (let i = 0; i < TEST_DATA.length; i++) {
|
||||
let data = TEST_DATA[i];
|
||||
promise = promise.then(() => testGetCallBarringOption(data.options,
|
||||
data.expectedError));
|
||||
}
|
||||
return promise;
|
||||
return Promise.resolve()
|
||||
|
||||
// Test program
|
||||
.then(() => testGetCallBarringOption("InvalidParameter", {
|
||||
program: 8, /* Invalid program */
|
||||
serviceClass: 0
|
||||
}))
|
||||
|
||||
.then(() => testGetCallBarringOption("InvalidParameter", {
|
||||
program: null, /* Invalid program */
|
||||
serviceClass: 0
|
||||
}))
|
||||
|
||||
.then(() => testGetCallBarringOption("InvalidParameter", {
|
||||
/* Undefined program */
|
||||
serviceClass: 0
|
||||
}))
|
||||
|
||||
// Test serviceClass
|
||||
.then(() => testGetCallBarringOption("InvalidParameter", {
|
||||
program: MozMobileConnection.CALL_BARRING_PROGRAM_ALL_OUTGOING,
|
||||
serviceClass: null /* Invalid serviceClass */
|
||||
}))
|
||||
|
||||
.then(() => testGetCallBarringOption("InvalidParameter", {
|
||||
program: MozMobileConnection.CALL_BARRING_PROGRAM_ALL_OUTGOING,
|
||||
/* Undefined serviceClass */
|
||||
}));
|
||||
});
|
||||
|
||||
@@ -4,107 +4,12 @@
|
||||
MARIONETTE_TIMEOUT = 60000;
|
||||
MARIONETTE_HEAD_JS = "head.js";
|
||||
|
||||
const TEST_DATA = [
|
||||
// Test passing invalid program.
|
||||
{
|
||||
options: {
|
||||
"program": 5, /* Invalid program */
|
||||
"enabled": true,
|
||||
"password": "0000",
|
||||
"serviceClass": 0
|
||||
},
|
||||
expectedError: "InvalidParameter"
|
||||
}, {
|
||||
options: {
|
||||
"program": null,
|
||||
"enabled": true,
|
||||
"password": "0000",
|
||||
"serviceClass": 0
|
||||
},
|
||||
expectedError: "InvalidParameter"
|
||||
}, {
|
||||
options: {
|
||||
/* Undefined program */
|
||||
"enabled": true,
|
||||
"password": "0000",
|
||||
"serviceClass": 0
|
||||
},
|
||||
expectedError: "InvalidParameter"
|
||||
},
|
||||
// Test passing invalid enabled.
|
||||
{
|
||||
options: {
|
||||
"program": MozMobileConnection.CALL_BARRING_PROGRAM_ALL_OUTGOING,
|
||||
"enabled": null,
|
||||
"password": "0000",
|
||||
"serviceClass": 0
|
||||
},
|
||||
expectedError: "InvalidParameter"
|
||||
}, {
|
||||
options: {
|
||||
"program": MozMobileConnection.CALL_BARRING_PROGRAM_ALL_OUTGOING,
|
||||
/* Undefined enabled */
|
||||
"password": "0000",
|
||||
"serviceClass": 0
|
||||
},
|
||||
expectedError: "InvalidParameter"
|
||||
},
|
||||
// Test passing invalid password.
|
||||
{
|
||||
options: {
|
||||
"program": MozMobileConnection.CALL_BARRING_PROGRAM_ALL_OUTGOING,
|
||||
"enabled": true,
|
||||
"password": null,
|
||||
"serviceClass": 0
|
||||
},
|
||||
expectedError: "InvalidParameter"
|
||||
}, {
|
||||
options: {
|
||||
"program": MozMobileConnection.CALL_BARRING_PROGRAM_ALL_OUTGOING,
|
||||
"enabled": true,
|
||||
/* Undefined password */
|
||||
"serviceClass": 0
|
||||
},
|
||||
expectedError: "InvalidParameter"
|
||||
},
|
||||
// Test passing invalid serviceClass.
|
||||
{
|
||||
options: {
|
||||
"program": MozMobileConnection.CALL_BARRING_PROGRAM_ALL_OUTGOING,
|
||||
"enabled": true,
|
||||
"password": "0000",
|
||||
"serviceClass": null
|
||||
},
|
||||
expectedError: "InvalidParameter"
|
||||
}, {
|
||||
options: {
|
||||
"program": MozMobileConnection.CALL_BARRING_PROGRAM_ALL_OUTGOING,
|
||||
"enabled": true,
|
||||
"password": "0000",
|
||||
/* Undefined serviceClass */
|
||||
},
|
||||
expectedError: "InvalidParameter"
|
||||
},
|
||||
// TODO: Bug 1027546 - [B2G][Emulator] Support call barring
|
||||
// Currently emulator doesn't support call barring, so we expect to get a
|
||||
// 'RequestNotSupported' error here.
|
||||
{
|
||||
options: {
|
||||
"program": MozMobileConnection.CALL_BARRING_PROGRAM_ALL_OUTGOING,
|
||||
"enabled": true,
|
||||
"password": "0000",
|
||||
"serviceClass": 0
|
||||
},
|
||||
expectedError: "RequestNotSupported"
|
||||
}
|
||||
];
|
||||
|
||||
function testSetCallBarringOption(aOptions, aExpectedError) {
|
||||
log("Test setting call barring to " + JSON.stringify(aOptions));
|
||||
function testSetCallBarringOption(aExpectedError, aOptions) {
|
||||
log("Test setCallBarringOption with " + JSON.stringify(aOptions));
|
||||
|
||||
return setCallBarringOption(aOptions)
|
||||
.then(function resolve() {
|
||||
ok(false, "changeCallBarringPassword success");
|
||||
ok(false, "should be rejected");
|
||||
}, function reject(aError) {
|
||||
is(aError.name, aExpectedError, "failed to changeCallBarringPassword");
|
||||
});
|
||||
@@ -112,11 +17,79 @@ function testSetCallBarringOption(aOptions, aExpectedError) {
|
||||
|
||||
// Start tests
|
||||
startTestCommon(function() {
|
||||
let promise = Promise.resolve();
|
||||
for (let i = 0; i < TEST_DATA.length; i++) {
|
||||
let data = TEST_DATA[i];
|
||||
promise = promise.then(() => testSetCallBarringOption(data.options,
|
||||
data.expectedError));
|
||||
}
|
||||
return promise;
|
||||
return Promise.resolve()
|
||||
|
||||
// Test program
|
||||
.then(() => testSetCallBarringOption("InvalidParameter", {
|
||||
"program": 8, /* Invalid program */
|
||||
"enabled": true,
|
||||
"password": "0000",
|
||||
"serviceClass": 0
|
||||
}))
|
||||
|
||||
.then(() => testSetCallBarringOption("InvalidParameter", {
|
||||
"program": null,
|
||||
"enabled": true,
|
||||
"password": "0000",
|
||||
"serviceClass": 0
|
||||
}))
|
||||
|
||||
.then(() => testSetCallBarringOption("InvalidParameter", {
|
||||
/* Undefined program */
|
||||
"enabled": true,
|
||||
"password": "0000",
|
||||
"serviceClass": 0
|
||||
}))
|
||||
|
||||
// Test enabled
|
||||
.then(() => testSetCallBarringOption("InvalidParameter", {
|
||||
"program": MozMobileConnection.CALL_BARRING_PROGRAM_ALL_OUTGOING,
|
||||
"enabled": null, /* Invalid enabled */
|
||||
"password": "0000",
|
||||
"serviceClass": 0
|
||||
}))
|
||||
|
||||
.then(() => testSetCallBarringOption("InvalidParameter", {
|
||||
"program": MozMobileConnection.CALL_BARRING_PROGRAM_ALL_OUTGOING,
|
||||
/* Undefined enabled */
|
||||
"password": "0000",
|
||||
"serviceClass": 0
|
||||
}))
|
||||
|
||||
// Test password
|
||||
.then(() => testSetCallBarringOption("InvalidParameter", {
|
||||
"program": MozMobileConnection.CALL_BARRING_PROGRAM_ALL_OUTGOING,
|
||||
"enabled": true,
|
||||
"password": null, /* Invalid password */
|
||||
"serviceClass": 0
|
||||
}))
|
||||
|
||||
.then(() => testSetCallBarringOption("InvalidParameter", {
|
||||
"program": MozMobileConnection.CALL_BARRING_PROGRAM_ALL_OUTGOING,
|
||||
"enabled": true,
|
||||
/* Undefined password */
|
||||
"serviceClass": 0
|
||||
}))
|
||||
|
||||
.then(() => testSetCallBarringOption("IncorrectPassword", {
|
||||
"program": MozMobileConnection.CALL_BARRING_PROGRAM_ALL_OUTGOING,
|
||||
"enabled": true,
|
||||
"password": "1111", /* Incorrect password */
|
||||
"serviceClass": 0
|
||||
}))
|
||||
|
||||
// Test serviceClass
|
||||
.then(() => testSetCallBarringOption("InvalidParameter", {
|
||||
"program": MozMobileConnection.CALL_BARRING_PROGRAM_ALL_OUTGOING,
|
||||
"enabled": true,
|
||||
"password": "0000",
|
||||
"serviceClass": null /* Invalid serviceClass */
|
||||
}))
|
||||
|
||||
.then(() => testSetCallBarringOption("InvalidParameter", {
|
||||
"program": MozMobileConnection.CALL_BARRING_PROGRAM_ALL_OUTGOING,
|
||||
"enabled": true,
|
||||
"password": "0000",
|
||||
/* Undefined serviceClass */
|
||||
}))
|
||||
});
|
||||
|
||||
@@ -6,9 +6,9 @@ MARIONETTE_HEAD_JS = "head.js";
|
||||
|
||||
const SETTINGS_KEY_DATA_DEFAULT_ID = "ril.data.defaultServiceId";
|
||||
|
||||
let connections;
|
||||
let numOfRadioInterfaces;
|
||||
let currentDataDefaultId = 0;
|
||||
var connections;
|
||||
var numOfRadioInterfaces;
|
||||
var currentDataDefaultId = 0;
|
||||
|
||||
function muxModem(id) {
|
||||
return runEmulatorCmdSafe("mux modem " + id);
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
MARIONETTE_TIMEOUT = 60000;
|
||||
MARIONETTE_HEAD_JS = "head_chrome.js";
|
||||
|
||||
// Start test.
|
||||
startTestBase(function() {
|
||||
return getCellInfoList()
|
||||
.then((aResults) => {
|
||||
// Cell Info are hard-coded in hardware/ril/reference-ril/reference-ril.c.
|
||||
is(aResults.length, 1, "Check number of cell Info");
|
||||
|
||||
let cell = aResults[0];
|
||||
is(cell.type, Ci.nsICellInfo.CELL_INFO_TYPE_GSM, "Check cell.type");
|
||||
is(cell.registered, true, "Check cell.registered");
|
||||
|
||||
ok(cell instanceof Ci.nsIGsmCellInfo,
|
||||
"cell.constructor is " + cell.constructor);
|
||||
|
||||
// The data hard-coded in hardware/ril/reference-ril/reference-ril.c
|
||||
// isn't correct (missing timeStampType), so we skip to check other
|
||||
// attributes first until we fix it.
|
||||
});
|
||||
});
|
||||
@@ -11,7 +11,7 @@ MARIONETTE_HEAD_JS = "head.js";
|
||||
*
|
||||
* 1) set "ril.data.apnSettings" to a given settings object,
|
||||
* 2) enable data connection and wait for a "datachange" event,
|
||||
* 3) check the IP address type of the active network interface,
|
||||
* 3) check the IP address type of the active network info,
|
||||
* 4) disable data connection.
|
||||
*
|
||||
* Fulfill params: (none)
|
||||
@@ -30,12 +30,12 @@ function doTest(aApnSettings, aHaveV4Address, aHaveV6Address) {
|
||||
.then(() => setDataEnabledAndWait(true))
|
||||
.then(function() {
|
||||
let nm = getNetworkManager();
|
||||
let active = nm.active;
|
||||
ok(active, "Active network interface");
|
||||
log(" Interface: " + active.name);
|
||||
let networkInfo = nm.activeNetworkInfo;
|
||||
ok(networkInfo, "Active network info");
|
||||
log(" Interface: " + networkInfo.name);
|
||||
|
||||
let ips = {}, prefixLengths = {};
|
||||
let num = active.getAddresses(ips, prefixLengths);
|
||||
let num = networkInfo.getAddresses(ips, prefixLengths);
|
||||
log(" Num addresses: " + num);
|
||||
log(" Addresses: " + JSON.stringify(ips.value));
|
||||
log(" PrefixLengths: " + JSON.stringify(prefixLengths.value));
|
||||
@@ -43,12 +43,12 @@ function doTest(aApnSettings, aHaveV4Address, aHaveV6Address) {
|
||||
if (aHaveV4Address) {
|
||||
ok(ips.value.reduce(function(aFound, aAddress) {
|
||||
return aFound || aAddress.indexOf(":") < 0;
|
||||
}), "IPv4 address");
|
||||
}, false), "IPv4 address");
|
||||
}
|
||||
if (aHaveV6Address) {
|
||||
ok(ips.value.reduce(function(aFound, aAddress) {
|
||||
return aFound || aAddress.indexOf(":") > 0;
|
||||
}), "IPv6 address");
|
||||
}, false), "IPv6 address");
|
||||
}
|
||||
})
|
||||
.then(() => setDataEnabledAndWait(false));
|
||||
@@ -106,14 +106,16 @@ startTestCommon(function() {
|
||||
|
||||
.then(() => doTestHome(aApnSettings, "NoSuchProtocol"))
|
||||
.then(() => doTestHome(aApnSettings, "IP"))
|
||||
.then(() => doTestHome(aApnSettings, "IPV4V6"))
|
||||
// TODO: Bug 979137 - B2G Emulator: Support the IPV4V6
|
||||
//.then(() => doTestHome(aApnSettings, "IPV4V6"))
|
||||
.then(() => doTestHome(aApnSettings, "IPV6"))
|
||||
|
||||
.then(() => setEmulatorRoamingAndWait(true))
|
||||
|
||||
.then(() => doTestRoaming(aApnSettings, "NoSuchProtocol"))
|
||||
.then(() => doTestRoaming(aApnSettings, "IP"))
|
||||
.then(() => doTestRoaming(aApnSettings, "IPV4V6"))
|
||||
// TODO: Bug 979137 - B2G Emulator: Support the IPV4V6
|
||||
//.then(() => doTestRoaming(aApnSettings, "IPV4V6"))
|
||||
.then(() => doTestRoaming(aApnSettings, "IPV6"))
|
||||
|
||||
.then(() => setEmulatorRoamingAndWait(false));
|
||||
|
||||
@@ -2,37 +2,17 @@
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
MARIONETTE_TIMEOUT = 30000;
|
||||
// This test must run in chrome context.
|
||||
MARIONETTE_CONTEXT = "chrome";
|
||||
MARIONETTE_HEAD_JS = "head_chrome.js";
|
||||
|
||||
let Promise = Cu.import("resource://gre/modules/Promise.jsm").Promise;
|
||||
|
||||
let service = Cc["@mozilla.org/mobileconnection/mobileconnectionservice;1"]
|
||||
.getService(Ci.nsIMobileConnectionService);
|
||||
ok(service, "service.constructor is " + service.constructor);
|
||||
|
||||
let mobileConnection = service.getItemByServiceId(0);
|
||||
ok(mobileConnection, "mobileConnection.constructor is " + mobileConnection.constrctor);
|
||||
|
||||
function testGetNeighboringCellIds() {
|
||||
log("Test getting mobile neighboring cell ids");
|
||||
let deferred = Promise.defer();
|
||||
|
||||
mobileConnection.getNeighboringCellIds({
|
||||
notifyGetNeighboringCellIds: function(aResult) {
|
||||
deferred.resolve(aResult);
|
||||
},
|
||||
notifyGetNeighboringCellIdsFailed: function(aError) {
|
||||
deferred.reject(aError);
|
||||
}
|
||||
});
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
// Start tests
|
||||
testGetNeighboringCellIds()
|
||||
.then(function resolve(aResult) {
|
||||
ok(false, "getNeighboringCellIds should not success");
|
||||
}, function reject(aError) {
|
||||
is(aError, "RequestNotSupported", "failed to getNeighboringCellIds");
|
||||
}).then(finish);
|
||||
// Start test.
|
||||
startTestBase(function() {
|
||||
// Emulator doesn't support REQUEST_GET_NEIGHBORING_CELL_IDS, so we expect to
|
||||
// get an 'RequestNotSupported' error here.
|
||||
return getNeighboringCellIds()
|
||||
.then(() => {
|
||||
ok(false, "should not success");
|
||||
}, (aErrorMsg) => {
|
||||
is(aErrorMsg, "RequestNotSupported",
|
||||
"Failed to getNeighboringCellIds: " + aErrorMsg);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -10,6 +10,12 @@ function verifyVoiceCellLocationInfo(aLac, aCid) {
|
||||
|
||||
is(cell.gsmLocationAreaCode, aLac, "check voice.cell.gsmLocationAreaCode");
|
||||
is(cell.gsmCellId, aCid, "check voice.cell.gsmCellId");
|
||||
|
||||
// TODO: Since gecko doesn't reset these values below to their invalid values,
|
||||
// the tests below will fail after we once change to CDMA mode. Please refer
|
||||
// to Bug 1190274 for more information.
|
||||
|
||||
/*
|
||||
is(cell.cdmaBaseStationId, -1, "check voice.cell.cdmaBaseStationId");
|
||||
is(cell.cdmaBaseStationLatitude, -2147483648,
|
||||
"check voice.cell.cdmaBaseStationLatitude");
|
||||
@@ -17,6 +23,7 @@ function verifyVoiceCellLocationInfo(aLac, aCid) {
|
||||
"check voice.cell.cdmaBaseStationLongitude");
|
||||
is(cell.cdmaSystemId, -1, "check voice.cell.cdmaSystemId");
|
||||
is(cell.cdmaNetworkId, -1, "check voice.cell.cdmaNetworkId");
|
||||
*/
|
||||
}
|
||||
|
||||
/* Test Voice Cell Location Info Change */
|
||||
|
||||
@@ -4,25 +4,6 @@
|
||||
MARIONETTE_TIMEOUT = 60000;
|
||||
MARIONETTE_HEAD_JS = "head.js";
|
||||
|
||||
const INITIAL_STATES = {
|
||||
state: "registered",
|
||||
connected: true,
|
||||
emergencyCallsOnly: false,
|
||||
roaming: false,
|
||||
signalStrength: -99,
|
||||
relSignalStrength: 44,
|
||||
|
||||
cell: {
|
||||
gsmLocationAreaCode: 0,
|
||||
gsmCellId: 0,
|
||||
cdmaBaseStationId: -1,
|
||||
cdmaBaseStationLatitude: -2147483648,
|
||||
cdmaBaseStationLongitude: -2147483648,
|
||||
cdmaSystemId: -1,
|
||||
cdmaNetworkId: -1,
|
||||
}
|
||||
};
|
||||
|
||||
const TEST_DATA = [{
|
||||
// Test state becomes to "unregistered"
|
||||
state: "unregistered",
|
||||
@@ -126,8 +107,6 @@ function testVoiceStateUpdate(aNewState, aExpected) {
|
||||
startTestCommon(function() {
|
||||
log("Test initial voice connection info");
|
||||
|
||||
verifyVoiceInfo(INITIAL_STATES);
|
||||
|
||||
let promise = Promise.resolve();
|
||||
for (let i = 0; i < TEST_DATA.length; i++) {
|
||||
let entry = TEST_DATA[i];
|
||||
|
||||
@@ -11,12 +11,14 @@ UNIFIED_SOURCES += [
|
||||
'RemoteSpellCheckEngineParent.cpp',
|
||||
]
|
||||
|
||||
CXXFLAGS += CONFIG['MOZ_HUNSPELL_CFLAGS']
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
||||
if CONFIG['MOZ_SYSTEM_HUNSPELL']:
|
||||
CXXFLAGS += CONFIG['MOZ_HUNSPELL_CFLAGS']
|
||||
else:
|
||||
LOCAL_INCLUDES += ['../src']
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'../src',
|
||||
'/dom/base',
|
||||
'/editor/libeditor',
|
||||
'/extensions/spellcheck/src',
|
||||
|
||||
@@ -17,9 +17,13 @@ SOURCES += [
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
||||
if CONFIG['MOZ_SYSTEM_HUNSPELL']:
|
||||
CXXFLAGS += CONFIG['MOZ_HUNSPELL_CFLAGS']
|
||||
else:
|
||||
LOCAL_INCLUDES += ['../hunspell/src']
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'../hunspell/glue',
|
||||
'../hunspell/src',
|
||||
'/dom/base',
|
||||
'/editor/libeditor',
|
||||
]
|
||||
|
||||
@@ -1178,7 +1178,7 @@ DrawTargetCairo::ClearRect(const Rect& aRect)
|
||||
|
||||
AutoPrepareForDrawing prep(this, mContext);
|
||||
|
||||
if (!mContext || aRect.Width() <= 0 || aRect.Height() <= 0 ||
|
||||
if (!mContext || aRect.Width() < 0 || aRect.Height() < 0 ||
|
||||
!IsFinite(aRect.X()) || !IsFinite(aRect.Width()) ||
|
||||
!IsFinite(aRect.Y()) || !IsFinite(aRect.Height())) {
|
||||
gfxCriticalNote << "ClearRect with invalid argument " << gfx::hexa(mContext) << " with " << aRect.Width() << "x" << aRect.Height() << " [" << aRect.X() << ", " << aRect.Y() << "]";
|
||||
|
||||
@@ -363,7 +363,7 @@ DrawTargetD2D1::CopySurface(SourceSurface *aSurface,
|
||||
mDC->SetTransform(D2D1::IdentityMatrix());
|
||||
mTransformDirty = true;
|
||||
|
||||
Matrix mat;
|
||||
Matrix mat = Matrix::Translation(aDestination.x - aSourceRect.x, aDestination.y - aSourceRect.y);
|
||||
RefPtr<ID2D1Image> image = GetImageForSurface(aSurface, mat, ExtendMode::CLAMP);
|
||||
|
||||
if (!image) {
|
||||
@@ -371,11 +371,17 @@ DrawTargetD2D1::CopySurface(SourceSurface *aSurface,
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mat.IsIdentity()) {
|
||||
gfxDebug() << *this << ": At this point complex partial uploads are not supported for CopySurface.";
|
||||
if (mat.HasNonIntegerTranslation()) {
|
||||
gfxDebug() << *this << ": At this point scaled partial uploads are not supported for CopySurface.";
|
||||
return;
|
||||
}
|
||||
|
||||
IntRect sourceRect = aSourceRect;
|
||||
sourceRect.x += (aDestination.x - aSourceRect.x) - mat._31;
|
||||
sourceRect.width -= (aDestination.x - aSourceRect.x) - mat._31;
|
||||
sourceRect.y += (aDestination.y - aSourceRect.y) - mat._32;
|
||||
sourceRect.height -= (aDestination.y - aSourceRect.y) - mat._32;
|
||||
|
||||
RefPtr<ID2D1Bitmap> bitmap;
|
||||
image->QueryInterface((ID2D1Bitmap**)getter_AddRefs(bitmap));
|
||||
|
||||
@@ -391,7 +397,7 @@ DrawTargetD2D1::CopySurface(SourceSurface *aSurface,
|
||||
return;
|
||||
}
|
||||
|
||||
Rect srcRect(Float(aSourceRect.x), Float(aSourceRect.y),
|
||||
Rect srcRect(Float(sourceRect.x), Float(sourceRect.y),
|
||||
Float(aSourceRect.width), Float(aSourceRect.height));
|
||||
|
||||
Rect dstRect(Float(aDestination.x), Float(aDestination.y),
|
||||
|
||||
@@ -131,6 +131,9 @@ public:
|
||||
bool Init(ID3D11Texture2D* aTexture, SurfaceFormat aFormat);
|
||||
uint32_t GetByteSize() const;
|
||||
|
||||
// This function will get an image for a surface, it may adjust the source
|
||||
// transform for any transformation of the resulting image relative to the
|
||||
// oritingal SourceSurface.
|
||||
already_AddRefed<ID2D1Image> GetImageForSurface(SourceSurface *aSurface, Matrix &aSourceTransform,
|
||||
ExtendMode aExtendMode, const IntRect* aSourceRect = nullptr);
|
||||
|
||||
|
||||
@@ -389,10 +389,6 @@ DrawTargetRecording::FillGlyphs(ScaledFont *aFont,
|
||||
{
|
||||
EnsurePatternDependenciesStored(aPattern);
|
||||
|
||||
if (aFont->GetType() != FontType::DWRITE && aFont->GetType() != FontType::GDI) {
|
||||
gfxDevCrash(LogReason::GetFontFileDataFailed) << "Unexpected ScaledFont type " << (int)aFont->GetType();
|
||||
}
|
||||
|
||||
if (!aFont->GetUserData(reinterpret_cast<UserDataKey*>(mRecorder.get()))) {
|
||||
// TODO support font in b2g recordings
|
||||
#ifndef MOZ_WIDGET_GONK
|
||||
|
||||
@@ -416,7 +416,8 @@ DrawTargetSkia::DrawSurfaceWithShadow(SourceSurface *aSurface,
|
||||
Float aSigma,
|
||||
CompositionOp aOperator)
|
||||
{
|
||||
if (!(aSurface->GetType() == SurfaceType::SKIA || aSurface->GetType() == SurfaceType::DATA)) {
|
||||
if (!(aSurface->GetType() == SurfaceType::SKIA || aSurface->GetType() == SurfaceType::DATA) ||
|
||||
aSurface->GetSize().IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -636,10 +637,19 @@ DrawTargetSkia::FillGlyphs(ScaledFont *aFont,
|
||||
// SkFontHost_cairo does not support subpixel text, so only enable it for other font hosts.
|
||||
paint.mPaint.setSubpixelText(true);
|
||||
|
||||
if (aFont->GetType() == FontType::MAC) {
|
||||
if (aFont->GetType() == FontType::MAC &&
|
||||
(shouldLCDRenderText || aOptions.mAntialiasMode == AntialiasMode::GRAY)) {
|
||||
// SkFontHost_mac only enables CG Font Smoothing if hinting is disabled.
|
||||
// CG Font Smoothing normally enables subpixel AA in CG, but Skia supports
|
||||
// font smoothing with grayscale AA.
|
||||
// SkFontHost_mac only supports subpixel antialiasing when hinting is turned off.
|
||||
// For grayscale AA, we want to disable font smoothing as the only time we should
|
||||
// use grayscale AA is with explicit -moz-osx-font-smoothing
|
||||
// We can get grayscale AA if we have -moz-osx-font-smoothing: grayscale
|
||||
// explicitly enabled or for transparent surfaces.
|
||||
// If we have AA grayscale explicit through the draw options,
|
||||
// then we want to disable font smoothing.
|
||||
// If we have a transparent surface, shouldLCDRenderText will be false. But unless
|
||||
// grayscale font smoothing is explicitly requested, we still want Skia to use
|
||||
// CG Font smoothing.
|
||||
paint.mPaint.setHinting(SkPaint::kNo_Hinting);
|
||||
} else {
|
||||
paint.mPaint.setHinting(SkPaint::kNormal_Hinting);
|
||||
|
||||
+67
-56
@@ -10,30 +10,42 @@
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
static float CubicRoot(float aValue) {
|
||||
static double CubicRoot(double aValue) {
|
||||
if (aValue < 0.0) {
|
||||
return -CubicRoot(-aValue);
|
||||
}
|
||||
else {
|
||||
return powf(aValue, 1.0f / 3.0f);
|
||||
return pow(aValue, 1.0 / 3.0);
|
||||
}
|
||||
}
|
||||
|
||||
struct PointD : public BasePoint<double, PointD> {
|
||||
typedef BasePoint<double, PointD> Super;
|
||||
|
||||
PointD() : Super() {}
|
||||
PointD(double aX, double aY) : Super(aX, aY) {}
|
||||
MOZ_IMPLICIT PointD(const Point& aPoint) : Super(aPoint.x, aPoint.y) {}
|
||||
|
||||
Point ToPoint() const {
|
||||
return Point(static_cast<Float>(x), static_cast<Float>(y));
|
||||
}
|
||||
};
|
||||
|
||||
struct BezierControlPoints
|
||||
{
|
||||
BezierControlPoints() {}
|
||||
BezierControlPoints(const Point &aCP1, const Point &aCP2,
|
||||
const Point &aCP3, const Point &aCP4)
|
||||
BezierControlPoints(const PointD &aCP1, const PointD &aCP2,
|
||||
const PointD &aCP3, const PointD &aCP4)
|
||||
: mCP1(aCP1), mCP2(aCP2), mCP3(aCP3), mCP4(aCP4)
|
||||
{
|
||||
}
|
||||
|
||||
Point mCP1, mCP2, mCP3, mCP4;
|
||||
PointD mCP1, mCP2, mCP3, mCP4;
|
||||
};
|
||||
|
||||
void
|
||||
FlattenBezier(const BezierControlPoints &aPoints,
|
||||
PathSink *aSink, Float aTolerance);
|
||||
PathSink *aSink, double aTolerance);
|
||||
|
||||
|
||||
Path::Path()
|
||||
@@ -205,18 +217,18 @@ static void
|
||||
SplitBezier(const BezierControlPoints &aControlPoints,
|
||||
BezierControlPoints *aFirstSegmentControlPoints,
|
||||
BezierControlPoints *aSecondSegmentControlPoints,
|
||||
Float t)
|
||||
double t)
|
||||
{
|
||||
MOZ_ASSERT(aSecondSegmentControlPoints);
|
||||
|
||||
*aSecondSegmentControlPoints = aControlPoints;
|
||||
|
||||
Point cp1a = aControlPoints.mCP1 + (aControlPoints.mCP2 - aControlPoints.mCP1) * t;
|
||||
Point cp2a = aControlPoints.mCP2 + (aControlPoints.mCP3 - aControlPoints.mCP2) * t;
|
||||
Point cp1aa = cp1a + (cp2a - cp1a) * t;
|
||||
Point cp3a = aControlPoints.mCP3 + (aControlPoints.mCP4 - aControlPoints.mCP3) * t;
|
||||
Point cp2aa = cp2a + (cp3a - cp2a) * t;
|
||||
Point cp1aaa = cp1aa + (cp2aa - cp1aa) * t;
|
||||
PointD cp1a = aControlPoints.mCP1 + (aControlPoints.mCP2 - aControlPoints.mCP1) * t;
|
||||
PointD cp2a = aControlPoints.mCP2 + (aControlPoints.mCP3 - aControlPoints.mCP2) * t;
|
||||
PointD cp1aa = cp1a + (cp2a - cp1a) * t;
|
||||
PointD cp3a = aControlPoints.mCP3 + (aControlPoints.mCP4 - aControlPoints.mCP3) * t;
|
||||
PointD cp2aa = cp2a + (cp3a - cp2a) * t;
|
||||
PointD cp1aaa = cp1aa + (cp2aa - cp1aa) * t;
|
||||
aSecondSegmentControlPoints->mCP4 = aControlPoints.mCP4;
|
||||
|
||||
if(aFirstSegmentControlPoints) {
|
||||
@@ -233,7 +245,7 @@ SplitBezier(const BezierControlPoints &aControlPoints,
|
||||
static void
|
||||
FlattenBezierCurveSegment(const BezierControlPoints &aControlPoints,
|
||||
PathSink *aSink,
|
||||
Float aTolerance)
|
||||
double aTolerance)
|
||||
{
|
||||
/* The algorithm implemented here is based on:
|
||||
* http://cis.usouthal.edu/~hain/general/Publications/Bezier/Bezier%20Offset%20Curves.pdf
|
||||
@@ -245,47 +257,46 @@ FlattenBezierCurveSegment(const BezierControlPoints &aControlPoints,
|
||||
*/
|
||||
BezierControlPoints currentCP = aControlPoints;
|
||||
|
||||
Float t = 0;
|
||||
while (t < 1.0f) {
|
||||
Point cp21 = currentCP.mCP2 - currentCP.mCP3;
|
||||
Point cp31 = currentCP.mCP3 - currentCP.mCP1;
|
||||
double t = 0;
|
||||
while (t < 1.0) {
|
||||
PointD cp21 = currentCP.mCP2 - currentCP.mCP3;
|
||||
PointD cp31 = currentCP.mCP3 - currentCP.mCP1;
|
||||
|
||||
/* To remove divisions and check for divide-by-zero, this is optimized from:
|
||||
* Float s3 = (cp31.x * cp21.y - cp31.y * cp21.x) / hypotf(cp21.x, cp21.y);
|
||||
* t = 2 * Float(sqrt(aTolerance / (3. * std::abs(s3))));
|
||||
*/
|
||||
Float cp21x31 = cp31.x * cp21.y - cp31.y * cp21.x;
|
||||
Float h = hypotf(cp21.x, cp21.y);
|
||||
double cp21x31 = cp31.x * cp21.y - cp31.y * cp21.x;
|
||||
double h = hypot(cp21.x, cp21.y);
|
||||
if (cp21x31 * h == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
Float s3inv = h / cp21x31;
|
||||
t = 2 * Float(sqrt(aTolerance * std::abs(s3inv) / 3.));
|
||||
if (t >= 1.0f) {
|
||||
double s3inv = h / cp21x31;
|
||||
t = 2 * sqrt(aTolerance * std::abs(s3inv) / 3.);
|
||||
if (t >= 1.0) {
|
||||
break;
|
||||
}
|
||||
|
||||
Point prevCP2, prevCP3, nextCP1, nextCP2, nextCP3;
|
||||
SplitBezier(currentCP, nullptr, ¤tCP, t);
|
||||
|
||||
aSink->LineTo(currentCP.mCP1);
|
||||
aSink->LineTo(currentCP.mCP1.ToPoint());
|
||||
}
|
||||
|
||||
aSink->LineTo(currentCP.mCP4);
|
||||
aSink->LineTo(currentCP.mCP4.ToPoint());
|
||||
}
|
||||
|
||||
static inline void
|
||||
FindInflectionApproximationRange(BezierControlPoints aControlPoints,
|
||||
Float *aMin, Float *aMax, Float aT,
|
||||
Float aTolerance)
|
||||
double *aMin, double *aMax, double aT,
|
||||
double aTolerance)
|
||||
{
|
||||
SplitBezier(aControlPoints, nullptr, &aControlPoints, aT);
|
||||
|
||||
Point cp21 = aControlPoints.mCP2 - aControlPoints.mCP1;
|
||||
Point cp41 = aControlPoints.mCP4 - aControlPoints.mCP1;
|
||||
PointD cp21 = aControlPoints.mCP2 - aControlPoints.mCP1;
|
||||
PointD cp41 = aControlPoints.mCP4 - aControlPoints.mCP1;
|
||||
|
||||
if (cp21.x == 0.f && cp21.y == 0.f) {
|
||||
if (cp21.x == 0. && cp21.y == 0.) {
|
||||
// In this case s3 becomes lim[n->0] (cp41.x * n) / n - (cp41.y * n) / n = cp41.x - cp41.y.
|
||||
|
||||
// Use the absolute value so that Min and Max will correspond with the
|
||||
@@ -295,18 +306,18 @@ FindInflectionApproximationRange(BezierControlPoints aControlPoints,
|
||||
return;
|
||||
}
|
||||
|
||||
Float s3 = (cp41.x * cp21.y - cp41.y * cp21.x) / hypotf(cp21.x, cp21.y);
|
||||
double s3 = (cp41.x * cp21.y - cp41.y * cp21.x) / hypot(cp21.x, cp21.y);
|
||||
|
||||
if (s3 == 0) {
|
||||
// This means within the precision we have it can be approximated
|
||||
// infinitely by a linear segment. Deal with this by specifying the
|
||||
// approximation range as extending beyond the entire curve.
|
||||
*aMin = -1.0f;
|
||||
*aMax = 2.0f;
|
||||
*aMin = -1.0;
|
||||
*aMax = 2.0;
|
||||
return;
|
||||
}
|
||||
|
||||
Float tf = CubicRoot(std::abs(aTolerance / s3));
|
||||
double tf = CubicRoot(std::abs(aTolerance / s3));
|
||||
|
||||
*aMin = aT - tf * (1 - aT);
|
||||
*aMax = aT + tf * (1 - aT);
|
||||
@@ -365,18 +376,18 @@ FindInflectionApproximationRange(BezierControlPoints aControlPoints,
|
||||
*/
|
||||
static inline void
|
||||
FindInflectionPoints(const BezierControlPoints &aControlPoints,
|
||||
Float *aT1, Float *aT2, uint32_t *aCount)
|
||||
double *aT1, double *aT2, uint32_t *aCount)
|
||||
{
|
||||
// Find inflection points.
|
||||
// See www.faculty.idc.ac.il/arik/quality/appendixa.html for an explanation
|
||||
// of this approach.
|
||||
Point A = aControlPoints.mCP2 - aControlPoints.mCP1;
|
||||
Point B = aControlPoints.mCP3 - (aControlPoints.mCP2 * 2) + aControlPoints.mCP1;
|
||||
Point C = aControlPoints.mCP4 - (aControlPoints.mCP3 * 3) + (aControlPoints.mCP2 * 3) - aControlPoints.mCP1;
|
||||
PointD A = aControlPoints.mCP2 - aControlPoints.mCP1;
|
||||
PointD B = aControlPoints.mCP3 - (aControlPoints.mCP2 * 2) + aControlPoints.mCP1;
|
||||
PointD C = aControlPoints.mCP4 - (aControlPoints.mCP3 * 3) + (aControlPoints.mCP2 * 3) - aControlPoints.mCP1;
|
||||
|
||||
Float a = Float(B.x) * C.y - Float(B.y) * C.x;
|
||||
Float b = Float(A.x) * C.y - Float(A.y) * C.x;
|
||||
Float c = Float(A.x) * B.y - Float(A.y) * B.x;
|
||||
double a = B.x * C.y - B.y * C.x;
|
||||
double b = A.x * C.y - A.y * C.x;
|
||||
double c = A.x * B.y - A.y * B.x;
|
||||
|
||||
if (a == 0) {
|
||||
// Not a quadratic equation.
|
||||
@@ -400,7 +411,7 @@ FindInflectionPoints(const BezierControlPoints &aControlPoints,
|
||||
*aCount = 1;
|
||||
return;
|
||||
} else {
|
||||
Float discriminant = b * b - 4 * a * c;
|
||||
double discriminant = b * b - 4 * a * c;
|
||||
|
||||
if (discriminant < 0) {
|
||||
// No inflection points.
|
||||
@@ -415,13 +426,13 @@ FindInflectionPoints(const BezierControlPoints &aControlPoints,
|
||||
* t1 = q / a
|
||||
* t2 = c / q
|
||||
*/
|
||||
Float q = sqrtf(discriminant);
|
||||
double q = sqrt(discriminant);
|
||||
if (b < 0) {
|
||||
q = b - q;
|
||||
} else {
|
||||
q = b + q;
|
||||
}
|
||||
q *= Float(-1./2);
|
||||
q *= -1./2;
|
||||
|
||||
*aT1 = q / a;
|
||||
*aT2 = c / q;
|
||||
@@ -437,10 +448,10 @@ FindInflectionPoints(const BezierControlPoints &aControlPoints,
|
||||
|
||||
void
|
||||
FlattenBezier(const BezierControlPoints &aControlPoints,
|
||||
PathSink *aSink, Float aTolerance)
|
||||
PathSink *aSink, double aTolerance)
|
||||
{
|
||||
Float t1;
|
||||
Float t2;
|
||||
double t1;
|
||||
double t2;
|
||||
uint32_t count;
|
||||
|
||||
FindInflectionPoints(aControlPoints, &t1, &t2, &count);
|
||||
@@ -451,7 +462,7 @@ FlattenBezier(const BezierControlPoints &aControlPoints,
|
||||
return;
|
||||
}
|
||||
|
||||
Float t1min = t1, t1max = t1, t2min = t2, t2max = t2;
|
||||
double t1min = t1, t1max = t1, t2min = t2, t2max = t2;
|
||||
|
||||
BezierControlPoints remainingCP = aControlPoints;
|
||||
|
||||
@@ -470,7 +481,7 @@ FlattenBezier(const BezierControlPoints &aControlPoints,
|
||||
// segments.
|
||||
if (count == 1 && t1min <= 0 && t1max >= 1.0) {
|
||||
// The whole range can be approximated by a line segment.
|
||||
aSink->LineTo(aControlPoints.mCP4);
|
||||
aSink->LineTo(aControlPoints.mCP4.ToPoint());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -487,7 +498,7 @@ FlattenBezier(const BezierControlPoints &aControlPoints,
|
||||
// subsequently flatten up until the end or the next inflection point.
|
||||
SplitBezier(aControlPoints, nullptr, &nextCPs, t1max);
|
||||
|
||||
aSink->LineTo(nextCPs.mCP1);
|
||||
aSink->LineTo(nextCPs.mCP1.ToPoint());
|
||||
|
||||
if (count == 1 || (count > 1 && t2min >= 1.0)) {
|
||||
// No more inflection points to deal with, flatten the rest of the curve.
|
||||
@@ -497,7 +508,7 @@ FlattenBezier(const BezierControlPoints &aControlPoints,
|
||||
// We've already concluded t2min <= t1max, so if this is true the
|
||||
// approximation range for the first inflection point runs past the
|
||||
// end of the curve, draw a line to the end and we're done.
|
||||
aSink->LineTo(aControlPoints.mCP4);
|
||||
aSink->LineTo(aControlPoints.mCP4.ToPoint());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -506,12 +517,12 @@ FlattenBezier(const BezierControlPoints &aControlPoints,
|
||||
// In this case the t2 approximation range starts inside the t1
|
||||
// approximation range.
|
||||
SplitBezier(aControlPoints, nullptr, &nextCPs, t1max);
|
||||
aSink->LineTo(nextCPs.mCP1);
|
||||
aSink->LineTo(nextCPs.mCP1.ToPoint());
|
||||
} else if (t2min > 0 && t1max > 0) {
|
||||
SplitBezier(aControlPoints, nullptr, &nextCPs, t1max);
|
||||
|
||||
// Find a control points describing the portion of the curve between t1max and t2min.
|
||||
Float t2mina = (t2min - t1max) / (1 - t1max);
|
||||
double t2mina = (t2min - t1max) / (1 - t1max);
|
||||
SplitBezier(nextCPs, &prevCPs, &nextCPs, t2mina);
|
||||
FlattenBezierCurveSegment(prevCPs, aSink, aTolerance);
|
||||
} else if (t2min > 0) {
|
||||
@@ -525,11 +536,11 @@ FlattenBezier(const BezierControlPoints &aControlPoints,
|
||||
|
||||
// Draw a line to the start, this is the approximation between t2min and
|
||||
// t2max.
|
||||
aSink->LineTo(nextCPs.mCP1);
|
||||
aSink->LineTo(nextCPs.mCP1.ToPoint());
|
||||
FlattenBezierCurveSegment(nextCPs, aSink, aTolerance);
|
||||
} else {
|
||||
// Our approximation range extends beyond the end of the curve.
|
||||
aSink->LineTo(aControlPoints.mCP4);
|
||||
aSink->LineTo(aControlPoints.mCP4.ToPoint());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
+35
-2
@@ -90,6 +90,31 @@ private:
|
||||
bool mNeedsFigureEnded;
|
||||
};
|
||||
|
||||
class MOZ_STACK_CLASS AutoRestoreFP
|
||||
{
|
||||
public:
|
||||
AutoRestoreFP()
|
||||
{
|
||||
// save the current floating point control word
|
||||
_controlfp_s(&savedFPSetting, 0, 0);
|
||||
UINT unused;
|
||||
// set the floating point control word to its default value
|
||||
_controlfp_s(&unused, _CW_DEFAULT, MCW_PC);
|
||||
}
|
||||
~AutoRestoreFP()
|
||||
{
|
||||
UINT unused;
|
||||
// restore the saved floating point control word
|
||||
_controlfp_s(&unused, savedFPSetting, MCW_PC);
|
||||
}
|
||||
private:
|
||||
UINT savedFPSetting;
|
||||
};
|
||||
|
||||
// Note that overrides of ID2D1SimplifiedGeometrySink methods in this class may
|
||||
// get called from D2D with nonstandard floating point settings (see comments in
|
||||
// bug 1134549) - use AutoRestoreFP to reset the floating point control word to
|
||||
// what we expect
|
||||
class StreamingGeometrySink : public ID2D1SimplifiedGeometrySink
|
||||
{
|
||||
public:
|
||||
@@ -129,11 +154,18 @@ public:
|
||||
STDMETHOD_(void, SetFillMode)(D2D1_FILL_MODE aMode)
|
||||
{ return; }
|
||||
STDMETHOD_(void, BeginFigure)(D2D1_POINT_2F aPoint, D2D1_FIGURE_BEGIN aBegin)
|
||||
{ mSink->MoveTo(ToPoint(aPoint)); }
|
||||
{
|
||||
AutoRestoreFP resetFloatingPoint;
|
||||
mSink->MoveTo(ToPoint(aPoint));
|
||||
}
|
||||
STDMETHOD_(void, AddLines)(const D2D1_POINT_2F *aLines, UINT aCount)
|
||||
{ for (UINT i = 0; i < aCount; i++) { mSink->LineTo(ToPoint(aLines[i])); } }
|
||||
{
|
||||
AutoRestoreFP resetFloatingPoint;
|
||||
for (UINT i = 0; i < aCount; i++) { mSink->LineTo(ToPoint(aLines[i])); }
|
||||
}
|
||||
STDMETHOD_(void, AddBeziers)(const D2D1_BEZIER_SEGMENT *aSegments, UINT aCount)
|
||||
{
|
||||
AutoRestoreFP resetFloatingPoint;
|
||||
for (UINT i = 0; i < aCount; i++) {
|
||||
mSink->BezierTo(ToPoint(aSegments[i].point1), ToPoint(aSegments[i].point2), ToPoint(aSegments[i].point3));
|
||||
}
|
||||
@@ -145,6 +177,7 @@ public:
|
||||
|
||||
STDMETHOD_(void, EndFigure)(D2D1_FIGURE_END aEnd)
|
||||
{
|
||||
AutoRestoreFP resetFloatingPoint;
|
||||
if (aEnd == D2D1_FIGURE_END_CLOSED) {
|
||||
return mSink->Close();
|
||||
}
|
||||
|
||||
@@ -659,7 +659,7 @@ private:
|
||||
|
||||
class RecordedPopLayer : public RecordedDrawingEvent {
|
||||
public:
|
||||
RecordedPopLayer(DrawTarget* aDT)
|
||||
MOZ_IMPLICIT RecordedPopLayer(DrawTarget* aDT)
|
||||
: RecordedDrawingEvent(POPLAYER, aDT)
|
||||
{
|
||||
}
|
||||
|
||||
+15
-8
@@ -116,7 +116,7 @@ SFNTData::Create(const uint8_t *aFontData, uint32_t aDataLength)
|
||||
|
||||
// Check to see if this is a font collection.
|
||||
if (aDataLength < sizeof(TTCHeader)) {
|
||||
gfxDevCrash(LogReason::GetFontFileDataFailed) << "Font data too short: length = " << aDataLength;
|
||||
gfxWarning() << "Font data too short.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ SFNTData::Create(const uint8_t *aFontData, uint32_t aDataLength)
|
||||
if (ttcHeader->ttcTag == TRUETYPE_TAG('t', 't', 'c', 'f')) {
|
||||
uint32_t numFonts = ttcHeader->numFonts;
|
||||
if (aDataLength < sizeof(TTCHeader) + (numFonts * sizeof(BigEndianUint32))) {
|
||||
gfxDevCrash(LogReason::GetFontFileDataFailed) << "Font data too short to contain full TTC Header: numFonts = " << numFonts << "; length = " << aDataLength;
|
||||
gfxWarning() << "Font data too short to contain full TTC Header.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -134,7 +134,6 @@ SFNTData::Create(const uint8_t *aFontData, uint32_t aDataLength)
|
||||
const BigEndianUint32* endOfOffsets = offset + numFonts;
|
||||
while (offset != endOfOffsets) {
|
||||
if (!sfntData->AddFont(aFontData, aDataLength, *offset)) {
|
||||
gfxDevCrash(LogReason::GetFontFileDataFailed) << "Failed to add font data from TTC";
|
||||
return nullptr;
|
||||
}
|
||||
++offset;
|
||||
@@ -145,7 +144,6 @@ SFNTData::Create(const uint8_t *aFontData, uint32_t aDataLength)
|
||||
|
||||
UniquePtr<SFNTData> sfntData(new SFNTData);
|
||||
if (!sfntData->AddFont(aFontData, aDataLength, 0)) {
|
||||
gfxDevCrash(LogReason::GetFontFileDataFailed) << "Failed to add single font data";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -206,11 +204,20 @@ SFNTData::GetU16FullNames(Vector<mozilla::u16string>& aU16FullNames)
|
||||
|
||||
bool
|
||||
SFNTData::GetIndexForU16Name(const mozilla::u16string& aU16FullName,
|
||||
uint32_t* aIndex)
|
||||
uint32_t* aIndex, size_t aTruncatedLen)
|
||||
{
|
||||
for (size_t i = 0; i < mFonts.length(); ++i) {
|
||||
mozilla::u16string name;
|
||||
if (mFonts[i]->GetU16FullName(name) && name == aU16FullName) {
|
||||
if (!mFonts[i]->GetU16FullName(name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (aTruncatedLen) {
|
||||
MOZ_ASSERT(aU16FullName.length() <= aTruncatedLen);
|
||||
name = name.substr(0, aTruncatedLen);
|
||||
}
|
||||
|
||||
if (name == aU16FullName) {
|
||||
*aIndex = i;
|
||||
return true;
|
||||
}
|
||||
@@ -225,7 +232,7 @@ SFNTData::AddFont(const uint8_t *aFontData, uint32_t aDataLength,
|
||||
{
|
||||
uint32_t remainingLength = aDataLength - aOffset;
|
||||
if (remainingLength < sizeof(OffsetTable)) {
|
||||
gfxCriticalError() << "Font data too short to contain OffsetTable: offset = " << aOffset << "; length = " << aDataLength;
|
||||
gfxWarning() << "Font data too short to contain OffsetTable " << aOffset;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -233,7 +240,7 @@ SFNTData::AddFont(const uint8_t *aFontData, uint32_t aDataLength,
|
||||
reinterpret_cast<const OffsetTable*>(aFontData + aOffset);
|
||||
if (remainingLength <
|
||||
sizeof(OffsetTable) + (offsetTable->numTables * sizeof(TableDirEntry))) {
|
||||
gfxCriticalError() << "Font data too short to contain tables. numTables = " << offsetTable->numTables << "; offset = " << aOffset << "; length = " << aDataLength;
|
||||
gfxWarning() << "Font data too short to contain tables.";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
+3
-1
@@ -70,9 +70,11 @@ public:
|
||||
*
|
||||
* @param aU16FullName full name to find.
|
||||
* @param aIndex out param for the index if found.
|
||||
* @param aTruncatedLen length to truncate the compared font name to.
|
||||
* @return true if the full name is successfully read.
|
||||
*/
|
||||
bool GetIndexForU16Name(const mozilla::u16string& aU16FullName, uint32_t* aIndex);
|
||||
bool GetIndexForU16Name(const mozilla::u16string& aU16FullName, uint32_t* aIndex,
|
||||
size_t aTruncatedLen = 0);
|
||||
|
||||
private:
|
||||
|
||||
|
||||
@@ -115,12 +115,42 @@ ScaledFontDWrite::GetPathForGlyphs(const GlyphBuffer &aBuffer, const DrawTarget
|
||||
|
||||
|
||||
#ifdef USE_SKIA
|
||||
// This can happen if we have mixed backends which create DWrite
|
||||
// fonts in a mixed environment. e.g. a cairo content backend
|
||||
// but Skia canvas backend.
|
||||
void
|
||||
ScaledFontDWrite::GetFontDataFromSystemFonts(IDWriteFactory* aFactory)
|
||||
{
|
||||
MOZ_ASSERT(mFontFace);
|
||||
RefPtr<IDWriteFontCollection> systemFonts;
|
||||
HRESULT hr = aFactory->GetSystemFontCollection(getter_AddRefs(systemFonts));
|
||||
if (FAILED(hr)) {
|
||||
gfxWarning() << "Failed to get system font collection from file data. Code: " << hexa(hr);
|
||||
return;
|
||||
}
|
||||
|
||||
hr = systemFonts->GetFontFromFontFace(mFontFace, getter_AddRefs(mFont));
|
||||
if (FAILED(hr)) {
|
||||
gfxWarning() << "Failed to get system font from font face. Code: " << hexa(hr);
|
||||
return;
|
||||
}
|
||||
|
||||
hr = mFont->GetFontFamily(getter_AddRefs(mFontFamily));
|
||||
if (FAILED(hr)) {
|
||||
gfxWarning() << "Failed to get font family from font face. Code: " << hexa(hr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SkTypeface*
|
||||
ScaledFontDWrite::GetSkTypeface()
|
||||
{
|
||||
MOZ_ASSERT(mFont);
|
||||
if (!mTypeface) {
|
||||
IDWriteFactory *factory = DrawTargetD2D1::GetDWriteFactory();
|
||||
if (!mFont || !mFontFamily) {
|
||||
GetFontDataFromSystemFonts(factory);
|
||||
}
|
||||
|
||||
mTypeface = SkCreateTypefaceFromDWriteFont(factory, mFontFace, mFont, mFontFamily);
|
||||
}
|
||||
return mTypeface;
|
||||
|
||||
@@ -46,8 +46,10 @@ public:
|
||||
|
||||
#ifdef USE_SKIA
|
||||
virtual SkTypeface* GetSkTypeface();
|
||||
void GetFontDataFromSystemFonts(IDWriteFactory* aFactory);
|
||||
#endif
|
||||
|
||||
// The font and font family are only used with Skia
|
||||
RefPtr<IDWriteFont> mFont;
|
||||
RefPtr<IDWriteFontFamily> mFontFamily;
|
||||
RefPtr<IDWriteFontFace> mFontFace;
|
||||
|
||||
@@ -40,7 +40,6 @@ ScaledFontWin::GetFontFileData(FontFileDataOutput aDataCallback, void *aBaton)
|
||||
table = 0;
|
||||
tableSize = ::GetFontData(dc.GetDC(), table, 0, nullptr, 0);
|
||||
if (tableSize == GDI_ERROR) {
|
||||
gfxDevCrash(LogReason::GetFontFileDataFailed) << "Failed to get font data from GDI";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -50,7 +49,6 @@ ScaledFontWin::GetFontFileData(FontFileDataOutput aDataCallback, void *aBaton)
|
||||
uint32_t sizeGot =
|
||||
::GetFontData(dc.GetDC(), table, 0, fontData.get(), tableSize);
|
||||
if (sizeGot != tableSize) {
|
||||
gfxDevCrash(LogReason::GetFontFileDataFailed) << "GDI did not return enough data for font: wanted " << tableSize << ", got " << sizeGot;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -60,15 +58,17 @@ ScaledFontWin::GetFontFileData(FontFileDataOutput aDataCallback, void *aBaton)
|
||||
UniquePtr<SFNTData> sfntData = SFNTData::Create(fontData.get(),
|
||||
tableSize);
|
||||
if (!sfntData) {
|
||||
gfxDevCrash(LogReason::GetFontFileDataFailed) << "Failed to create SFNTData for GetFontFileData.";
|
||||
gfxWarning() << "Failed to create SFNTData for GetFontFileData.";
|
||||
return false;
|
||||
}
|
||||
|
||||
// We cast here because for VS2015 char16_t != wchar_t, even though they are
|
||||
// both 16 bit.
|
||||
if (!sfntData->GetIndexForU16Name(
|
||||
reinterpret_cast<char16_t*>(mLogFont.lfFaceName), &index)) {
|
||||
gfxDevCrash(LogReason::GetFontFileDataFailed) << "Failed to get index for face name.";
|
||||
reinterpret_cast<char16_t*>(mLogFont.lfFaceName), &index, LF_FACESIZE - 1)) {
|
||||
gfxWarning() << "Failed to get index for face name.";
|
||||
gfxDevCrash(LogReason::GetFontFileDataFailed) <<
|
||||
"Failed to get index for face name |" << mLogFont.lfFaceName << "|.";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,8 @@ CairoFormatToSurfaceFormat(cairo_format_t format)
|
||||
return SurfaceFormat::B8G8R8A8;
|
||||
case CAIRO_FORMAT_RGB24:
|
||||
return SurfaceFormat::B8G8R8X8;
|
||||
case CAIRO_FORMAT_RGB16_565:
|
||||
return SurfaceFormat::R5G6B5_UINT16;
|
||||
case CAIRO_FORMAT_A8:
|
||||
return SurfaceFormat::A8;
|
||||
default:
|
||||
|
||||
@@ -322,13 +322,13 @@ void ConvolveHorizontally(const unsigned char* src_data,
|
||||
bool has_alpha, bool use_simd) {
|
||||
int width = filter.num_values();
|
||||
int processed = 0;
|
||||
#if defined(USE_SSE2)
|
||||
#if defined(USE_SSE2) || defined(_MIPS_ARCH_LOONGSON3A)
|
||||
int simd_width = width & ~3;
|
||||
if (use_simd && simd_width) {
|
||||
// SIMD implementation works with 4 pixels at a time.
|
||||
// Therefore we process as much as we can using SSE and then use
|
||||
// C implementation for leftovers
|
||||
ConvolveHorizontally_SSE2(src_data, filter, out_row);
|
||||
ConvolveHorizontally_SIMD(src_data, filter, out_row);
|
||||
processed = simd_width;
|
||||
}
|
||||
#endif
|
||||
|
||||
+14
-8
@@ -99,7 +99,8 @@ void ConvolveHorizontally_LS3(const unsigned char* src_data,
|
||||
".set arch=loongson3a \n\t"
|
||||
// Load 4 coefficients => duplicate 1st and 2nd of them for all channels.
|
||||
// [16] xx xx xx xx c3 c2 c1 c0
|
||||
"ldc1 %[coeffl], (%[fval]) \n\t"
|
||||
"gsldlc1 %[coeffl], 7(%[fval]) \n\t"
|
||||
"gsldrc1 %[coeffl], (%[fval]) \n\t"
|
||||
"xor %[coeffh], %[coeffh], %[coeffh] \n\t"
|
||||
// [16] xx xx xx xx c1 c1 c0 c0
|
||||
_mm_pshuflh(coeff16, coeff, shuf_50)
|
||||
@@ -170,7 +171,8 @@ void ConvolveHorizontally_LS3(const unsigned char* src_data,
|
||||
asm volatile (
|
||||
".set push \n\t"
|
||||
".set arch=loongson3a \n\t"
|
||||
"ldc1 %[coeffl], (%[fval]) \n\t"
|
||||
"gsldlc1 %[coeffl], 7(%[fval]) \n\t"
|
||||
"gsldrc1 %[coeffl], (%[fval]) \n\t"
|
||||
"xor %[coeffh], %[coeffh], %[coeffh] \n\t"
|
||||
// Mask out extra filter taps.
|
||||
"and %[coeffl], %[coeffl], %[mask] \n\t"
|
||||
@@ -305,7 +307,8 @@ void ConvolveHorizontally4_LS3(const unsigned char* src_data[4],
|
||||
".set push \n\t"
|
||||
".set arch=loongson3a \n\t"
|
||||
// [16] xx xx xx xx c3 c2 c1 c0
|
||||
"ldc1 %[coeffl], (%[fval]) \n\t"
|
||||
"gsldlc1 %[coeffl], 7(%[fval]) \n\t"
|
||||
"gsldrc1 %[coeffl], (%[fval]) \n\t"
|
||||
"xor %[coeffh], %[coeffh], %[coeffh] \n\t"
|
||||
// [16] xx xx xx xx c1 c1 c0 c0
|
||||
_mm_pshuflh(coeff16lo, coeff, shuf_50)
|
||||
@@ -374,7 +377,8 @@ void ConvolveHorizontally4_LS3(const unsigned char* src_data[4],
|
||||
asm volatile (
|
||||
".set push \n\t"
|
||||
".set arch=loongson3a \n\t"
|
||||
"ldc1 %[coeffl], (%[fval]) \n\t"
|
||||
"gsldlc1 %[coeffl], 7(%[fval]) \n\t"
|
||||
"gsldrc1 %[coeffl], (%[fval]) \n\t"
|
||||
"xor %[coeffh], %[coeffh], %[coeffh] \n\t"
|
||||
// Mask out extra filter taps.
|
||||
"and %[coeffl], %[coeffl], %[mask] \n\t"
|
||||
@@ -500,7 +504,8 @@ void ConvolveVertically_LS3_impl(const ConvolutionFilter1D::Fixed* filter_values
|
||||
".set arch=loongson3a \n\t"
|
||||
// Duplicate the filter coefficient 8 times.
|
||||
// [16] cj cj cj cj cj cj cj cj
|
||||
"mtc1 %[fval], %[coeff16l] \n\t"
|
||||
"gsldlc1 %[coeff16l], 7+%[fval] \n\t"
|
||||
"gsldrc1 %[coeff16l], %[fval] \n\t"
|
||||
"pshufh %[coeff16l], %[coeff16l], %[zerol] \n\t"
|
||||
"mov.d %[coeff16h], %[coeff16l] \n\t"
|
||||
// Load four pixels (16 bytes) together.
|
||||
@@ -537,7 +542,7 @@ void ConvolveVertically_LS3_impl(const ConvolutionFilter1D::Fixed* filter_values
|
||||
[accum1h]"+f"(accum1h), [accum1l]"+f"(accum1l),
|
||||
[coeff16h]"=&f"(coeff16h), [coeff16l]"=&f"(coeff16l)
|
||||
:[zeroh]"f"(zero), [zerol]"f"(zero),
|
||||
[fval]"r"(filter_values[filter_y]),
|
||||
[fval]"m"(filter_values[filter_y]),
|
||||
[src]"r"(src)
|
||||
);
|
||||
|
||||
@@ -675,7 +680,8 @@ void ConvolveVertically_LS3_impl(const ConvolutionFilter1D::Fixed* filter_values
|
||||
asm volatile (
|
||||
".set push \n\t"
|
||||
".set arch=loongson3a \n\t"
|
||||
"mtc1 %[fval], %[coeff16l] \n\t"
|
||||
"gsldlc1 %[coeff16l], 7+%[fval] \n\t"
|
||||
"gsldrc1 %[coeff16l], %[fval] \n\t"
|
||||
"pshufh %[coeff16l], %[coeff16l], %[zerol] \n\t"
|
||||
"mov.d %[coeff16h], %[coeff16l] \n\t"
|
||||
// [8] a3 b3 g3 r3 a2 b2 g2 r2 a1 b1 g1 r1 a0 b0 g0 r0
|
||||
@@ -711,7 +717,7 @@ void ConvolveVertically_LS3_impl(const ConvolutionFilter1D::Fixed* filter_values
|
||||
[accum2h]"+f"(accum2h), [accum2l]"+f"(accum2l),
|
||||
[coeff16h]"=&f"(coeff16h), [coeff16l]"=&f"(coeff16l)
|
||||
:[zeroh]"f"(zero), [zerol]"f"(zero),
|
||||
[fval]"r"(filter_values[filter_y]),
|
||||
[fval]"m"(filter_values[filter_y]),
|
||||
[src]"r"(src)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -582,7 +582,9 @@ gl::Error StateManager11::setDepthStencilState(const gl::State &glState)
|
||||
|
||||
gl::Error StateManager11::setRasterizerState(const gl::RasterizerState &rasterState)
|
||||
{
|
||||
if (!mRasterizerStateIsDirty)
|
||||
// TODO: Remove pointDrawMode and multiSample from gl::RasterizerState.
|
||||
if (!mRasterizerStateIsDirty && rasterState.pointDrawMode == mCurRasterState.pointDrawMode &&
|
||||
rasterState.multiSample == mCurRasterState.multiSample)
|
||||
{
|
||||
return gl::Error(GL_NO_ERROR);
|
||||
}
|
||||
|
||||
@@ -434,6 +434,84 @@ TEST_P(PointSpritesTest, PointSizeDeclaredButUnused)
|
||||
glDeleteProgram(program);
|
||||
}
|
||||
|
||||
// Test to cover a bug where the D3D11 rasterizer state would not be update when switching between
|
||||
// draw types. This causes the cull face to potentially be incorrect when drawing emulated point
|
||||
// spites.
|
||||
TEST_P(PointSpritesTest, PointSpriteAlternatingDrawTypes)
|
||||
{
|
||||
// clang-format off
|
||||
const std::string pointFS = SHADER_SOURCE
|
||||
(
|
||||
precision mediump float;
|
||||
void main()
|
||||
{
|
||||
gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
|
||||
}
|
||||
);
|
||||
|
||||
const std::string pointVS = SHADER_SOURCE
|
||||
(
|
||||
void main()
|
||||
{
|
||||
gl_PointSize = 16.0;
|
||||
gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
);
|
||||
|
||||
const std::string quadFS = SHADER_SOURCE
|
||||
(
|
||||
precision mediump float;
|
||||
void main()
|
||||
{
|
||||
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
);
|
||||
|
||||
const std::string quadVS = SHADER_SOURCE
|
||||
(
|
||||
precision mediump float;
|
||||
attribute vec4 pos;
|
||||
void main()
|
||||
{
|
||||
gl_Position = pos;
|
||||
}
|
||||
);
|
||||
// clang-format on
|
||||
|
||||
GLuint pointProgram = CompileProgram(pointVS, pointFS);
|
||||
ASSERT_NE(pointProgram, 0u);
|
||||
ASSERT_GL_NO_ERROR();
|
||||
|
||||
GLuint quadProgram = CompileProgram(quadVS, quadFS);
|
||||
ASSERT_NE(pointProgram, 0u);
|
||||
ASSERT_GL_NO_ERROR();
|
||||
|
||||
glEnable(GL_CULL_FACE);
|
||||
glCullFace(GL_FRONT);
|
||||
|
||||
const GLfloat quadVertices[] = {
|
||||
-1.0f, 1.0f, 0.5f, 1.0f, -1.0f, 0.5f, -1.0f, -1.0f, 0.5f,
|
||||
|
||||
-1.0f, 1.0f, 0.5f, 1.0f, 1.0f, 0.5f, 1.0f, -1.0f, 0.5f,
|
||||
};
|
||||
|
||||
glUseProgram(quadProgram);
|
||||
GLint positionLocation = glGetAttribLocation(quadProgram, "pos");
|
||||
glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices);
|
||||
glEnableVertexAttribArray(positionLocation);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
|
||||
glUseProgram(pointProgram);
|
||||
glDrawArrays(GL_POINTS, 0, 1);
|
||||
ASSERT_GL_NO_ERROR();
|
||||
|
||||
// expect the center pixel to be green
|
||||
EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 255, 0, 255);
|
||||
|
||||
glDeleteProgram(pointProgram);
|
||||
glDeleteProgram(quadProgram);
|
||||
}
|
||||
|
||||
// Use this to select which configurations (e.g. which renderer, which GLES
|
||||
// major version) these tests should be run against.
|
||||
//
|
||||
|
||||
@@ -0,0 +1,349 @@
|
||||
<?xml version="1.0"?>
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1000" height="800">
|
||||
<title>Touch input event flow on B2G</title>
|
||||
<g id="arrows"></g>
|
||||
<style type="text/css"><![CDATA[
|
||||
text {
|
||||
fill: black;
|
||||
text-anchor: middle;
|
||||
white-space: pre-line;
|
||||
font-size: 14px;
|
||||
}
|
||||
rect {
|
||||
fill: none;
|
||||
}
|
||||
line {
|
||||
stroke: black;
|
||||
}
|
||||
.parentinput rect {
|
||||
stroke: black;
|
||||
}
|
||||
text.parentinput {
|
||||
fill: black;
|
||||
text-anchor: start;
|
||||
}
|
||||
.parentmain rect {
|
||||
stroke: orange;
|
||||
}
|
||||
text.parentmain {
|
||||
fill: orange;
|
||||
text-anchor: start;
|
||||
}
|
||||
.parentcompositor rect {
|
||||
stroke: green;
|
||||
}
|
||||
text.parentcompositor {
|
||||
fill: green;
|
||||
text-anchor: start;
|
||||
}
|
||||
.childmain rect {
|
||||
stroke: red;
|
||||
}
|
||||
text.childmain {
|
||||
fill: red;
|
||||
text-anchor: start;
|
||||
}
|
||||
.bothmain rect {
|
||||
stroke: blue;
|
||||
}
|
||||
text.bothmain {
|
||||
fill: blue;
|
||||
text-anchor: start;
|
||||
}
|
||||
]]></style>
|
||||
<script type="text/javascript"><![CDATA[
|
||||
var svg = "http://www.w3.org/2000/svg";
|
||||
var maxY = 0;
|
||||
|
||||
function breaks(text) {
|
||||
var count = 0;
|
||||
for (var i = text.length - 1; i >= 0; i--) {
|
||||
if (text.charAt(i) == '\n') {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
function makeAction(text, x, y, thread) {
|
||||
maxY = Math.max(maxY, y);
|
||||
var g = document.createElementNS(svg, "g");
|
||||
g.setAttribute("class", "action " + thread);
|
||||
g.setAttribute("transform", "translate(" + x + ", " + (y + 30) + ")");
|
||||
var r = document.createElementNS(svg, "rect");
|
||||
r.setAttribute("width", "100");
|
||||
r.setAttribute("height", "40");
|
||||
var t = document.createElementNS(svg, "text");
|
||||
t.setAttribute("x", "50");
|
||||
t.setAttribute("y", 25 - (7 * breaks(text)));
|
||||
t.appendChild(document.createTextNode(text));
|
||||
g.appendChild(r);
|
||||
g.appendChild(t);
|
||||
return g;
|
||||
}
|
||||
|
||||
function makeChoice(text, x, y, thread) {
|
||||
maxY = Math.max(maxY, y);
|
||||
var g = document.createElementNS(svg, "g");
|
||||
g.setAttribute("class", "choice " + thread);
|
||||
g.setAttribute("transform", "translate(" + (x + 15) + ", " + (y + 15) + ")");
|
||||
var g2 = document.createElementNS(svg, "g");
|
||||
g2.setAttribute("transform", "rotate(-45, 35, 35)");
|
||||
var r = document.createElementNS(svg, "rect");
|
||||
r.setAttribute("width", "70");
|
||||
r.setAttribute("height", "70");
|
||||
g2.appendChild(r);
|
||||
var t = document.createElementNS(svg, "text");
|
||||
t.setAttribute("x", "35");
|
||||
t.setAttribute("y", 40 - (7 * breaks(text)));
|
||||
t.appendChild(document.createTextNode(text));
|
||||
g.appendChild(g2);
|
||||
g.appendChild(t);
|
||||
return g;
|
||||
}
|
||||
|
||||
function makeLabelChoice(label, point) {
|
||||
var t = document.createElementNS(svg, "text");
|
||||
t.setAttribute("x", point.x);
|
||||
t.setAttribute("y", point.y);
|
||||
t.appendChild(document.createTextNode(label));
|
||||
return t;
|
||||
}
|
||||
|
||||
function makeLine(sx, sy, ex, ey) {
|
||||
maxY = Math.max(maxY, sy, ey);
|
||||
var l = document.createElementNS(svg, "line");
|
||||
l.setAttribute("x1", sx);
|
||||
l.setAttribute("y1", sy);
|
||||
l.setAttribute("x2", ex);
|
||||
l.setAttribute("y2", ey);
|
||||
return l;
|
||||
}
|
||||
|
||||
function makeArrow(start, end) {
|
||||
var g = document.createElementNS(svg, "g");
|
||||
g.appendChild(makeLine(start.x, start.y, end.x, end.y));
|
||||
if (start.x != end.x) {
|
||||
start.x = end.x + (4 * Math.sign(start.x - end.x));
|
||||
g.appendChild(makeLine(start.x, start.y - 4, end.x, end.y));
|
||||
g.appendChild(makeLine(start.x, start.y + 4, end.x, end.y));
|
||||
} else if (start.y != end.y) {
|
||||
start.y = end.y + (4 * Math.sign(start.y - end.y));
|
||||
g.appendChild(makeLine(start.x - 4, start.y, end.x, end.y));
|
||||
g.appendChild(makeLine(start.x + 4, start.y, end.x, end.y));
|
||||
}
|
||||
return g;
|
||||
}
|
||||
|
||||
function makeVHArrow(start, end) {
|
||||
var g = document.createElementNS(svg, "g");
|
||||
g.appendChild(makeLine(start.x, start.y, start.x, end.y));
|
||||
start.y = end.y;
|
||||
g.appendChild(makeArrow(start, end));
|
||||
return g;
|
||||
}
|
||||
|
||||
function makeHVArrow(start, end) {
|
||||
var g = document.createElementNS(svg, "g");
|
||||
g.appendChild(makeLine(start.x, start.y, end.x, start.y));
|
||||
start.x = end.x;
|
||||
g.appendChild(makeArrow(start, end));
|
||||
return g;
|
||||
}
|
||||
|
||||
function makeVHVArrow(start, end, length) {
|
||||
var g = document.createElementNS(svg, "g");
|
||||
g.appendChild(makeLine(start.x, start.y, start.x, start.y + length));
|
||||
start.y += length;
|
||||
g.appendChild(makeLine(start.x, start.y, end.x, start.y));
|
||||
start.x = end.x;
|
||||
g.appendChild(makeArrow(start, end));
|
||||
return g;
|
||||
}
|
||||
|
||||
function makeHVHArrow(start, end, length) {
|
||||
var g = document.createElementNS(svg, "g");
|
||||
g.appendChild(makeLine(start.x, start.y, start.x + length, start.y));
|
||||
start.x += length;
|
||||
g.appendChild(makeLine(start.x, start.y, start.x, end.y));
|
||||
start.y = end.y;
|
||||
g.appendChild(makeArrow(start, end));
|
||||
return g;
|
||||
}
|
||||
|
||||
function translation(group) {
|
||||
var r = new RegExp("translate\\((\\d+), (\\d+)\\)");
|
||||
var result = r.exec(group.getAttribute("transform"));
|
||||
return { x: parseInt(result[1]), y: parseInt(result[2]) };
|
||||
}
|
||||
|
||||
function isAction(group) {
|
||||
return group.classList.contains("action");
|
||||
}
|
||||
|
||||
function isChoice(group) {
|
||||
return group.classList.contains("choice");
|
||||
}
|
||||
|
||||
function offset(point, x, y) {
|
||||
point.x += x;
|
||||
point.y += y;
|
||||
return point;
|
||||
}
|
||||
|
||||
function rightOf(group) {
|
||||
var t = translation(group);
|
||||
if (isAction(group)) {
|
||||
return offset(t, 100, 20);
|
||||
}
|
||||
if (isChoice(group)) {
|
||||
return offset(t, 85, 35);
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
function leftOf(group) {
|
||||
var t = translation(group);
|
||||
if (isAction(group)) {
|
||||
return offset(t, 0, 20);
|
||||
}
|
||||
if (isChoice(group)) {
|
||||
return offset(t, -15, 35);
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
function topOf(group) {
|
||||
var t = translation(group);
|
||||
if (isAction(group)) {
|
||||
return offset(t, 50, 0);
|
||||
}
|
||||
if (isChoice(group)) {
|
||||
return offset(t, 35, -15);
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
function bottomOf(group) {
|
||||
var t = translation(group);
|
||||
if (isAction(group)) {
|
||||
return offset(t, 50, 40);
|
||||
}
|
||||
if (isChoice(group)) {
|
||||
return offset(t, 35, 85);
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
function midpoint(start, end) {
|
||||
return { x: (start.x + end.x) / 2,
|
||||
y: (start.y + end.y) / 2 };
|
||||
}
|
||||
|
||||
function makeLegend(label, thread) {
|
||||
var t = document.createElementNS(svg, "text");
|
||||
t.setAttribute("x", "10");
|
||||
t.setAttribute("y", maxY);
|
||||
t.setAttribute("class", thread);
|
||||
maxY += 15;
|
||||
t.appendChild(document.createTextNode(label));
|
||||
return t;
|
||||
}
|
||||
|
||||
var android = makeAction("Android/Gonk", 20, 0, "parentinput");
|
||||
var sendNative = makeAction("DOMWindowUtils\nsendNativeTouchPoint", 20, 100, "parentmain");
|
||||
var apzHitTest = makeAction("APZ hit test", 150, 0, "parentcompositor");
|
||||
var apzUntransform = makeAction("APZ\nuntransform", 300, 0, "parentcompositor");
|
||||
var apzGesture = makeAction("APZ gesture\ndetection", 450, 0, "parentcompositor");
|
||||
var apzTransform = makeAction("APZ transform\nupdate", 600, 0, "parentcompositor");
|
||||
var compositor = makeAction("Compositor", 750, 0, "parentcompositor");
|
||||
var nsAppShell = makeAction("nsAppShell", 150, 100, "parentmain");
|
||||
var rootHitTest = makeAction("Gecko hit test\n(root process)", 300, 100, "parentmain");
|
||||
var rootEsm = makeAction("Gecko ESM\n(root process)", 450, 100, "parentmain");
|
||||
var isEdgeGesture = makeChoice("Edge gesture?", 300, 200, "parentmain");
|
||||
var edgeConsume = makeAction("Consume\nevent block", 150, 200, "parentmain");
|
||||
var bepjsm = makeAction("BEParent.jsm\nsendTouchEvent", 450, 200, "parentmain");
|
||||
var iframeSend = makeAction("HTMLIFrameElement\nsendTouchEvent", 20, 275, "parentmain");
|
||||
var isApzTarget = makeChoice("Target\nhas APZ?", 600, 200, "parentmain");
|
||||
var sendTouchEvent = makeAction("Target\nsendTouchEventToWindow", 750, 100, "parentmain");
|
||||
var injectTouch = makeAction("injectTouchEvent", 750, 200, "parentmain");
|
||||
var targetESM = makeAction("Target window\nESM", 750, 450, "bothmain");
|
||||
var tabParent = makeAction("TabParent", 750, 350, "parentmain");
|
||||
var geckoUntransform = makeAction("Gecko\nuntransform", 600, 350, "parentmain");
|
||||
var tabChild = makeAction("TabChild", 450, 350, "childmain");
|
||||
var isApzcEnabled = makeChoice("APZ\nenabled?", 300, 350, "childmain");
|
||||
var tabGesture = makeAction("TabChild gesture\ndetection", 150, 350, "childmain");
|
||||
var childHitTest = makeAction("Gecko hit test\n(child process)", 300, 450, "childmain");
|
||||
var childEsm = makeAction("Gecko ESM\n(child process)", 450, 450, "childmain");
|
||||
var childContent = makeAction("Content\n(child process)", 600, 450, "childmain");
|
||||
|
||||
document.documentElement.appendChild(android);
|
||||
document.documentElement.appendChild(sendNative);
|
||||
document.documentElement.appendChild(apzHitTest);
|
||||
document.documentElement.appendChild(apzUntransform);
|
||||
document.documentElement.appendChild(apzGesture);
|
||||
document.documentElement.appendChild(apzTransform);
|
||||
document.documentElement.appendChild(compositor);
|
||||
document.documentElement.appendChild(nsAppShell);
|
||||
document.documentElement.appendChild(rootHitTest);
|
||||
document.documentElement.appendChild(rootEsm);
|
||||
document.documentElement.appendChild(isEdgeGesture);
|
||||
document.documentElement.appendChild(edgeConsume);
|
||||
document.documentElement.appendChild(bepjsm);
|
||||
document.documentElement.appendChild(iframeSend);
|
||||
document.documentElement.appendChild(isApzTarget);
|
||||
document.documentElement.appendChild(sendTouchEvent);
|
||||
document.documentElement.appendChild(injectTouch);
|
||||
document.documentElement.appendChild(targetESM);
|
||||
document.documentElement.appendChild(tabParent);
|
||||
document.documentElement.appendChild(geckoUntransform);
|
||||
document.documentElement.appendChild(tabChild);
|
||||
document.documentElement.appendChild(isApzcEnabled);
|
||||
document.documentElement.appendChild(tabGesture);
|
||||
document.documentElement.appendChild(childHitTest);
|
||||
document.documentElement.appendChild(childEsm);
|
||||
document.documentElement.appendChild(childContent);
|
||||
|
||||
document.documentElement.appendChild(makeLabelChoice("Y", offset(leftOf(isEdgeGesture), -5, -5)));
|
||||
document.documentElement.appendChild(makeLabelChoice("N", offset(rightOf(isEdgeGesture), 5, -5)));
|
||||
document.documentElement.appendChild(makeLabelChoice("N", offset(topOf(isApzTarget), 8, -10)));
|
||||
document.documentElement.appendChild(makeLabelChoice("Y", offset(rightOf(isApzTarget), 10, 14)));
|
||||
document.documentElement.appendChild(makeLabelChoice("N", offset(leftOf(isApzcEnabled), -5, -5)));
|
||||
document.documentElement.appendChild(makeLabelChoice("Y", offset(bottomOf(isApzcEnabled), 10, 14)));
|
||||
|
||||
var arrows = document.getElementById('arrows');
|
||||
arrows.appendChild(makeArrow(rightOf(android), leftOf(apzHitTest)));
|
||||
arrows.appendChild(makeVHVArrow(topOf(sendNative), midpoint(rightOf(android), leftOf(apzHitTest)), -20));
|
||||
arrows.appendChild(makeArrow(rightOf(apzHitTest), leftOf(apzUntransform)));
|
||||
arrows.appendChild(makeArrow(rightOf(apzUntransform), leftOf(apzGesture)));
|
||||
arrows.appendChild(makeArrow(rightOf(apzGesture), leftOf(apzTransform)));
|
||||
arrows.appendChild(makeArrow(rightOf(apzTransform), leftOf(compositor)));
|
||||
arrows.appendChild(makeVHVArrow(midpoint(leftOf(apzUntransform), rightOf(apzGesture)), topOf(nsAppShell), 40));
|
||||
arrows.appendChild(makeArrow(rightOf(nsAppShell), leftOf(rootHitTest)));
|
||||
arrows.appendChild(makeArrow(rightOf(rootHitTest), leftOf(rootEsm)));
|
||||
arrows.appendChild(makeVHVArrow(bottomOf(rootEsm), topOf(isEdgeGesture), 15));
|
||||
arrows.appendChild(makeArrow(leftOf(isEdgeGesture), rightOf(edgeConsume)));
|
||||
arrows.appendChild(makeArrow(rightOf(isEdgeGesture), leftOf(bepjsm), 20));
|
||||
arrows.appendChild(makeHVArrow(rightOf(iframeSend), bottomOf(bepjsm)));
|
||||
arrows.appendChild(makeArrow(rightOf(bepjsm), leftOf(isApzTarget)));
|
||||
arrows.appendChild(makeArrow(rightOf(isApzTarget), leftOf(injectTouch)));
|
||||
arrows.appendChild(makeArrow(bottomOf(injectTouch), topOf(tabParent)));
|
||||
arrows.appendChild(makeVHArrow(topOf(isApzTarget), leftOf(sendTouchEvent)));
|
||||
arrows.appendChild(makeHVHArrow(rightOf(sendTouchEvent), rightOf(targetESM), 30));
|
||||
arrows.appendChild(makeArrow(leftOf(tabParent), rightOf(geckoUntransform)));
|
||||
arrows.appendChild(makeArrow(leftOf(geckoUntransform), rightOf(tabChild)));
|
||||
arrows.appendChild(makeArrow(leftOf(tabChild), rightOf(isApzcEnabled)));
|
||||
arrows.appendChild(makeArrow(leftOf(isApzcEnabled), rightOf(tabGesture)));
|
||||
arrows.appendChild(makeArrow(bottomOf(isApzcEnabled), topOf(childHitTest)));
|
||||
arrows.appendChild(makeVHArrow(bottomOf(tabGesture), leftOf(childHitTest)));
|
||||
arrows.appendChild(makeArrow(rightOf(childHitTest), leftOf(childEsm)));
|
||||
arrows.appendChild(makeArrow(rightOf(childEsm), leftOf(childContent)));
|
||||
arrows.appendChild(makeVHVArrow(midpoint(leftOf(apzGesture), rightOf(apzTransform)), topOf(tabChild), 300));
|
||||
|
||||
document.documentElement.appendChild(makeLegend("Main process input thread", "parentinput"));
|
||||
document.documentElement.appendChild(makeLegend("Main process main thread", "parentmain"));
|
||||
document.documentElement.appendChild(makeLegend("Main process compositor thread", "parentcompositor"));
|
||||
document.documentElement.appendChild(makeLegend("Child process main thread", "childmain"));
|
||||
document.documentElement.appendChild(makeLegend("Undetermined process main thread", "bothmain"));
|
||||
]]></script>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 14 KiB |
@@ -0,0 +1,60 @@
|
||||
This is an overview of the major events in the history of our Layers infrastructure.
|
||||
|
||||
- iPhone released in July 2007 (Built on a toolkit called LayerKit)
|
||||
|
||||
- Core Animation (October 2007) LayerKit was publicly renamed to OS X 10.5
|
||||
|
||||
- Webkit CSS 3d transforms (July 2009)
|
||||
|
||||
- Original layers API (March 2010) Introduced the idea of a layer manager that
|
||||
would composite. One of the first use cases for this was hardware accelerated
|
||||
YUV conversion for video.
|
||||
|
||||
- Retained layers (July 7 2010 - Bug 564991)
|
||||
This was an important concept that introduced the idea of persisting the layer
|
||||
content across paints in gecko controlled buffers instead of just by the OS. This introduced
|
||||
the concept of buffer rotation to deal with scrolling instead of using the
|
||||
native scrolling APIs like ScrollWindowEx
|
||||
|
||||
- Layers IPC (July 2010 - Bug 570294)
|
||||
This introduced shadow layers and edit lists and was originally done for e10s v1
|
||||
|
||||
- 3d transforms (September 2011 - Bug 505115)
|
||||
|
||||
- OMTC (December 2011 - Bug 711168)
|
||||
This was prototyped on OS X but shipped first for Fennec
|
||||
|
||||
- Tiling v1 (April 2012 - Bug 739679)
|
||||
Originally done for Fennec.
|
||||
This was done to avoid situations where we had to do a bunch of work for
|
||||
scrolling a small amount. i.e. buffer rotation. It allowed us to have a
|
||||
variety of interesting features like progressive painting and lower resolution
|
||||
painting.
|
||||
|
||||
- C++ Async pan zoom controller (July 2012 - Bug 750974)
|
||||
The existing APZ code was in Java for Fennec so this was reimplemented.
|
||||
|
||||
- Streaming WebGL Buffers (February 2013 - Bug 716859)
|
||||
Infrastructure to allow OMTC WebGL and avoid the need to glFinish() every
|
||||
frame.
|
||||
|
||||
- Compositor API (April 2013 - Bug 825928)
|
||||
The planning for this started around November 2012.
|
||||
Layers refactoring created a compositor API that abstracted away the differences between the
|
||||
D3D vs OpenGL. The main piece of API is DrawQuad.
|
||||
|
||||
- Tiling v2 (Mar 7 2014 - Bug 963073)
|
||||
Tiling for B2G. This work is mainly porting tiled layers to new textures,
|
||||
implementing double-buffered tiles and implementing a texture client pool, to
|
||||
be used by tiled content clients.
|
||||
|
||||
A large motivation for the pool was the very slow performance of allocating tiles because
|
||||
of the sync messages to the compositor.
|
||||
|
||||
The slow performance of allocating was directly addressed by bug 959089 which allowed us
|
||||
to allocate gralloc buffers without sync messages to the compositor thread.
|
||||
|
||||
- B2G WebGL performance (May 2014 - Bug 1006957, 1001417, 1024144)
|
||||
This work improved the synchronization mechanism between the compositor
|
||||
and the producer.
|
||||
|
||||
@@ -155,6 +155,7 @@ static const char* const sExtensionNames[] = {
|
||||
"GL_NV_geometry_program4",
|
||||
"GL_NV_half_float",
|
||||
"GL_NV_instanced_arrays",
|
||||
"GL_NV_texture_barrier",
|
||||
"GL_NV_transform_feedback",
|
||||
"GL_NV_transform_feedback2",
|
||||
"GL_OES_EGL_image",
|
||||
@@ -1556,6 +1557,14 @@ GLContext::LoadMoreSymbols(const char* prefix, bool trygl)
|
||||
fnLoadForExt(symbols, NV_fence);
|
||||
}
|
||||
|
||||
if (IsExtensionSupported(NV_texture_barrier)) {
|
||||
const SymLoadStruct symbols[] = {
|
||||
{ (PRFuncPtr*) &mSymbols.fTextureBarrier, { "TextureBarrierNV", nullptr } },
|
||||
END_SYMBOLS
|
||||
};
|
||||
fnLoadForExt(symbols, NV_texture_barrier);
|
||||
}
|
||||
|
||||
if (IsSupported(GLFeature::read_buffer)) {
|
||||
const SymLoadStruct symbols[] = {
|
||||
{ (PRFuncPtr*) &mSymbols.fReadBuffer, { "ReadBuffer", nullptr } },
|
||||
|
||||
@@ -478,6 +478,7 @@ public:
|
||||
NV_geometry_program4,
|
||||
NV_half_float,
|
||||
NV_instanced_arrays,
|
||||
NV_texture_barrier,
|
||||
NV_transform_feedback,
|
||||
NV_transform_feedback2,
|
||||
OES_EGL_image,
|
||||
@@ -2879,6 +2880,17 @@ public:
|
||||
AFTER_GL_CALL;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Extension NV_texture_barrier
|
||||
public:
|
||||
void fTextureBarrier()
|
||||
{
|
||||
ASSERT_SYMBOL_PRESENT(fTextureBarrier);
|
||||
BEFORE_GL_CALL;
|
||||
mSymbols.fTextureBarrier();
|
||||
AFTER_GL_CALL;
|
||||
}
|
||||
|
||||
// Core GL & Extension ARB_copy_buffer
|
||||
public:
|
||||
void fCopyBufferSubData(GLenum readtarget, GLenum writetarget,
|
||||
|
||||
@@ -690,6 +690,10 @@ struct GLContextSymbols
|
||||
// APPLE_framebuffer_multisample
|
||||
typedef void (GLAPIENTRY * PFNRESOLVEMULTISAMPLEFRAMEBUFFERAPPLE) (void);
|
||||
PFNRESOLVEMULTISAMPLEFRAMEBUFFERAPPLE fResolveMultisampleFramebufferAPPLE;
|
||||
|
||||
// NV_texture_barrier
|
||||
typedef void (GLAPIENTRY * PFNTEXTUREBARRIERPROC) (void);
|
||||
PFNTEXTUREBARRIERPROC fTextureBarrier;
|
||||
};
|
||||
|
||||
} // namespace gl
|
||||
|
||||
@@ -108,9 +108,52 @@ public:
|
||||
GLLibraryEGL()
|
||||
: mInitialized(false),
|
||||
mEGLLibrary(nullptr),
|
||||
mEGLDisplay(EGL_NO_DISPLAY),
|
||||
mIsANGLE(false),
|
||||
mIsWARP(false)
|
||||
{
|
||||
ClearSymbols();
|
||||
}
|
||||
|
||||
void ClearSymbols() {
|
||||
mSymbols.fGetDisplay = nullptr;
|
||||
mSymbols.fGetPlatformDisplayEXT = nullptr;
|
||||
mSymbols.fTerminate = nullptr;
|
||||
mSymbols.fGetCurrentSurface = nullptr;
|
||||
mSymbols.fGetCurrentContext = nullptr;
|
||||
mSymbols.fMakeCurrent = nullptr;
|
||||
mSymbols.fDestroyContext = nullptr;
|
||||
mSymbols.fCreateContext = nullptr;
|
||||
mSymbols.fDestroySurface = nullptr;
|
||||
mSymbols.fCreateWindowSurface = nullptr;
|
||||
mSymbols.fCreatePbufferSurface = nullptr;
|
||||
mSymbols.fCreatePixmapSurface = nullptr;
|
||||
mSymbols.fBindAPI = nullptr;
|
||||
mSymbols.fInitialize = nullptr;
|
||||
mSymbols.fChooseConfig = nullptr;
|
||||
mSymbols.fGetError = nullptr;
|
||||
mSymbols.fGetConfigAttrib = nullptr;
|
||||
mSymbols.fGetConfigs = nullptr;
|
||||
mSymbols.fWaitNative = nullptr;
|
||||
mSymbols.fGetProcAddress = nullptr;
|
||||
mSymbols.fSwapBuffers = nullptr;
|
||||
mSymbols.fCopyBuffers = nullptr;
|
||||
mSymbols.fQueryString = nullptr;
|
||||
mSymbols.fQueryStringImplementationANDROID = nullptr;
|
||||
mSymbols.fQueryContext = nullptr;
|
||||
mSymbols.fBindTexImage = nullptr;
|
||||
mSymbols.fReleaseTexImage = nullptr;
|
||||
mSymbols.fCreateImage = nullptr;
|
||||
mSymbols.fDestroyImage = nullptr;
|
||||
mSymbols.fLockSurface = nullptr;
|
||||
mSymbols.fUnlockSurface = nullptr;
|
||||
mSymbols.fQuerySurface = nullptr;
|
||||
mSymbols.fQuerySurfacePointerANGLE = nullptr;
|
||||
mSymbols.fCreateSync = nullptr;
|
||||
mSymbols.fDestroySync = nullptr;
|
||||
mSymbols.fClientWaitSync = nullptr;
|
||||
mSymbols.fGetSyncAttrib = nullptr;
|
||||
mSymbols.fDupNativeFenceFDANDROID = nullptr;
|
||||
}
|
||||
|
||||
void InitClientExtensions();
|
||||
|
||||
@@ -854,7 +854,7 @@ DrawBuffer::Create(GLContext* const gl,
|
||||
|
||||
DrawBuffer::~DrawBuffer()
|
||||
{
|
||||
if(!mGL->MakeCurrent())
|
||||
if (!mGL->MakeCurrent())
|
||||
return;
|
||||
|
||||
GLuint fb = mFB;
|
||||
@@ -932,7 +932,7 @@ ReadBuffer::Create(GLContext* gl,
|
||||
|
||||
ReadBuffer::~ReadBuffer()
|
||||
{
|
||||
if(!mGL->MakeCurrent())
|
||||
if (!mGL->MakeCurrent())
|
||||
return;
|
||||
|
||||
GLuint fb = mFB;
|
||||
|
||||
+30
-7
@@ -32,13 +32,36 @@ namespace gl {
|
||||
class GLXLibrary
|
||||
{
|
||||
public:
|
||||
GLXLibrary() : mInitialized(false), mTriedInitializing(false),
|
||||
mUseTextureFromPixmap(false), mDebug(false),
|
||||
mHasRobustness(false), mHasCreateContextAttribs(false),
|
||||
mIsATI(false), mIsNVIDIA(false),
|
||||
mClientIsMesa(false), mGLXMajorVersion(0),
|
||||
mGLXMinorVersion(0),
|
||||
mOGLLibrary(nullptr) {}
|
||||
MOZ_CONSTEXPR GLXLibrary()
|
||||
: xDestroyContextInternal(nullptr)
|
||||
, xMakeCurrentInternal(nullptr)
|
||||
, xGetCurrentContextInternal(nullptr)
|
||||
, xGetProcAddressInternal(nullptr)
|
||||
, xChooseFBConfigInternal(nullptr)
|
||||
, xGetFBConfigsInternal(nullptr)
|
||||
, xCreateNewContextInternal(nullptr)
|
||||
, xGetFBConfigAttribInternal(nullptr)
|
||||
, xSwapBuffersInternal(nullptr)
|
||||
, xQueryExtensionsStringInternal(nullptr)
|
||||
, xGetClientStringInternal(nullptr)
|
||||
, xQueryServerStringInternal(nullptr)
|
||||
, xCreatePixmapInternal(nullptr)
|
||||
, xCreateGLXPixmapWithConfigInternal(nullptr)
|
||||
, xDestroyPixmapInternal(nullptr)
|
||||
, xQueryVersionInternal(nullptr)
|
||||
, xBindTexImageInternal(nullptr)
|
||||
, xReleaseTexImageInternal(nullptr)
|
||||
, xWaitGLInternal(nullptr)
|
||||
, xWaitXInternal(nullptr)
|
||||
, xCreateContextAttribsInternal(nullptr)
|
||||
, mInitialized(false), mTriedInitializing(false)
|
||||
, mUseTextureFromPixmap(false), mDebug(false)
|
||||
, mHasRobustness(false), mHasCreateContextAttribs(false)
|
||||
, mIsATI(false), mIsNVIDIA(false)
|
||||
, mClientIsMesa(false), mGLXMajorVersion(0)
|
||||
, mGLXMinorVersion(0)
|
||||
, mOGLLibrary(nullptr)
|
||||
{}
|
||||
|
||||
void xDestroyContext(Display* display, GLXContext context);
|
||||
Bool xMakeCurrent(Display* display,
|
||||
|
||||
@@ -39,7 +39,7 @@ SharedSurface_EGLImage::Create(GLContext* prodGL,
|
||||
return Move(ret);
|
||||
}
|
||||
|
||||
EGLClientBuffer buffer = reinterpret_cast<EGLClientBuffer>(prodTex);
|
||||
EGLClientBuffer buffer = reinterpret_cast<EGLClientBuffer>(uintptr_t(prodTex));
|
||||
EGLImage image = egl->fCreateImage(egl->Display(), context,
|
||||
LOCAL_EGL_GL_TEXTURE_2D, buffer,
|
||||
nullptr);
|
||||
|
||||
@@ -906,7 +906,7 @@ struct ParamTraits<mozilla::StereoMode>
|
||||
: public ContiguousEnumSerializer<
|
||||
mozilla::StereoMode,
|
||||
mozilla::StereoMode::MONO,
|
||||
mozilla::StereoMode::TOP_BOTTOM>
|
||||
mozilla::StereoMode::MAX>
|
||||
{};
|
||||
|
||||
template <>
|
||||
|
||||
@@ -99,7 +99,8 @@ enum class StereoMode {
|
||||
LEFT_RIGHT,
|
||||
RIGHT_LEFT,
|
||||
BOTTOM_TOP,
|
||||
TOP_BOTTOM
|
||||
TOP_BOTTOM,
|
||||
MAX,
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
@@ -135,7 +135,7 @@ struct LayerPropertiesBase : public LayerProperties
|
||||
, mPostXScale(aLayer->GetPostXScale())
|
||||
, mPostYScale(aLayer->GetPostYScale())
|
||||
, mOpacity(aLayer->GetLocalOpacity())
|
||||
, mUseClipRect(!!aLayer->GetEffectiveClipRect())
|
||||
, mUseClipRect(!!aLayer->GetLocalClipRect())
|
||||
{
|
||||
MOZ_COUNT_CTOR(LayerPropertiesBase);
|
||||
if (aLayer->GetMaskLayer()) {
|
||||
@@ -146,7 +146,7 @@ struct LayerPropertiesBase : public LayerProperties
|
||||
mAncestorMaskLayers.AppendElement(CloneLayerTreePropertiesInternal(maskLayer, true));
|
||||
}
|
||||
if (mUseClipRect) {
|
||||
mClipRect = *aLayer->GetEffectiveClipRect();
|
||||
mClipRect = *aLayer->GetLocalClipRect();
|
||||
}
|
||||
mTransform = GetTransformForInvalidation(aLayer);
|
||||
}
|
||||
@@ -173,7 +173,7 @@ struct LayerPropertiesBase : public LayerProperties
|
||||
bool transformChanged = !mTransform.FuzzyEqual(GetTransformForInvalidation(mLayer)) ||
|
||||
mLayer->GetPostXScale() != mPostXScale ||
|
||||
mLayer->GetPostYScale() != mPostYScale;
|
||||
const Maybe<ParentLayerIntRect>& otherClip = mLayer->GetEffectiveClipRect();
|
||||
const Maybe<ParentLayerIntRect>& otherClip = mLayer->GetLocalClipRect();
|
||||
nsIntRegion result;
|
||||
|
||||
bool ancestorMaskChanged = mAncestorMaskLayers.Length() != mLayer->GetAncestorMaskLayerCount();
|
||||
@@ -191,7 +191,7 @@ struct LayerPropertiesBase : public LayerProperties
|
||||
ancestorMaskChanged ||
|
||||
(mUseClipRect != !!otherClip) ||
|
||||
mLayer->GetLocalOpacity() != mOpacity ||
|
||||
transformChanged)
|
||||
transformChanged)
|
||||
{
|
||||
aGeometryChanged = true;
|
||||
result = OldTransformedBounds();
|
||||
@@ -220,7 +220,7 @@ struct LayerPropertiesBase : public LayerProperties
|
||||
if (mUseClipRect && otherClip) {
|
||||
if (!mClipRect.IsEqualInterior(*otherClip)) {
|
||||
aGeometryChanged = true;
|
||||
nsIntRegion tmp;
|
||||
nsIntRegion tmp;
|
||||
tmp.Xor(mClipRect.ToUnknownRect(), otherClip->ToUnknownRect());
|
||||
AddRegion(result, tmp);
|
||||
}
|
||||
@@ -474,7 +474,7 @@ struct ImageLayerProperties : public LayerPropertiesBase
|
||||
bool& aGeometryChanged)
|
||||
{
|
||||
ImageLayer* imageLayer = static_cast<ImageLayer*>(mLayer.get());
|
||||
|
||||
|
||||
if (!imageLayer->GetLocalVisibleRegion().ToUnknownRegion().IsEqual(mVisibleRegion)) {
|
||||
aGeometryChanged = true;
|
||||
IntRect result = NewTransformedBounds();
|
||||
@@ -585,7 +585,7 @@ LayerProperties::CloneFrom(Layer* aRoot)
|
||||
return CloneLayerTreePropertiesInternal(aRoot);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
/* static */ void
|
||||
LayerProperties::ClearInvalidations(Layer *aLayer)
|
||||
{
|
||||
aLayer->ClearInvalidRect();
|
||||
|
||||
+13
-21
@@ -600,7 +600,7 @@ Layer::CanUseOpaqueSurface()
|
||||
// NB: eventually these methods will be defined unconditionally, and
|
||||
// can be moved into Layers.h
|
||||
const Maybe<ParentLayerIntRect>&
|
||||
Layer::GetEffectiveClipRect()
|
||||
Layer::GetLocalClipRect()
|
||||
{
|
||||
if (LayerComposite* shadow = AsLayerComposite()) {
|
||||
return shadow->GetShadowClipRect();
|
||||
@@ -786,7 +786,7 @@ Layer::CalculateScissorRect(const RenderTargetIntRect& aCurrentScissorRect)
|
||||
// ContainerState::SetupScrollingMetadata() may install a clip on
|
||||
// the layer.
|
||||
Layer *clipLayer =
|
||||
containerChild && containerChild->GetEffectiveClipRect() ?
|
||||
containerChild && containerChild->GetLocalClipRect() ?
|
||||
containerChild : this;
|
||||
|
||||
// Establish initial clip rect: it's either the one passed in, or
|
||||
@@ -798,7 +798,7 @@ Layer::CalculateScissorRect(const RenderTargetIntRect& aCurrentScissorRect)
|
||||
currentClip = aCurrentScissorRect;
|
||||
}
|
||||
|
||||
if (!clipLayer->GetEffectiveClipRect()) {
|
||||
if (!clipLayer->GetLocalClipRect()) {
|
||||
return currentClip;
|
||||
}
|
||||
|
||||
@@ -815,7 +815,7 @@ Layer::CalculateScissorRect(const RenderTargetIntRect& aCurrentScissorRect)
|
||||
}
|
||||
|
||||
const RenderTargetIntRect clipRect =
|
||||
ViewAs<RenderTargetPixel>(*clipLayer->GetEffectiveClipRect(),
|
||||
ViewAs<RenderTargetPixel>(*clipLayer->GetLocalClipRect(),
|
||||
PixelCastJustification::RenderTargetIsParentLayerForRoot);
|
||||
if (clipRect.IsEmpty()) {
|
||||
// We might have a non-translation transform in the container so we can't
|
||||
@@ -904,18 +904,10 @@ Layer::GetTransformTyped() const
|
||||
const Matrix4x4
|
||||
Layer::GetLocalTransform()
|
||||
{
|
||||
Matrix4x4 transform;
|
||||
if (LayerComposite* shadow = AsLayerComposite())
|
||||
transform = shadow->GetShadowBaseTransform();
|
||||
return shadow->GetShadowTransform();
|
||||
else
|
||||
transform = mTransform;
|
||||
|
||||
transform.PostScale(GetPostXScale(), GetPostYScale(), 1.0f);
|
||||
if (ContainerLayer* c = AsContainerLayer()) {
|
||||
transform.PreScale(c->GetPreXScale(), c->GetPreYScale(), 1.0f);
|
||||
}
|
||||
|
||||
return transform;
|
||||
return GetTransform();
|
||||
}
|
||||
|
||||
const LayerToParentLayerMatrix4x4
|
||||
@@ -981,7 +973,7 @@ Layer::GetEffectiveOpacity()
|
||||
}
|
||||
return opacity;
|
||||
}
|
||||
|
||||
|
||||
CompositionOp
|
||||
Layer::GetEffectiveMixBlendMode()
|
||||
{
|
||||
@@ -1061,8 +1053,8 @@ Layer::GetVisibleRegionRelativeToRootLayer(nsIntRegion& aResult,
|
||||
|
||||
// If the parent layer clips its lower layers, clip the visible region
|
||||
// we're accumulating.
|
||||
if (layer->GetEffectiveClipRect()) {
|
||||
aResult.AndWith(layer->GetEffectiveClipRect()->ToUnknownRect());
|
||||
if (layer->GetLocalClipRect()) {
|
||||
aResult.AndWith(layer->GetLocalClipRect()->ToUnknownRect());
|
||||
}
|
||||
|
||||
// Now we need to walk across the list of siblings for this parent layer,
|
||||
@@ -1086,7 +1078,7 @@ Layer::GetVisibleRegionRelativeToRootLayer(nsIntRegion& aResult,
|
||||
siblingVisibleRegion.MoveBy(-siblingOffset.x, -siblingOffset.y);
|
||||
// Apply the sibling's clip.
|
||||
// Layer clip rects are not affected by the layer's transform.
|
||||
Maybe<ParentLayerIntRect> clipRect = sibling->GetEffectiveClipRect();
|
||||
Maybe<ParentLayerIntRect> clipRect = sibling->GetLocalClipRect();
|
||||
if (clipRect) {
|
||||
siblingVisibleRegion.AndWith(clipRect->ToUnknownRect());
|
||||
}
|
||||
@@ -1327,7 +1319,7 @@ ContainerLayer::HasMultipleChildren()
|
||||
{
|
||||
uint32_t count = 0;
|
||||
for (Layer* child = GetFirstChild(); child; child = child->GetNextSibling()) {
|
||||
const Maybe<ParentLayerIntRect>& clipRect = child->GetEffectiveClipRect();
|
||||
const Maybe<ParentLayerIntRect>& clipRect = child->GetLocalClipRect();
|
||||
if (clipRect && clipRect->IsEmpty())
|
||||
continue;
|
||||
if (child->GetLocalVisibleRegion().IsEmpty())
|
||||
@@ -1447,7 +1439,7 @@ ContainerLayer::DefaultComputeEffectiveTransforms(const Matrix4x4& aTransformToS
|
||||
|
||||
if (checkClipRect || checkMaskLayers) {
|
||||
for (Layer* child = GetFirstChild(); child; child = child->GetNextSibling()) {
|
||||
const Maybe<ParentLayerIntRect>& clipRect = child->GetEffectiveClipRect();
|
||||
const Maybe<ParentLayerIntRect>& clipRect = child->GetLocalClipRect();
|
||||
/* We can't (easily) forward our transform to children with a non-empty clip
|
||||
* rect since it would need to be adjusted for the transform. See
|
||||
* the calculations performed by CalculateScissorRect above.
|
||||
@@ -1578,7 +1570,7 @@ RefLayer::FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
|
||||
aAttrs = RefLayerAttributes(GetReferentId(), mEventRegionsOverride);
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* StartFrameTimeRecording, together with StopFrameTimeRecording
|
||||
* enable recording of frame intervals.
|
||||
*
|
||||
|
||||
+1
-1
@@ -1505,7 +1505,7 @@ public:
|
||||
// These getters can be used anytime. They return the effective
|
||||
// values that should be used when drawing this layer to screen,
|
||||
// accounting for this layer possibly being a shadow.
|
||||
const Maybe<ParentLayerIntRect>& GetEffectiveClipRect();
|
||||
const Maybe<ParentLayerIntRect>& GetLocalClipRect();
|
||||
const LayerIntRegion& GetLocalVisibleRegion();
|
||||
|
||||
bool Extend3DContext() {
|
||||
|
||||
@@ -79,7 +79,7 @@ FindBackgroundLayer(ReadbackLayer* aLayer, nsIntPoint* aOffset)
|
||||
}
|
||||
|
||||
// cliprects are post-transform
|
||||
const Maybe<ParentLayerIntRect>& clipRect = l->GetEffectiveClipRect();
|
||||
const Maybe<ParentLayerIntRect>& clipRect = l->GetLocalClipRect();
|
||||
if (clipRect && !clipRect->Contains(ViewAs<ParentLayerPixel>(IntRect(transformOffset, aLayer->GetSize()))))
|
||||
return nullptr;
|
||||
|
||||
|
||||
@@ -781,6 +781,16 @@ APZCTreeManager::ReceiveInputEvent(InputData& aEvent,
|
||||
return result;
|
||||
}
|
||||
|
||||
// If/when we enable support for pan inputs off-main-thread, we'll need
|
||||
// to duplicate this EventStateManager code or something. See the other
|
||||
// call to GetUserPrefsForWheelEvent in this file for why these fields
|
||||
// are stored separately.
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
WidgetWheelEvent wheelEvent = panInput.ToWidgetWheelEvent(nullptr);
|
||||
EventStateManager::GetUserPrefsForWheelEvent(&wheelEvent,
|
||||
&panInput.mUserDeltaMultiplierX,
|
||||
&panInput.mUserDeltaMultiplierY);
|
||||
|
||||
RefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(panInput.mPanStartPoint,
|
||||
&hitResult);
|
||||
if (apzc) {
|
||||
|
||||
@@ -1750,7 +1750,7 @@ AsyncPanZoomController::CanScroll(const InputData& aEvent) const
|
||||
delta = GetScrollWheelDelta(aEvent.AsScrollWheelInput());
|
||||
} else if (aEvent.mInputType == PANGESTURE_INPUT) {
|
||||
const PanGestureInput& panInput = aEvent.AsPanGestureInput();
|
||||
delta = ToParentLayerCoordinates(panInput.mPanDisplacement, panInput.mPanStartPoint);
|
||||
delta = ToParentLayerCoordinates(panInput.UserMultipliedPanDisplacement(), panInput.mPanStartPoint);
|
||||
}
|
||||
if (!delta.x && !delta.y) {
|
||||
return false;
|
||||
@@ -1896,6 +1896,7 @@ nsEventStatus AsyncPanZoomController::OnScrollWheel(const ScrollWheelInput& aEve
|
||||
// If we're scroll snapping, use a smooth scroll animation to get
|
||||
// the desired physics. Note that SmoothScrollTo() will re-use an
|
||||
// existing smooth scroll animation if there is one.
|
||||
APZC_LOG("%p wheel scrolling to snap point %s\n", this, Stringify(startPosition).c_str());
|
||||
SmoothScrollTo(startPosition);
|
||||
break;
|
||||
}
|
||||
@@ -2018,19 +2019,27 @@ nsEventStatus AsyncPanZoomController::OnPan(const PanGestureInput& aEvent, bool
|
||||
return OnPanBegin(aEvent);
|
||||
}
|
||||
|
||||
// Note that there is a multiplier that applies onto the "physical" pan
|
||||
// displacement (how much the user's fingers moved) that produces the "logical"
|
||||
// pan displacement (how much the page should move). For some of the code
|
||||
// below it makes more sense to use the physical displacement rather than
|
||||
// the logical displacement, and vice-versa.
|
||||
ScreenPoint physicalPanDisplacement = aEvent.mPanDisplacement;
|
||||
ParentLayerPoint logicalPanDisplacement = aEvent.UserMultipliedLocalPanDisplacement();
|
||||
|
||||
// We need to update the axis velocity in order to get a useful display port
|
||||
// size and position. We need to do so even if this is a momentum pan (i.e.
|
||||
// aFingersOnTouchpad == false); in that case the "with touch" part is not
|
||||
// really appropriate, so we may want to rethink this at some point.
|
||||
mX.UpdateWithTouchAtDevicePoint(aEvent.mLocalPanStartPoint.x, aEvent.mLocalPanDisplacement.x, aEvent.mTime);
|
||||
mY.UpdateWithTouchAtDevicePoint(aEvent.mLocalPanStartPoint.y, aEvent.mLocalPanDisplacement.y, aEvent.mTime);
|
||||
mX.UpdateWithTouchAtDevicePoint(aEvent.mLocalPanStartPoint.x, logicalPanDisplacement.x, aEvent.mTime);
|
||||
mY.UpdateWithTouchAtDevicePoint(aEvent.mLocalPanStartPoint.y, logicalPanDisplacement.y, aEvent.mTime);
|
||||
|
||||
HandlePanningUpdate(aEvent.mPanDisplacement);
|
||||
HandlePanningUpdate(physicalPanDisplacement);
|
||||
|
||||
mozilla::Telemetry::Accumulate(mozilla::Telemetry::SCROLL_INPUT_METHODS,
|
||||
(uint32_t) ScrollInputMethod::ApzPanGesture);
|
||||
|
||||
ScreenPoint panDistance(fabs(aEvent.mPanDisplacement.x), fabs(aEvent.mPanDisplacement.y));
|
||||
ScreenPoint panDistance(fabs(physicalPanDisplacement.x), fabs(physicalPanDisplacement.y));
|
||||
OverscrollHandoffState handoffState(
|
||||
*CurrentPanGestureBlock()->GetOverscrollHandoffChain(),
|
||||
panDistance,
|
||||
@@ -2044,7 +2053,7 @@ nsEventStatus AsyncPanZoomController::OnPan(const PanGestureInput& aEvent, bool
|
||||
// the motion of the scrolled contents, not of the scroll position, they need
|
||||
// to move in the opposite direction of the pan displacement.
|
||||
ParentLayerPoint startPoint = aEvent.mLocalPanStartPoint;
|
||||
ParentLayerPoint endPoint = aEvent.mLocalPanStartPoint - aEvent.mLocalPanDisplacement;
|
||||
ParentLayerPoint endPoint = aEvent.mLocalPanStartPoint - logicalPanDisplacement;
|
||||
CallDispatchScroll(startPoint, endPoint, handoffState);
|
||||
|
||||
return nsEventStatus_eConsumeNoDefault;
|
||||
@@ -3852,11 +3861,14 @@ AsyncPanZoomController::GetZoomConstraints() const
|
||||
|
||||
void AsyncPanZoomController::PostDelayedTask(already_AddRefed<Runnable> aTask, int aDelayMs) {
|
||||
APZThreadUtils::AssertOnControllerThread();
|
||||
RefPtr<Runnable> task = aTask;
|
||||
RefPtr<GeckoContentController> controller = GetGeckoContentController();
|
||||
if (controller) {
|
||||
controller->PostDelayedTask(Move(aTask), aDelayMs);
|
||||
controller->PostDelayedTask(task.forget(), aDelayMs);
|
||||
}
|
||||
// XXX khuey what is supposed to happen if there's no controller? We were leaking tasks ...
|
||||
// If there is no controller, that means this APZC has been destroyed, and
|
||||
// we probably don't need to run the task. It will get destroyed when the
|
||||
// RefPtr goes out of scope.
|
||||
}
|
||||
|
||||
bool AsyncPanZoomController::Matches(const ScrollableLayerGuid& aGuid)
|
||||
@@ -3965,6 +3977,7 @@ void AsyncPanZoomController::ScrollSnapNear(const CSSPoint& aDestination) {
|
||||
if (Maybe<CSSPoint> snapPoint =
|
||||
FindSnapPointNear(aDestination, nsIScrollableFrame::DEVICE_PIXELS)) {
|
||||
if (*snapPoint != mFrameMetrics.GetScrollOffset()) {
|
||||
APZC_LOG("%p smooth scrolling to snap point %s\n", this, Stringify(*snapPoint).c_str());
|
||||
SmoothScrollTo(*snapPoint);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -400,7 +400,7 @@ InputQueue::CancelAnimationsForNewBlock(CancelableBlockState* aBlock)
|
||||
// being processed) we only do this animation-cancellation if there are no older
|
||||
// touch blocks still in the queue.
|
||||
if (aBlock == CurrentBlock()) {
|
||||
aBlock->GetOverscrollHandoffChain()->CancelAnimations(ExcludeOverscroll);
|
||||
aBlock->GetOverscrollHandoffChain()->CancelAnimations(ExcludeOverscroll | ScrollSnap);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,10 @@ WheelScrollAnimation::DoSample(FrameMetrics& aFrameMetrics, const TimeDuration&
|
||||
ParentLayerPoint displacement =
|
||||
(CSSPoint::FromAppUnits(sampledDest) - aFrameMetrics.GetScrollOffset()) * zoom;
|
||||
|
||||
if (!IsZero(displacement)) {
|
||||
if (finished) {
|
||||
mApzc.mX.SetVelocity(0);
|
||||
mApzc.mY.SetVelocity(0);
|
||||
} else if (!IsZero(displacement)) {
|
||||
// Velocity is measured in ParentLayerCoords / Milliseconds
|
||||
float xVelocity = displacement.x / aDelta.ToMilliseconds();
|
||||
float yVelocity = displacement.y / aDelta.ToMilliseconds();
|
||||
|
||||
@@ -66,6 +66,11 @@ private:
|
||||
&(gfxPrefs::Set##prefBase), \
|
||||
prefValue)
|
||||
|
||||
static TimeStamp GetStartupTime() {
|
||||
static TimeStamp sStartupTime = TimeStamp::Now();
|
||||
return sStartupTime;
|
||||
}
|
||||
|
||||
class MockContentController : public GeckoContentController {
|
||||
public:
|
||||
MOCK_METHOD1(RequestContentRepaint, void(const FrameMetrics&));
|
||||
@@ -85,7 +90,7 @@ public:
|
||||
class MockContentControllerDelayed : public MockContentController {
|
||||
public:
|
||||
MockContentControllerDelayed()
|
||||
: mTime(TimeStamp::Now())
|
||||
: mTime(GetStartupTime())
|
||||
{
|
||||
}
|
||||
|
||||
@@ -265,11 +270,6 @@ public:
|
||||
mWaitForMainThread = true;
|
||||
}
|
||||
|
||||
static TimeStamp GetStartupTime() {
|
||||
static TimeStamp sStartupTime = TimeStamp::Now();
|
||||
return sStartupTime;
|
||||
}
|
||||
|
||||
private:
|
||||
bool mWaitForMainThread;
|
||||
MockContentControllerDelayed* mcc;
|
||||
@@ -300,7 +300,7 @@ TestFrameMetrics()
|
||||
uint32_t
|
||||
MillisecondsSinceStartup(TimeStamp aTime)
|
||||
{
|
||||
return (aTime - TestAsyncPanZoomController::GetStartupTime()).ToMilliseconds();
|
||||
return (aTime - GetStartupTime()).ToMilliseconds();
|
||||
}
|
||||
|
||||
#endif // mozilla_layers_APZTestCommon_h
|
||||
|
||||
@@ -605,6 +605,25 @@ TEST_F(APZCGestureDetectorTester, LongPressInterruptedByWheel) {
|
||||
Wheel(apzc, ScreenIntPoint(10, 10), ScreenPoint(0, -10), mcc->Time(), &wheelBlockId);
|
||||
EXPECT_NE(touchBlockId, wheelBlockId);
|
||||
mcc->AdvanceByMillis(1000);
|
||||
|
||||
|
||||
}
|
||||
|
||||
TEST_F(APZCGestureDetectorTester, TapTimeoutInterruptedByWheel) {
|
||||
// In this test, even though the wheel block comes right after the tap, the
|
||||
// tap should still be dispatched because it completes fully before the wheel
|
||||
// block arrived.
|
||||
EXPECT_CALL(*mcc, HandleSingleTap(CSSPoint(10, 10), 0, apzc->GetGuid())).Times(1);
|
||||
|
||||
// We make the APZC zoomable so the gesture detector needs to wait to
|
||||
// distinguish between tap and double-tap. During that timeout is when we
|
||||
// insert the wheel event.
|
||||
MakeApzcZoomable();
|
||||
|
||||
uint64_t touchBlockId = 0;
|
||||
uint64_t wheelBlockId = 0;
|
||||
Tap(apzc, ScreenIntPoint(10, 10), mcc, TimeDuration::FromMilliseconds(100),
|
||||
nullptr, &touchBlockId);
|
||||
mcc->AdvanceByMillis(10);
|
||||
Wheel(apzc, ScreenIntPoint(10, 10), ScreenPoint(0, -10), mcc->Time(), &wheelBlockId);
|
||||
EXPECT_NE(touchBlockId, wheelBlockId);
|
||||
while (mcc->RunThroughDelayedTasks());
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
<html>
|
||||
<script>
|
||||
function run() {
|
||||
document.body.classList.toggle('noscroll');
|
||||
document.getElementById('spacer').style.height = '100%';
|
||||
// Scroll to the very end, including any fractional pixels
|
||||
document.body.scrollTop = document.body.scrollTopMax + 1;
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
html, body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: green;
|
||||
}
|
||||
|
||||
.noscroll {
|
||||
overflow: hidden;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
<body onload="run()">
|
||||
<div id="spacer" style="height: 5000px">
|
||||
This is the top of the page.
|
||||
</div>
|
||||
This is the bottom of the page.
|
||||
</body>
|
||||
@@ -0,0 +1,53 @@
|
||||
<html class="reftest-wait">
|
||||
<!--
|
||||
For bug 1266833; syncing the scroll offset to APZ properly when the scroll
|
||||
position is clamped to a smaller value during a frame reconstruction.
|
||||
-->
|
||||
<script>
|
||||
function run() {
|
||||
document.body.scrollTop = document.body.scrollTopMax;
|
||||
|
||||
// Let the scroll position propagate to APZ before we do the frame
|
||||
// reconstruction. Ideally we would wait for flushApzRepaints here but
|
||||
// we don't have access to DOMWindowUtils in a reftest, so we just wait
|
||||
// 100ms to approximate it. With bug 1266833 fixed, this test should
|
||||
// never fail regardless of what this timeout value is.
|
||||
setTimeout(frameReconstruction, 100);
|
||||
}
|
||||
|
||||
function frameReconstruction() {
|
||||
document.body.classList.toggle('noscroll');
|
||||
document.documentElement.classList.toggle('reconstruct-body');
|
||||
document.getElementById('spacer').style.height = '100%';
|
||||
document.documentElement.classList.remove('reftest-wait');
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
html, body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: green;
|
||||
}
|
||||
|
||||
.noscroll {
|
||||
overflow: hidden;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* Toggling this on and off triggers a frame reconstruction on the <body> */
|
||||
html.reconstruct-body::before {
|
||||
top: 0;
|
||||
content: '';
|
||||
display: block;
|
||||
height: 2px;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
z-index: 99;
|
||||
}
|
||||
</style>
|
||||
<body onload="setTimeout(run, 0)">
|
||||
<div id="spacer" style="height: 5000px">
|
||||
This is the top of the page.
|
||||
</div>
|
||||
This is the bottom of the page.
|
||||
</body>
|
||||
@@ -15,3 +15,5 @@ skip-if(!asyncZoom) fuzzy-if(B2G,94,146) == async-scrollbar-zoom-2.html async-sc
|
||||
|
||||
# Meta-viewport tag support
|
||||
skip-if(!asyncZoom) == initial-scale-1.html initial-scale-1-ref.html
|
||||
|
||||
skip-if(!asyncPan) == frame-reconstruction-scroll-clamping.html frame-reconstruction-scroll-clamping-ref.html
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "gfxPrefs.h"
|
||||
#include "LayersLogging.h"
|
||||
#include "mozilla/BasicEvents.h"
|
||||
#include "mozilla/IntegerPrintfMacros.h"
|
||||
#include "mozilla/Move.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/TouchEvents.h"
|
||||
|
||||
@@ -80,23 +80,6 @@ APZThreadUtils::RunOnControllerThread(already_AddRefed<Runnable> aTask)
|
||||
#endif
|
||||
}
|
||||
|
||||
/*static*/ void
|
||||
APZThreadUtils::RunDelayedTaskOnCurrentThread(already_AddRefed<Runnable> aTask,
|
||||
const TimeDuration& aDelay)
|
||||
{
|
||||
if (MessageLoop* messageLoop = MessageLoop::current()) {
|
||||
messageLoop->PostDelayedTask(Move(aTask), aDelay.ToMilliseconds());
|
||||
} else {
|
||||
#ifdef MOZ_ANDROID_APZ
|
||||
// Fennec does not have a MessageLoop::current() on the controller thread.
|
||||
AndroidBridge::Bridge()->PostTaskToUiThread(Move(aTask), aDelay.ToMilliseconds());
|
||||
#else
|
||||
// Other platforms should.
|
||||
MOZ_RELEASE_ASSERT(false, "This non-Fennec platform should have a MessageLoop::current()");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/*static*/ bool
|
||||
APZThreadUtils::IsControllerThread()
|
||||
{
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#define mozilla_layers_APZThreadUtils_h
|
||||
|
||||
#include "base/message_loop.h"
|
||||
#include "mozilla/TimeStamp.h" // for TimeDuration
|
||||
#include "nsITimer.h"
|
||||
|
||||
namespace mozilla {
|
||||
@@ -53,12 +52,6 @@ public:
|
||||
*/
|
||||
static void RunOnControllerThread(already_AddRefed<Runnable> aTask);
|
||||
|
||||
/**
|
||||
* Runs the given task on the current thread after a delay of |aDelay|.
|
||||
*/
|
||||
static void RunDelayedTaskOnCurrentThread(already_AddRefed<Runnable> aTask,
|
||||
const TimeDuration& aDelay);
|
||||
|
||||
/**
|
||||
* Returns true if currently on APZ "controller thread".
|
||||
*/
|
||||
|
||||
@@ -413,7 +413,7 @@ MarkLayersHidden(Layer* aLayer, const IntRect& aClipRect,
|
||||
}
|
||||
|
||||
{
|
||||
const Maybe<ParentLayerIntRect>& clipRect = aLayer->GetEffectiveClipRect();
|
||||
const Maybe<ParentLayerIntRect>& clipRect = aLayer->GetLocalClipRect();
|
||||
if (clipRect) {
|
||||
IntRect cr = clipRect->ToUnknownRect();
|
||||
// clipRect is in the container's coordinate system. Get it into the
|
||||
@@ -492,7 +492,7 @@ ApplyDoubleBuffering(Layer* aLayer, const IntRect& aVisibleRect)
|
||||
IntRect newVisibleRect(aVisibleRect);
|
||||
|
||||
{
|
||||
const Maybe<ParentLayerIntRect>& clipRect = aLayer->GetEffectiveClipRect();
|
||||
const Maybe<ParentLayerIntRect>& clipRect = aLayer->GetLocalClipRect();
|
||||
if (clipRect) {
|
||||
IntRect cr = clipRect->ToUnknownRect();
|
||||
// clipRect is in the container's coordinate system. Get it into the
|
||||
@@ -771,7 +771,7 @@ BasicLayerManager::FlushGroup(PaintLayerContext& aPaintContext, bool aNeedsClipT
|
||||
static void
|
||||
InstallLayerClipPreserves3D(gfxContext* aTarget, Layer* aLayer)
|
||||
{
|
||||
const Maybe<ParentLayerIntRect> &clipRect = aLayer->GetEffectiveClipRect();
|
||||
const Maybe<ParentLayerIntRect> &clipRect = aLayer->GetLocalClipRect();
|
||||
|
||||
if (!clipRect) {
|
||||
return;
|
||||
@@ -823,7 +823,7 @@ BasicLayerManager::PaintLayer(gfxContext* aTarget,
|
||||
|
||||
RenderTraceScope trace("BasicLayerManager::PaintLayer", "707070");
|
||||
|
||||
const Maybe<ParentLayerIntRect>& clipRect = aLayer->GetEffectiveClipRect();
|
||||
const Maybe<ParentLayerIntRect>& clipRect = aLayer->GetLocalClipRect();
|
||||
BasicContainerLayer* container =
|
||||
static_cast<BasicContainerLayer*>(aLayer->AsContainerLayer());
|
||||
bool needsGroup = container && container->UseIntermediateSurface();
|
||||
@@ -871,7 +871,7 @@ BasicLayerManager::PaintLayer(gfxContext* aTarget,
|
||||
// Don't need to clip to visible region again
|
||||
needsClipToVisibleRegion = false;
|
||||
}
|
||||
|
||||
|
||||
if (is2D) {
|
||||
paintLayerContext.AnnotateOpaqueRect();
|
||||
}
|
||||
|
||||
@@ -390,6 +390,9 @@ CanvasClientSharedSurface::UpdateRenderer(gfx::IntSize aSize, Renderer& aRendere
|
||||
}
|
||||
} else {
|
||||
mShSurfClient = gl->Screen()->Front();
|
||||
if (mShSurfClient && mShSurfClient->GetAllocator() != GetForwarder()) {
|
||||
mShSurfClient = CloneSurface(mShSurfClient->Surf(), gl->Screen()->Factory());
|
||||
}
|
||||
if (!mShSurfClient) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -352,10 +352,6 @@ ClientLayerManager::EndTransaction(DrawPaintedLayerCallback aCallback,
|
||||
MakeSnapshotIfRequired();
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < mTexturePools.Length(); i++) {
|
||||
mTexturePools[i]->ReturnDeferredClients();
|
||||
}
|
||||
|
||||
mInTransaction = false;
|
||||
mTransactionStart = TimeStamp();
|
||||
}
|
||||
@@ -432,6 +428,10 @@ ClientLayerManager::DidComposite(uint64_t aTransactionId,
|
||||
for (size_t i = 0; i < mDidCompositeObservers.Length(); i++) {
|
||||
mDidCompositeObservers[i]->DidComposite();
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < mTexturePools.Length(); i++) {
|
||||
mTexturePools[i]->ReturnDeferredClients();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -33,7 +33,7 @@ public:
|
||||
|
||||
// TextureClientAllocator
|
||||
already_AddRefed<TextureClient> GetTextureClient() override;
|
||||
void ReturnTextureClientDeferred(TextureClient* aClient) override {}
|
||||
void ReturnTextureClientDeferred(TextureClient* aClient, gfxSharedReadLock* aLock) override {}
|
||||
void ReportClientLost() override {}
|
||||
|
||||
// ClientTiledLayerBuffer
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user