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:
2024-09-25 09:51:11 +08:00
parent f38f996411
commit 7b6d9cb864
173 changed files with 2972 additions and 1361 deletions
+2 -3
View File
@@ -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);
}
+2 -2
View File
@@ -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;
+1 -1
View File
@@ -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;
+59 -4
View File
@@ -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;
}
+3
View File
@@ -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
+4 -4
View File
@@ -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;' +
+7 -3
View File
@@ -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);
};
};
+32 -24
View File
@@ -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;
}
+24 -2
View File
@@ -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 = [
+1 -1
View File
@@ -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',
+1 -1
View File
@@ -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"
View File
@@ -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>
+59 -48
View File
@@ -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;
}
+26 -13
View File
@@ -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());
+16 -197
View File
@@ -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>
+6 -3
View File
@@ -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);
+1 -1
View File
@@ -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
View File
@@ -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);
}
+3 -3
View File
@@ -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;
}
+2 -1
View File
@@ -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',
+5 -1
View File
@@ -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',
]
+1 -1
View File
@@ -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() << "]";
+10 -4
View File
@@ -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),
+3
View File
@@ -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);
-4
View File
@@ -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
+14 -4
View File
@@ -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
View File
@@ -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, &currentCP, 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
View File
@@ -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();
}
+1 -1
View File
@@ -659,7 +659,7 @@ private:
class RecordedPopLayer : public RecordedDrawingEvent {
public:
RecordedPopLayer(DrawTarget* aDT)
MOZ_IMPLICIT RecordedPopLayer(DrawTarget* aDT)
: RecordedDrawingEvent(POPLAYER, aDT)
{
}
+15 -8
View File
@@ -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
View File
@@ -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:
+31 -1
View File
@@ -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;
+2
View File
@@ -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;
+5 -5
View File
@@ -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;
}
}
+2
View File
@@ -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:
+2 -2
View File
@@ -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
View File
@@ -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.
//
+349
View File
@@ -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

+60
View File
@@ -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.
+9
View File
@@ -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 } },
+12
View File
@@ -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,
+4
View File
@@ -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
+43
View File
@@ -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();
+2 -2
View File
@@ -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
View File
@@ -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,
+1 -1
View File
@@ -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);
+1 -1
View File
@@ -906,7 +906,7 @@ struct ParamTraits<mozilla::StereoMode>
: public ContiguousEnumSerializer<
mozilla::StereoMode,
mozilla::StereoMode::MONO,
mozilla::StereoMode::TOP_BOTTOM>
mozilla::StereoMode::MAX>
{};
template <>
+2 -1
View File
@@ -99,7 +99,8 @@ enum class StereoMode {
LEFT_RIGHT,
RIGHT_LEFT,
BOTTOM_TOP,
TOP_BOTTOM
TOP_BOTTOM,
MAX,
};
} // namespace mozilla
+7 -7
View File
@@ -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
View File
@@ -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
View File
@@ -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() {
+1 -1
View File
@@ -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;
+10
View File
@@ -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) {
+21 -8
View File
@@ -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);
}
}
+1 -1
View File
@@ -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);
}
}
+4 -1
View File
@@ -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();
+7 -7
View File
@@ -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>
+2
View File
@@ -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
+1
View File
@@ -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"
-17
View File
@@ -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
View File
@@ -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".
*/
+5 -5
View File
@@ -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();
}
+3
View File
@@ -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;
}
+4 -4
View File
@@ -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
+1 -1
View File
@@ -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